summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Android.bp17
-rwxr-xr-xapct-tests/perftests/textclassifier/run.sh6
-rw-r--r--apct-tests/perftests/windowmanager/README.md2
-rw-r--r--apct-tests/perftests/windowmanager/src/android/wm/WindowAddRemovePerfTest.java3
-rw-r--r--apex/Android.bp2
-rw-r--r--apex/appsearch/framework/Android.bp2
-rw-r--r--apex/appsearch/framework/jarjar-rules.txt2
-rw-r--r--apex/appsearch/framework/java/android/app/appsearch/AppSearchManager.java18
-rw-r--r--apex/appsearch/framework/java/android/app/appsearch/IAppSearchManager.aidl33
-rw-r--r--apex/appsearch/service/java/com/android/server/appsearch/AppSearchManagerService.java38
-rw-r--r--apex/jobscheduler/framework/java/android/os/DeviceIdleManager.java1
-rw-r--r--apex/jobscheduler/framework/java/android/os/PowerWhitelistManager.java2
-rw-r--r--apex/jobscheduler/service/java/com/android/server/AppStateTrackerImpl.java12
-rw-r--r--apex/jobscheduler/service/java/com/android/server/alarm/Alarm.java10
-rw-r--r--apex/jobscheduler/service/java/com/android/server/alarm/AlarmManagerService.java201
-rw-r--r--api/Android.bp72
-rw-r--r--api/current.txt21
-rw-r--r--api/module-lib-current.txt2
-rw-r--r--api/system-current.txt105
-rw-r--r--api/test-current.txt3389
-rw-r--r--api/test-removed.txt9
-rw-r--r--cmds/idmap2/idmap2d/Idmap2Service.h2
-rw-r--r--cmds/idmap2/include/idmap2/BinaryStreamVisitor.h3
-rw-r--r--cmds/idmap2/include/idmap2/Idmap.h118
-rw-r--r--cmds/idmap2/include/idmap2/PrettyPrintVisitor.h3
-rw-r--r--cmds/idmap2/include/idmap2/RawPrintVisitor.h4
-rw-r--r--cmds/idmap2/include/idmap2/ResourceMapping.h21
-rw-r--r--cmds/idmap2/libidmap2/BinaryStreamVisitor.cpp34
-rw-r--r--cmds/idmap2/libidmap2/Idmap.cpp86
-rw-r--r--cmds/idmap2/libidmap2/PrettyPrintVisitor.cpp65
-rw-r--r--cmds/idmap2/libidmap2/RawPrintVisitor.cpp85
-rw-r--r--cmds/idmap2/libidmap2/ResourceMapping.cpp62
-rw-r--r--cmds/idmap2/tests/BinaryStreamVisitorTests.cpp13
-rw-r--r--cmds/idmap2/tests/Idmap2BinaryTests.cpp8
-rw-r--r--cmds/idmap2/tests/IdmapTests.cpp114
-rw-r--r--cmds/idmap2/tests/PrettyPrintVisitorTests.cpp5
-rw-r--r--cmds/idmap2/tests/RawPrintVisitorTests.cpp24
-rw-r--r--cmds/idmap2/tests/ResourceMappingTests.cpp180
-rw-r--r--cmds/idmap2/tests/TestConstants.h2
-rw-r--r--cmds/idmap2/tests/TestHelpers.h90
-rw-r--r--cmds/statsd/Android.bp24
-rw-r--r--cmds/statsd/src/atoms.proto188
-rw-r--r--cmds/statsd/src/metrics/DurationMetricProducer.cpp95
-rw-r--r--cmds/statsd/src/metrics/DurationMetricProducer.h28
-rw-r--r--cmds/statsd/src/metrics/MetricProducer.h1
-rw-r--r--cmds/statsd/src/metrics/duration_helper/DurationTracker.h10
-rw-r--r--cmds/statsd/src/metrics/parsing_utils/config_update_utils.cpp39
-rw-r--r--cmds/statsd/src/metrics/parsing_utils/metrics_manager_util.cpp238
-rw-r--r--cmds/statsd/src/metrics/parsing_utils/metrics_manager_util.h19
-rw-r--r--cmds/statsd/tests/metrics/parsing_utils/config_update_utils_test.cpp377
-rw-r--r--config/boot-image-profile.txt4
-rw-r--r--core/java/android/accessibilityservice/AccessibilityGestureEvent.java47
-rw-r--r--core/java/android/accessibilityservice/AccessibilityService.java23
-rw-r--r--core/java/android/accessibilityservice/AccessibilityServiceInfo.java16
-rw-r--r--core/java/android/app/ActivityManager.java15
-rw-r--r--core/java/android/app/ActivityTaskManager.java13
-rw-r--r--core/java/android/app/ActivityView.java29
-rw-r--r--core/java/android/app/AppOpsManager.java132
-rw-r--r--core/java/android/app/IActivityTaskManager.aidl6
-rw-r--r--core/java/android/app/ITaskStackListener.aidl15
-rw-r--r--core/java/android/app/Notification.java39
-rw-r--r--core/java/android/app/NotificationChannel.java4
-rw-r--r--core/java/android/app/NotificationManager.java6
-rw-r--r--core/java/android/app/RuntimeAppOpAccessMessage.java2
-rw-r--r--core/java/android/app/StatusBarManager.java9
-rw-r--r--core/java/android/app/SystemServiceRegistry.java4
-rw-r--r--core/java/android/app/TaskStackListener.java8
-rw-r--r--core/java/android/app/UiModeManager.java1
-rw-r--r--core/java/android/app/WallpaperManager.java1
-rw-r--r--core/java/android/app/admin/DevicePolicyManager.java18
-rw-r--r--core/java/android/app/assist/AssistStructure.java2
-rw-r--r--core/java/android/app/backup/BackupManager.java6
-rw-r--r--core/java/android/app/prediction/AppPredictionContext.java4
-rw-r--r--core/java/android/app/prediction/AppPredictionManager.java2
-rw-r--r--core/java/android/app/prediction/AppPredictionSessionId.java2
-rw-r--r--core/java/android/app/prediction/AppPredictor.java1
-rw-r--r--core/java/android/app/prediction/AppTarget.java5
-rw-r--r--core/java/android/app/prediction/AppTargetEvent.java3
-rw-r--r--core/java/android/app/prediction/AppTargetId.java3
-rw-r--r--core/java/android/app/role/OnRoleHoldersChangedListener.java2
-rw-r--r--core/java/android/app/role/RoleManager.java12
-rw-r--r--core/java/android/app/servertransaction/ClientTransaction.java2
-rw-r--r--core/java/android/app/slice/SliceProvider.java2
-rw-r--r--core/java/android/app/usage/CacheQuotaHint.java2
-rw-r--r--core/java/android/bluetooth/BluetoothHeadset.java2
-rw-r--r--core/java/android/companion/CompanionDeviceManager.java2
-rw-r--r--core/java/android/companion/ICompanionDeviceDiscoveryService.aidl2
-rw-r--r--core/java/android/content/ApexEnvironment.java2
-rw-r--r--core/java/android/content/ContentProviderClient.java2
-rw-r--r--core/java/android/content/ContentProviderOperation.java12
-rw-r--r--core/java/android/content/ContentProviderResult.java8
-rw-r--r--core/java/android/content/ContentResolver.java2
-rw-r--r--core/java/android/content/Context.java12
-rw-r--r--core/java/android/content/Intent.java32
-rw-r--r--core/java/android/content/SyncResult.java2
-rw-r--r--core/java/android/content/integrity/AppIntegrityManager.java1
-rw-r--r--core/java/android/content/integrity/AtomicFormula.java19
-rw-r--r--core/java/android/content/integrity/CompoundFormula.java14
-rw-r--r--core/java/android/content/integrity/IntegrityFormula.java2
-rw-r--r--core/java/android/content/integrity/IntegrityUtils.java2
-rw-r--r--core/java/android/content/integrity/Rule.java4
-rw-r--r--core/java/android/content/integrity/RuleSet.java2
-rw-r--r--core/java/android/content/pm/ApplicationInfo.java1
-rw-r--r--core/java/android/content/pm/PackageInstaller.java16
-rw-r--r--core/java/android/content/pm/PackageManager.java68
-rw-r--r--core/java/android/content/pm/PermissionInfo.java66
-rw-r--r--core/java/android/content/res/CompatibilityInfo.java29
-rw-r--r--core/java/android/content/rollback/PackageRollbackInfo.java3
-rw-r--r--core/java/android/content/rollback/RollbackInfo.java3
-rw-r--r--core/java/android/content/rollback/RollbackManager.java3
-rw-r--r--core/java/android/database/CursorWindow.java4
-rw-r--r--core/java/android/database/DatabaseUtils.java6
-rw-r--r--core/java/android/database/sqlite/SQLiteConnection.java32
-rw-r--r--core/java/android/database/sqlite/SQLiteCursor.java2
-rw-r--r--core/java/android/database/sqlite/SQLiteDatabase.java4
-rw-r--r--core/java/android/hardware/Sensor.java2
-rw-r--r--core/java/android/hardware/SensorEvent.java2
-rw-r--r--core/java/android/hardware/biometrics/BiometricConstants.java16
-rw-r--r--core/java/android/hardware/biometrics/BiometricFingerprintConstants.java39
-rw-r--r--core/java/android/hardware/biometrics/BiometricTestSession.java15
-rw-r--r--core/java/android/hardware/biometrics/ITestSession.aidl4
-rw-r--r--core/java/android/hardware/camera2/CameraDevice.java5
-rw-r--r--core/java/android/hardware/camera2/params/ColorSpaceTransform.java4
-rw-r--r--core/java/android/hardware/display/AmbientBrightnessDayStats.java2
-rw-r--r--core/java/android/hardware/display/BrightnessChangeEvent.java2
-rw-r--r--core/java/android/hardware/display/BrightnessConfiguration.java2
-rw-r--r--core/java/android/hardware/display/BrightnessCorrection.java2
-rw-r--r--core/java/android/hardware/display/DisplayManager.java6
-rw-r--r--core/java/android/hardware/display/DisplayManagerInternal.java6
-rw-r--r--core/java/android/hardware/hdmi/HdmiControlManager.java2
-rw-r--r--core/java/android/hardware/hdmi/HdmiDeviceInfo.java2
-rw-r--r--core/java/android/hardware/hdmi/HdmiPortInfo.java4
-rw-r--r--core/java/android/hardware/hdmi/HdmiSwitchClient.java2
-rw-r--r--core/java/android/hardware/lights/Light.java2
-rw-r--r--core/java/android/hardware/lights/LightState.java2
-rw-r--r--core/java/android/hardware/lights/LightsManager.java1
-rw-r--r--core/java/android/hardware/lights/LightsRequest.java2
-rw-r--r--core/java/android/hardware/soundtrigger/SoundTrigger.java1
-rw-r--r--core/java/android/metrics/LogMaker.java2
-rw-r--r--core/java/android/metrics/MetricsReader.java2
-rw-r--r--core/java/android/net/CaptivePortal.java8
-rw-r--r--core/java/android/net/CaptivePortalData.java2
-rw-r--r--core/java/android/net/ConnectivityManager.java3
-rw-r--r--core/java/android/net/EthernetManager.java1
-rw-r--r--core/java/android/net/IpPrefix.java3
-rw-r--r--core/java/android/net/IpSecAlgorithm.java16
-rw-r--r--core/java/android/net/LinkAddress.java12
-rw-r--r--core/java/android/net/LinkProperties.java100
-rw-r--r--core/java/android/net/Network.java4
-rw-r--r--core/java/android/net/NetworkCapabilities.java5
-rw-r--r--core/java/android/net/NetworkStack.java3
-rw-r--r--core/java/android/net/RouteInfo.java6
-rw-r--r--core/java/android/net/StaticIpConfiguration.java2
-rw-r--r--core/java/android/net/apf/ApfCapabilities.java2
-rw-r--r--core/java/android/net/metrics/ApfProgramEvent.java2
-rw-r--r--core/java/android/net/metrics/ApfStats.java3
-rw-r--r--core/java/android/net/metrics/DhcpClientEvent.java2
-rw-r--r--core/java/android/net/metrics/DhcpErrorEvent.java2
-rw-r--r--core/java/android/net/metrics/IpConnectivityLog.java3
-rw-r--r--core/java/android/net/metrics/IpManagerEvent.java2
-rw-r--r--core/java/android/net/metrics/IpReachabilityEvent.java2
-rw-r--r--core/java/android/net/metrics/NetworkEvent.java2
-rw-r--r--core/java/android/net/metrics/RaEvent.java2
-rw-r--r--core/java/android/net/metrics/ValidationProbeEvent.java2
-rw-r--r--core/java/android/net/util/SocketUtils.java2
-rw-r--r--core/java/android/os/BatteryManager.java2
-rw-r--r--core/java/android/os/BatteryStats.java27
-rw-r--r--core/java/android/os/Binder.java1
-rw-r--r--core/java/android/os/BugreportManager.java3
-rw-r--r--core/java/android/os/BugreportParams.java2
-rw-r--r--core/java/android/os/Debug.java6
-rw-r--r--core/java/android/os/Environment.java5
-rw-r--r--core/java/android/os/FileObserver.java13
-rw-r--r--core/java/android/os/FileUtils.java56
-rw-r--r--core/java/android/os/GraphicsEnvironment.java20
-rw-r--r--core/java/android/os/HidlMemory.java2
-rw-r--r--core/java/android/os/HwBinder.java2
-rw-r--r--core/java/android/os/HwBlob.java2
-rw-r--r--core/java/android/os/HwParcel.java2
-rw-r--r--core/java/android/os/IHwBinder.java2
-rw-r--r--core/java/android/os/IHwInterface.java2
-rw-r--r--core/java/android/os/IncidentManager.java4
-rw-r--r--core/java/android/os/IncidentReportArgs.java2
-rw-r--r--core/java/android/os/NativeHandle.java2
-rw-r--r--core/java/android/os/Parcel.java10
-rw-r--r--core/java/android/os/Parcelable.java4
-rw-r--r--core/java/android/os/ParcelableHolder.java54
-rw-r--r--core/java/android/os/PowerManager.java8
-rw-r--r--core/java/android/os/RemoteCallback.java2
-rw-r--r--core/java/android/os/StrictMode.java45
-rw-r--r--core/java/android/os/SystemConfigManager.java2
-rw-r--r--core/java/android/os/SystemProperties.java7
-rw-r--r--core/java/android/os/UserHandle.java7
-rw-r--r--core/java/android/os/UserManager.java49
-rw-r--r--core/java/android/os/Vibrator.java6
-rw-r--r--core/java/android/os/WorkSource.java6
-rw-r--r--core/java/android/os/image/DynamicSystemClient.java6
-rw-r--r--core/java/android/os/incremental/IIncrementalService.aidl10
-rw-r--r--core/java/android/os/incremental/IStorageHealthListener.aidl10
-rw-r--r--core/java/android/os/incremental/IncrementalManager.java37
-rw-r--r--core/java/android/os/incremental/IncrementalStorage.java27
-rw-r--r--core/java/android/os/storage/StorageManager.java2
-rw-r--r--core/java/android/permission/PermissionControllerManager.java1
-rw-r--r--core/java/android/permission/PermissionManager.java19
-rw-r--r--core/java/android/permission/RuntimePermissionPresentationInfo.java2
-rw-r--r--core/java/android/provider/DeviceConfig.java25
-rw-r--r--core/java/android/provider/DocumentsContract.java3
-rw-r--r--core/java/android/provider/Settings.java53
-rw-r--r--core/java/android/provider/Telephony.java1
-rw-r--r--core/java/android/service/appprediction/AppPredictionService.java2
-rw-r--r--core/java/android/service/autofill/AutofillFieldClassificationService.java3
-rw-r--r--core/java/android/service/autofill/BatchUpdates.java2
-rw-r--r--core/java/android/service/autofill/CustomDescription.java6
-rw-r--r--core/java/android/service/autofill/Dataset.java3
-rw-r--r--core/java/android/service/autofill/InlineSuggestionRenderService.java2
-rw-r--r--core/java/android/service/autofill/SaveInfo.java4
-rw-r--r--core/java/android/service/autofill/UserData.java4
-rw-r--r--core/java/android/service/autofill/Validators.java4
-rw-r--r--core/java/android/service/autofill/augmented/AugmentedAutofillService.java2
-rw-r--r--core/java/android/service/autofill/augmented/FillCallback.java2
-rw-r--r--core/java/android/service/autofill/augmented/FillController.java2
-rw-r--r--core/java/android/service/autofill/augmented/FillResponse.java2
-rw-r--r--core/java/android/service/autofill/augmented/FillWindow.java2
-rw-r--r--core/java/android/service/autofill/augmented/PresentationParams.java3
-rw-r--r--core/java/android/service/contentcapture/ActivityEvent.java2
-rw-r--r--core/java/android/service/contentcapture/ContentCaptureService.java3
-rw-r--r--core/java/android/service/contentcapture/DataShareCallback.java2
-rw-r--r--core/java/android/service/contentcapture/DataShareReadAdapter.java2
-rw-r--r--core/java/android/service/contentcapture/SnapshotData.java2
-rw-r--r--core/java/android/service/notification/Adjustment.java4
-rw-r--r--core/java/android/service/notification/NotificationAssistantService.java2
-rw-r--r--core/java/android/service/notification/NotificationListenerService.java2
-rw-r--r--core/java/android/service/notification/NotificationStats.java2
-rw-r--r--core/java/android/service/notification/SnoozeCriterion.java2
-rw-r--r--core/java/android/service/textclassifier/TextClassifierService.java2
-rw-r--r--core/java/android/service/wallpaper/WallpaperService.java47
-rw-r--r--core/java/android/service/watchdog/ExplicitHealthCheckService.java2
-rw-r--r--core/java/android/telephony/PhoneStateListener.java7
-rw-r--r--core/java/android/text/TextLine.java3
-rw-r--r--core/java/android/text/TextShaper.java6
-rw-r--r--core/java/android/text/TextUtils.java31
-rw-r--r--core/java/android/text/style/LineHeightSpan.java2
-rw-r--r--core/java/android/util/FeatureFlagUtils.java2
-rw-r--r--core/java/android/util/proto/EncodedBuffer.java4
-rw-r--r--core/java/android/util/proto/ProtoInputStream.java7
-rw-r--r--core/java/android/uwb/AngleMeasurement.java149
-rw-r--r--core/java/android/uwb/AngleOfArrivalMeasurement.java114
-rw-r--r--core/java/android/uwb/DistanceMeasurement.java145
-rw-r--r--core/java/android/uwb/RangingMeasurement.java229
-rw-r--r--core/java/android/uwb/RangingParams.java381
-rw-r--r--core/java/android/uwb/RangingReport.java101
-rw-r--r--core/java/android/uwb/RangingSession.java148
-rw-r--r--core/java/android/uwb/UwbManager.java29
-rw-r--r--core/java/android/view/IScrollCaptureCallbacks.aidl (renamed from core/java/android/view/IScrollCaptureController.aidl)21
-rw-r--r--core/java/android/view/IScrollCaptureConnection.aidl (renamed from core/java/android/view/IScrollCaptureClient.aidl)2
-rw-r--r--core/java/android/view/IWindow.aidl6
-rw-r--r--core/java/android/view/IWindowManager.aidl9
-rw-r--r--core/java/android/view/IWindowSession.aidl16
-rw-r--r--core/java/android/view/InsetsAnimationControlImpl.java15
-rw-r--r--core/java/android/view/InsetsAnimationThreadControlRunner.java6
-rw-r--r--core/java/android/view/InsetsController.java13
-rw-r--r--core/java/android/view/InsetsState.java19
-rw-r--r--core/java/android/view/NotificationHeaderView.java54
-rw-r--r--core/java/android/view/ScrollCaptureCallback.java12
-rw-r--r--core/java/android/view/ScrollCaptureConnection.java (renamed from core/java/android/view/ScrollCaptureClient.java)46
-rw-r--r--core/java/android/view/ScrollCaptureSession.java12
-rw-r--r--core/java/android/view/ScrollCaptureTargetResolver.java69
-rw-r--r--core/java/android/view/SurfaceControl.java10
-rw-r--r--core/java/android/view/SurfaceView.java2
-rw-r--r--core/java/android/view/View.java11
-rw-r--r--core/java/android/view/ViewGroup.java5
-rw-r--r--core/java/android/view/ViewRootImpl.java117
-rw-r--r--core/java/android/view/ViewRootInsetsControllerHost.java9
-rw-r--r--core/java/android/view/Window.java11
-rw-r--r--core/java/android/view/WindowInsets.java9
-rw-r--r--core/java/android/view/WindowManager.java37
-rw-r--r--core/java/android/view/WindowManagerImpl.java5
-rw-r--r--core/java/android/view/WindowlessWindowManager.java11
-rw-r--r--core/java/android/view/accessibility/AccessibilityManager.java3
-rw-r--r--core/java/android/view/autofill/AutofillManager.java1
-rw-r--r--core/java/android/view/autofill/AutofillValue.java10
-rw-r--r--core/java/android/view/contentcapture/ContentCaptureContext.java9
-rw-r--r--core/java/android/view/contentcapture/ContentCaptureEvent.java2
-rw-r--r--core/java/android/view/contentcapture/ContentCaptureManager.java1
-rw-r--r--core/java/android/view/contentcapture/ViewNode.java1
-rw-r--r--core/java/android/widget/Editor.java11
-rw-r--r--core/java/android/widget/TextView.java29
-rw-r--r--core/java/android/widget/TextViewOnReceiveContentCallback.java298
-rw-r--r--core/java/android/window/ClientWindowFrames.java20
-rw-r--r--core/java/android/window/ITaskOrganizerController.aidl8
-rw-r--r--core/java/android/window/TaskOrganizer.java2
-rw-r--r--core/java/android/window/VirtualDisplayTaskEmbedder.java12
-rw-r--r--core/java/com/android/internal/BrightnessSynchronizer.java2
-rw-r--r--core/java/com/android/internal/compat/CompatibilityChangeInfo.java39
-rw-r--r--core/java/com/android/internal/compat/IPlatformCompat.aidl2
-rw-r--r--core/java/com/android/internal/config/sysui/SystemUiDeviceConfigFlags.java5
-rw-r--r--core/java/com/android/internal/os/AppIdToPackageMap.java12
-rw-r--r--core/java/com/android/internal/os/BatteryStatsImpl.java2
-rw-r--r--core/java/com/android/internal/os/ZygoteInit.java1
-rw-r--r--core/java/com/android/internal/policy/PhoneWindow.java14
-rw-r--r--core/java/com/android/internal/util/LocalLog.java15
-rw-r--r--core/java/com/android/internal/util/NotificationMessagingUtil.java4
-rw-r--r--core/java/com/android/internal/util/Preconditions.java23
-rw-r--r--core/java/com/android/internal/util/XmlUtils.java6
-rw-r--r--core/java/com/android/internal/view/BaseIWindow.java6
-rw-r--r--core/java/com/android/internal/widget/CachingIconView.java50
-rw-r--r--core/java/com/android/internal/widget/ColoredIconHelper.java57
-rw-r--r--core/java/com/android/internal/widget/NotificationExpandButton.java37
-rw-r--r--core/java/com/android/server/SystemConfig.java2
-rw-r--r--core/jni/android_graphics_BLASTBufferQueue.cpp2
-rw-r--r--core/jni/android_opengl_GLES10.cpp13
-rw-r--r--core/jni/android_opengl_GLES11.cpp4
-rw-r--r--core/jni/android_opengl_GLES11Ext.cpp6
-rw-r--r--core/jni/android_opengl_GLES20.cpp22
-rw-r--r--core/jni/android_opengl_GLES30.cpp18
-rw-r--r--core/jni/android_opengl_GLES32.cpp7
-rw-r--r--core/jni/android_util_Binder.cpp12
-rw-r--r--core/jni/android_view_Surface.cpp2
-rw-r--r--core/jni/com_google_android_gles_jni_GLImpl.cpp17
-rw-r--r--core/jni/core_jni_helpers.h2
-rw-r--r--core/proto/android/server/windowmanagerservice.proto2
-rw-r--r--core/proto/android/service/package.proto12
-rw-r--r--core/proto/android/telephony/enums.proto48
-rw-r--r--core/proto/android/view/enums.proto2
-rw-r--r--core/res/AndroidManifest.xml3
-rw-r--r--core/res/res/layout/notification_material_media_transfer_action.xml39
-rw-r--r--core/res/res/layout/notification_template_header.xml4
-rw-r--r--core/res/res/values-af/strings.xml2
-rw-r--r--core/res/res/values-am/strings.xml2
-rw-r--r--core/res/res/values-ar/strings.xml2
-rw-r--r--core/res/res/values-as/strings.xml2
-rw-r--r--core/res/res/values-az/strings.xml2
-rw-r--r--core/res/res/values-b+sr+Latn/strings.xml2
-rw-r--r--core/res/res/values-be/strings.xml2
-rw-r--r--core/res/res/values-bg/strings.xml1
-rw-r--r--core/res/res/values-bn/strings.xml2
-rw-r--r--core/res/res/values-bs/strings.xml2
-rw-r--r--core/res/res/values-ca/strings.xml2
-rw-r--r--core/res/res/values-cs/strings.xml2
-rw-r--r--core/res/res/values-da/strings.xml2
-rw-r--r--core/res/res/values-de/strings.xml2
-rw-r--r--core/res/res/values-el/strings.xml2
-rw-r--r--core/res/res/values-en-rAU/strings.xml1
-rw-r--r--core/res/res/values-en-rCA/strings.xml1
-rw-r--r--core/res/res/values-en-rGB/strings.xml1
-rw-r--r--core/res/res/values-en-rIN/strings.xml1
-rw-r--r--core/res/res/values-en-rXC/strings.xml1
-rw-r--r--core/res/res/values-es-rUS/strings.xml2
-rw-r--r--core/res/res/values-es/strings.xml2
-rw-r--r--core/res/res/values-et/strings.xml2
-rw-r--r--core/res/res/values-eu/strings.xml2
-rw-r--r--core/res/res/values-fa/strings.xml2
-rw-r--r--core/res/res/values-fi/strings.xml2
-rw-r--r--core/res/res/values-fr-rCA/strings.xml2
-rw-r--r--core/res/res/values-fr/strings.xml2
-rw-r--r--core/res/res/values-gl/strings.xml2
-rw-r--r--core/res/res/values-gu/strings.xml2
-rw-r--r--core/res/res/values-hi/strings.xml2
-rw-r--r--core/res/res/values-hr/strings.xml2
-rw-r--r--core/res/res/values-hu/strings.xml2
-rw-r--r--core/res/res/values-hy/strings.xml2
-rw-r--r--core/res/res/values-in/strings.xml2
-rw-r--r--core/res/res/values-is/strings.xml2
-rw-r--r--core/res/res/values-it/strings.xml2
-rw-r--r--core/res/res/values-iw/strings.xml2
-rw-r--r--core/res/res/values-ja/strings.xml2
-rw-r--r--core/res/res/values-ka/strings.xml1
-rw-r--r--core/res/res/values-kk/strings.xml2
-rw-r--r--core/res/res/values-km/strings.xml2
-rw-r--r--core/res/res/values-kn/strings.xml2
-rw-r--r--core/res/res/values-ko/strings.xml2
-rw-r--r--core/res/res/values-ky/strings.xml2
-rw-r--r--core/res/res/values-lo/strings.xml1
-rw-r--r--core/res/res/values-lt/strings.xml2
-rw-r--r--core/res/res/values-lv/strings.xml2
-rw-r--r--core/res/res/values-mcc310-mnc560-as/strings.xml26
-rw-r--r--core/res/res/values-mk/strings.xml10
-rw-r--r--core/res/res/values-ml/strings.xml2
-rw-r--r--core/res/res/values-mn/strings.xml2
-rw-r--r--core/res/res/values-mr/strings.xml2
-rw-r--r--core/res/res/values-ms/strings.xml2
-rw-r--r--core/res/res/values-my/strings.xml2
-rw-r--r--core/res/res/values-nb/strings.xml2
-rw-r--r--core/res/res/values-ne/strings.xml2
-rw-r--r--core/res/res/values-nl/strings.xml2
-rw-r--r--core/res/res/values-or/strings.xml2
-rw-r--r--core/res/res/values-pa/strings.xml2
-rw-r--r--core/res/res/values-pl/strings.xml2
-rw-r--r--core/res/res/values-pt-rBR/strings.xml1
-rw-r--r--core/res/res/values-pt-rPT/strings.xml1
-rw-r--r--core/res/res/values-pt/strings.xml1
-rw-r--r--core/res/res/values-ro/strings.xml2
-rw-r--r--core/res/res/values-ru/strings.xml2
-rw-r--r--core/res/res/values-si/strings.xml2
-rw-r--r--core/res/res/values-sk/strings.xml2
-rw-r--r--core/res/res/values-sl/strings.xml2
-rw-r--r--core/res/res/values-sq/strings.xml2
-rw-r--r--core/res/res/values-sr/strings.xml2
-rw-r--r--core/res/res/values-sv/strings.xml2
-rw-r--r--core/res/res/values-sw/strings.xml2
-rw-r--r--core/res/res/values-ta/strings.xml2
-rw-r--r--core/res/res/values-te/strings.xml2
-rw-r--r--core/res/res/values-th/strings.xml2
-rw-r--r--core/res/res/values-tl/strings.xml2
-rw-r--r--core/res/res/values-tr/strings.xml2
-rw-r--r--core/res/res/values-uk/strings.xml2
-rw-r--r--core/res/res/values-ur/strings.xml2
-rw-r--r--core/res/res/values-uz/strings.xml2
-rw-r--r--core/res/res/values-vi/strings.xml2
-rw-r--r--core/res/res/values-zh-rCN/strings.xml2
-rw-r--r--core/res/res/values-zh-rHK/strings.xml2
-rw-r--r--core/res/res/values-zh-rTW/strings.xml2
-rw-r--r--core/res/res/values-zu/strings.xml2
-rw-r--r--core/res/res/values/attrs.xml1
-rw-r--r--core/res/res/values/required_apps_managed_device.xml1
-rw-r--r--core/res/res/values/required_apps_managed_profile.xml1
-rw-r--r--core/res/res/values/required_apps_managed_user.xml1
-rw-r--r--core/res/res/values/strings.xml3
-rw-r--r--core/res/res/values/symbols.xml3
-rw-r--r--core/tests/coretests/Android.bp1
-rw-r--r--core/tests/coretests/AndroidManifest.xml11
-rw-r--r--core/tests/coretests/apks/install_decl_perm/AndroidManifest.xml3
-rw-r--r--core/tests/coretests/res/layout/activity_custom_input_connection_edit_text.xml33
-rw-r--r--core/tests/coretests/src/android/text/TextUtilsTest.java26
-rw-r--r--core/tests/coretests/src/android/view/InsetsAnimationControlImplTest.java2
-rw-r--r--core/tests/coretests/src/android/view/ScrollCaptureConnectionTest.java (renamed from core/tests/coretests/src/android/view/ScrollCaptureClientTest.java)97
-rw-r--r--core/tests/coretests/src/android/widget/CustomInputConnectionEditText.java84
-rw-r--r--core/tests/coretests/src/android/widget/CustomInputConnectionEditTextActivity.java34
-rw-r--r--core/tests/coretests/src/android/widget/TextViewOnReceiveContentCallbackTest.java262
-rw-r--r--core/tests/coretests/src/com/android/internal/os/BinderCallsStatsTest.java4
-rw-r--r--data/etc/car/com.android.car.provision.xml2
-rw-r--r--data/etc/car/com.google.android.car.kitchensink.xml3
-rw-r--r--data/etc/platform.xml3
-rw-r--r--data/etc/services.core.protolog.json118
-rw-r--r--errorprone/java/com/google/errorprone/bugpatterns/android/EfficientParcelableChecker.java (renamed from errorprone/java/com/google/errorprone/bugpatterns/android/ParcelablePerformanceChecker.java)4
-rw-r--r--errorprone/java/com/google/errorprone/bugpatterns/android/EfficientStringsChecker.java94
-rw-r--r--errorprone/tests/java/com/google/errorprone/bugpatterns/android/EfficientParcelableCheckerTest.java (renamed from errorprone/tests/java/com/google/errorprone/bugpatterns/android/ParcelablePerformanceCheckerTest.java)4
-rw-r--r--errorprone/tests/java/com/google/errorprone/bugpatterns/android/EfficientStringsCheckerTest.java132
-rw-r--r--graphics/java/android/graphics/Typeface.java2
-rw-r--r--graphics/java/android/graphics/text/MeasuredText.java14
-rw-r--r--graphics/java/android/graphics/text/PositionedGlyphs.java3
-rw-r--r--graphics/java/android/graphics/text/TextRunShaper.java6
-rw-r--r--keystore/java/android/security/keystore/AttestationUtils.java2
-rw-r--r--keystore/java/android/security/keystore/DeviceIdAttestationException.java2
-rw-r--r--libs/WindowManager/Shell/res/raw/wm_shell_protolog.json24
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/FullscreenTaskListener.java20
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/ShellTaskOrganizer.java277
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/common/DisplayImeController.java5
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/common/SystemWindows.java25
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/pip/Pip.java4
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipBoundsHandler.java88
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipBoundsState.java80
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipTaskOrganizer.java60
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipController.java19
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/pip/tv/PipController.java47
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/pip/tv/PipMenuActivity.java4
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/pip/tv/PipNotification.java30
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitScreenTaskOrganizer.java93
-rw-r--r--libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/ShellTaskOrganizerTests.java83
-rw-r--r--libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/pip/PipBoundsHandlerTest.java151
-rw-r--r--libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/pip/PipBoundsStateTest.java110
-rw-r--r--libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/pip/PipTaskOrganizerTest.java (renamed from libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/pip/phone/PipTaskOrganizerTest.java)10
-rw-r--r--libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/pip/phone/PipTouchHandlerTest.java2
-rw-r--r--libs/androidfw/Android.bp24
-rw-r--r--libs/androidfw/AssetManager2.cpp51
-rw-r--r--libs/androidfw/CursorWindow.cpp539
-rw-r--r--libs/androidfw/Idmap.cpp121
-rw-r--r--libs/androidfw/fuzz/cursorwindow_fuzzer/Android.bp31
-rw-r--r--libs/androidfw/fuzz/cursorwindow_fuzzer/corpus/typical.binbin0 -> 292 bytes
-rw-r--r--libs/androidfw/fuzz/cursorwindow_fuzzer/cursorwindow_fuzzer.cpp78
-rw-r--r--libs/androidfw/include/androidfw/CursorWindow.h142
-rw-r--r--libs/androidfw/include/androidfw/Idmap.h36
-rw-r--r--libs/androidfw/include/androidfw/ResourceTypes.h67
-rw-r--r--libs/androidfw/tests/CursorWindow_bench.cpp86
-rw-r--r--libs/androidfw/tests/CursorWindow_test.cpp367
-rw-r--r--libs/androidfw/tests/data/overlay/overlay.apkbin2992 -> 2988 bytes
-rw-r--r--libs/androidfw/tests/data/overlay/overlay.idmapbin1090 -> 1092 bytes
-rw-r--r--location/java/android/location/Geofence.java2
-rw-r--r--location/java/android/location/Location.java3
-rw-r--r--location/java/android/location/LocationManager.java5
-rw-r--r--location/java/android/location/LocationRequest.java30
-rw-r--r--media/Android.bp3
-rw-r--r--media/OWNERS10
-rw-r--r--media/java/android/media/AudioFocusInfo.java2
-rw-r--r--media/java/android/media/AudioManager.java6
-rw-r--r--media/java/android/media/ExifInterface.java17
-rw-r--r--media/java/android/media/MediaMetadataRetriever.java25
-rw-r--r--media/java/android/media/MediaPlayer.java25
-rw-r--r--media/java/android/media/MediaTranscodeManager.java2
-rw-r--r--media/java/android/media/audiopolicy/AudioMix.java2
-rw-r--r--media/java/android/media/audiopolicy/AudioMixingRule.java2
-rw-r--r--media/java/android/media/audiopolicy/AudioPolicy.java5
-rw-r--r--media/java/android/media/musicrecognition/MusicRecognitionManager.java2
-rw-r--r--media/java/android/media/musicrecognition/MusicRecognitionService.java2
-rw-r--r--media/java/android/media/musicrecognition/RecognitionRequest.java3
-rw-r--r--media/java/android/media/tv/tuner/Tuner.java17
-rw-r--r--media/java/android/media/tv/tuner/TunerVersionChecker.java1
-rw-r--r--media/java/android/media/tv/tuner/filter/AvSettings.java208
-rw-r--r--media/java/android/media/tv/tuner/filter/IpFilterConfiguration.java2
-rw-r--r--media/java/android/media/tv/tuner/filter/MediaEvent.java1
-rw-r--r--media/java/android/media/tv/tuner/frontend/DvbsFrontendSettings.java33
-rw-r--r--media/java/android/media/tv/tuner/frontend/FrontendStatus.java379
-rw-r--r--media/java/android/media/tv/tuner/frontend/ScanCallback.java5
-rw-r--r--media/jni/android_media_MediaMetadataRetriever.cpp2
-rw-r--r--media/jni/android_media_tv_Tuner.cpp444
-rw-r--r--media/jni/android_media_tv_Tuner.h9
-rw-r--r--non-updatable-api/current.txt19
-rw-r--r--non-updatable-api/module-lib-current.txt2
-rw-r--r--non-updatable-api/system-current.txt99
-rw-r--r--packages/CarSystemUI/AndroidManifest.xml2
-rw-r--r--packages/CarSystemUI/res/layout/rear_view_camera.xml31
-rw-r--r--packages/CarSystemUI/res/layout/sysui_overlay_window.xml8
-rw-r--r--packages/CarSystemUI/res/values-af/strings.xml2
-rw-r--r--packages/CarSystemUI/res/values-am/strings.xml2
-rw-r--r--packages/CarSystemUI/res/values-ar/strings.xml2
-rw-r--r--packages/CarSystemUI/res/values-as/strings.xml2
-rw-r--r--packages/CarSystemUI/res/values-az/strings.xml2
-rw-r--r--packages/CarSystemUI/res/values-b+sr+Latn/strings.xml2
-rw-r--r--packages/CarSystemUI/res/values-be/strings.xml2
-rw-r--r--packages/CarSystemUI/res/values-bg/strings.xml2
-rw-r--r--packages/CarSystemUI/res/values-bn/strings.xml2
-rw-r--r--packages/CarSystemUI/res/values-bs/strings.xml2
-rw-r--r--packages/CarSystemUI/res/values-ca/strings.xml2
-rw-r--r--packages/CarSystemUI/res/values-cs/strings.xml2
-rw-r--r--packages/CarSystemUI/res/values-da/strings.xml2
-rw-r--r--packages/CarSystemUI/res/values-de/strings.xml2
-rw-r--r--packages/CarSystemUI/res/values-el/strings.xml2
-rw-r--r--packages/CarSystemUI/res/values-en-rAU/strings.xml2
-rw-r--r--packages/CarSystemUI/res/values-en-rCA/strings.xml2
-rw-r--r--packages/CarSystemUI/res/values-en-rGB/strings.xml2
-rw-r--r--packages/CarSystemUI/res/values-en-rIN/strings.xml2
-rw-r--r--packages/CarSystemUI/res/values-en-rXC/strings.xml2
-rw-r--r--packages/CarSystemUI/res/values-es-rUS/strings.xml2
-rw-r--r--packages/CarSystemUI/res/values-es/strings.xml2
-rw-r--r--packages/CarSystemUI/res/values-et/strings.xml2
-rw-r--r--packages/CarSystemUI/res/values-eu/strings.xml2
-rw-r--r--packages/CarSystemUI/res/values-fa/strings.xml2
-rw-r--r--packages/CarSystemUI/res/values-fi/strings.xml2
-rw-r--r--packages/CarSystemUI/res/values-fr-rCA/strings.xml2
-rw-r--r--packages/CarSystemUI/res/values-fr/strings.xml2
-rw-r--r--packages/CarSystemUI/res/values-gl/strings.xml2
-rw-r--r--packages/CarSystemUI/res/values-gu/strings.xml2
-rw-r--r--packages/CarSystemUI/res/values-hi/strings.xml2
-rw-r--r--packages/CarSystemUI/res/values-hr/strings.xml2
-rw-r--r--packages/CarSystemUI/res/values-hu/strings.xml2
-rw-r--r--packages/CarSystemUI/res/values-hy/strings.xml2
-rw-r--r--packages/CarSystemUI/res/values-in/strings.xml2
-rw-r--r--packages/CarSystemUI/res/values-is/strings.xml2
-rw-r--r--packages/CarSystemUI/res/values-it/strings.xml2
-rw-r--r--packages/CarSystemUI/res/values-iw/strings.xml2
-rw-r--r--packages/CarSystemUI/res/values-ja/strings.xml2
-rw-r--r--packages/CarSystemUI/res/values-ka/strings.xml2
-rw-r--r--packages/CarSystemUI/res/values-kk/strings.xml2
-rw-r--r--packages/CarSystemUI/res/values-km/strings.xml2
-rw-r--r--packages/CarSystemUI/res/values-kn/strings.xml2
-rw-r--r--packages/CarSystemUI/res/values-ko/strings.xml2
-rw-r--r--packages/CarSystemUI/res/values-ky/strings.xml2
-rw-r--r--packages/CarSystemUI/res/values-lo/strings.xml2
-rw-r--r--packages/CarSystemUI/res/values-lt/strings.xml2
-rw-r--r--packages/CarSystemUI/res/values-lv/strings.xml2
-rw-r--r--packages/CarSystemUI/res/values-mk/strings.xml2
-rw-r--r--packages/CarSystemUI/res/values-ml/strings.xml2
-rw-r--r--packages/CarSystemUI/res/values-mn/strings.xml2
-rw-r--r--packages/CarSystemUI/res/values-mr/strings.xml2
-rw-r--r--packages/CarSystemUI/res/values-ms/strings.xml2
-rw-r--r--packages/CarSystemUI/res/values-my/strings.xml2
-rw-r--r--packages/CarSystemUI/res/values-nb/strings.xml2
-rw-r--r--packages/CarSystemUI/res/values-ne/strings.xml2
-rw-r--r--packages/CarSystemUI/res/values-nl/strings.xml2
-rw-r--r--packages/CarSystemUI/res/values-or/strings.xml2
-rw-r--r--packages/CarSystemUI/res/values-pa/strings.xml2
-rw-r--r--packages/CarSystemUI/res/values-pl/strings.xml2
-rw-r--r--packages/CarSystemUI/res/values-pt-rPT/strings.xml2
-rw-r--r--packages/CarSystemUI/res/values-pt/strings.xml2
-rw-r--r--packages/CarSystemUI/res/values-ro/strings.xml2
-rw-r--r--packages/CarSystemUI/res/values-ru/strings.xml2
-rw-r--r--packages/CarSystemUI/res/values-si/strings.xml2
-rw-r--r--packages/CarSystemUI/res/values-sk/strings.xml2
-rw-r--r--packages/CarSystemUI/res/values-sl/strings.xml2
-rw-r--r--packages/CarSystemUI/res/values-sq/strings.xml2
-rw-r--r--packages/CarSystemUI/res/values-sr/strings.xml2
-rw-r--r--packages/CarSystemUI/res/values-sv/strings.xml2
-rw-r--r--packages/CarSystemUI/res/values-sw/strings.xml2
-rw-r--r--packages/CarSystemUI/res/values-ta/strings.xml2
-rw-r--r--packages/CarSystemUI/res/values-te/strings.xml2
-rw-r--r--packages/CarSystemUI/res/values-th/strings.xml2
-rw-r--r--packages/CarSystemUI/res/values-tl/strings.xml2
-rw-r--r--packages/CarSystemUI/res/values-tr/strings.xml2
-rw-r--r--packages/CarSystemUI/res/values-uk/strings.xml2
-rw-r--r--packages/CarSystemUI/res/values-ur/strings.xml2
-rw-r--r--packages/CarSystemUI/res/values-uz/strings.xml2
-rw-r--r--packages/CarSystemUI/res/values-vi/strings.xml2
-rw-r--r--packages/CarSystemUI/res/values-zh-rCN/strings.xml2
-rw-r--r--packages/CarSystemUI/res/values-zh-rHK/strings.xml2
-rw-r--r--packages/CarSystemUI/res/values-zh-rTW/strings.xml2
-rw-r--r--packages/CarSystemUI/res/values-zu/strings.xml2
-rw-r--r--packages/CarSystemUI/res/values/colors.xml2
-rw-r--r--packages/CarSystemUI/res/values/config.xml4
-rw-r--r--packages/CarSystemUI/res/values/dimens.xml4
-rw-r--r--packages/CarSystemUI/res/values/strings.xml2
-rw-r--r--packages/CarSystemUI/samples/sample3/rro/Android.bp27
-rw-r--r--packages/CarSystemUI/samples/sample3/rro/AndroidManifest.xml24
-rw-r--r--packages/CarSystemUI/samples/sample3/rro/res/drawable/car_ic_apps.xml25
-rw-r--r--packages/CarSystemUI/samples/sample3/rro/res/drawable/car_ic_home.xml25
-rw-r--r--packages/CarSystemUI/samples/sample3/rro/res/drawable/car_ic_hvac.xml25
-rw-r--r--packages/CarSystemUI/samples/sample3/rro/res/drawable/car_ic_music.xml25
-rw-r--r--packages/CarSystemUI/samples/sample3/rro/res/drawable/car_ic_navigation.xml25
-rw-r--r--packages/CarSystemUI/samples/sample3/rro/res/drawable/car_ic_notification.xml25
-rw-r--r--packages/CarSystemUI/samples/sample3/rro/res/drawable/car_ic_overview.xml26
-rw-r--r--packages/CarSystemUI/samples/sample3/rro/res/drawable/car_ic_phone.xml25
-rw-r--r--packages/CarSystemUI/samples/sample3/rro/res/drawable/system_bar_background.xml21
-rw-r--r--packages/CarSystemUI/samples/sample3/rro/res/layout/car_left_navigation_bar.xml51
-rw-r--r--packages/CarSystemUI/samples/sample3/rro/res/layout/car_navigation_bar.xml122
-rw-r--r--packages/CarSystemUI/samples/sample3/rro/res/values/attrs.xml43
-rw-r--r--packages/CarSystemUI/samples/sample3/rro/res/values/colors.xml19
-rw-r--r--packages/CarSystemUI/samples/sample3/rro/res/values/config.xml57
-rw-r--r--packages/CarSystemUI/samples/sample3/rro/res/values/dimens.xml22
-rw-r--r--packages/CarSystemUI/samples/sample3/rro/res/values/styles.xml30
-rw-r--r--packages/CarSystemUI/samples/sample3/rro/res/xml/car_sysui_overlays.xml75
-rw-r--r--packages/CarSystemUI/src/com/android/systemui/CarGlobalRootComponent.java7
-rw-r--r--packages/CarSystemUI/src/com/android/systemui/CarSystemUIModule.java4
-rw-r--r--packages/CarSystemUI/src/com/android/systemui/car/rvc/RearViewCameraViewController.java141
-rw-r--r--packages/CarSystemUI/src/com/android/systemui/car/rvc/RearViewCameraViewMediator.java121
-rw-r--r--packages/CarSystemUI/src/com/android/systemui/car/window/OverlayWindowModule.java8
-rw-r--r--packages/CarSystemUI/src/com/android/systemui/wmshell/CarWMComponent.java39
-rw-r--r--packages/CarSystemUI/src/com/android/systemui/wmshell/CarWMShellModule.java4
-rw-r--r--packages/CarSystemUI/tests/src/com/android/systemui/car/rvc/RearViewCameraViewControllerTest.java117
-rw-r--r--packages/CarSystemUI/tests/src/com/android/systemui/car/rvc/RearViewCameraViewMediatorTest.java169
-rwxr-xr-xpackages/PackageInstaller/src/com/android/packageinstaller/UninstallerActivity.java5
-rw-r--r--packages/PrintSpooler/res/values-mr/strings.xml2
-rw-r--r--packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java15
-rw-r--r--packages/SettingsProvider/test/src/android/provider/SettingsBackupTest.java14
-rw-r--r--packages/Shell/res/values-mr/strings.xml4
-rw-r--r--packages/Shell/src/com/android/shell/BugreportProgressService.java6
-rw-r--r--packages/SystemUI/Android.bp4
-rw-r--r--packages/SystemUI/AndroidManifest.xml31
-rw-r--r--packages/SystemUI/res-keyguard/font/clock.xml28
-rw-r--r--packages/SystemUI/res-keyguard/layout/keyguard_clock_switch.xml22
-rw-r--r--packages/SystemUI/res/drawable/ic_check_box.xml26
-rw-r--r--packages/SystemUI/res/drawable/ic_check_box_blue_24dp.xml26
-rw-r--r--packages/SystemUI/res/drawable/ic_check_box_outline_24dp.xml26
-rw-r--r--packages/SystemUI/res/drawable/ic_speaker_group_black_24dp.xml31
-rw-r--r--packages/SystemUI/res/layout/global_screenshot.xml4
-rw-r--r--packages/SystemUI/res/layout/media_output_list_item.xml177
-rw-r--r--packages/SystemUI/res/layout/people_space_widget.xml27
-rw-r--r--packages/SystemUI/res/layout/people_space_widget_item.xml59
-rw-r--r--packages/SystemUI/res/layout/qs_footer_impl.xml4
-rw-r--r--packages/SystemUI/res/values-af/strings.xml6
-rw-r--r--packages/SystemUI/res/values-am/strings.xml6
-rw-r--r--packages/SystemUI/res/values-ar/strings.xml6
-rw-r--r--packages/SystemUI/res/values-as/strings.xml6
-rw-r--r--packages/SystemUI/res/values-az/strings.xml6
-rw-r--r--packages/SystemUI/res/values-b+sr+Latn/strings.xml6
-rw-r--r--packages/SystemUI/res/values-be/strings.xml6
-rw-r--r--packages/SystemUI/res/values-bn/strings.xml6
-rw-r--r--packages/SystemUI/res/values-bs/strings.xml6
-rw-r--r--packages/SystemUI/res/values-ca/strings.xml6
-rw-r--r--packages/SystemUI/res/values-cs/strings.xml6
-rw-r--r--packages/SystemUI/res/values-da/strings.xml6
-rw-r--r--packages/SystemUI/res/values-de/strings.xml6
-rw-r--r--packages/SystemUI/res/values-el/strings.xml6
-rw-r--r--packages/SystemUI/res/values-es-rUS/strings.xml6
-rw-r--r--packages/SystemUI/res/values-es/strings.xml6
-rw-r--r--packages/SystemUI/res/values-et/strings.xml6
-rw-r--r--packages/SystemUI/res/values-eu/strings.xml6
-rw-r--r--packages/SystemUI/res/values-fa/strings.xml6
-rw-r--r--packages/SystemUI/res/values-fi/strings.xml6
-rw-r--r--packages/SystemUI/res/values-fr-rCA/strings.xml6
-rw-r--r--packages/SystemUI/res/values-fr/strings.xml6
-rw-r--r--packages/SystemUI/res/values-gl/strings.xml6
-rw-r--r--packages/SystemUI/res/values-gu/strings.xml6
-rw-r--r--packages/SystemUI/res/values-hi/strings.xml6
-rw-r--r--packages/SystemUI/res/values-hr/strings.xml6
-rw-r--r--packages/SystemUI/res/values-hu/strings.xml6
-rw-r--r--packages/SystemUI/res/values-in/strings.xml6
-rw-r--r--packages/SystemUI/res/values-is/strings.xml6
-rw-r--r--packages/SystemUI/res/values-it/strings.xml6
-rw-r--r--packages/SystemUI/res/values-iw/strings.xml6
-rw-r--r--packages/SystemUI/res/values-ja/strings.xml6
-rw-r--r--packages/SystemUI/res/values-kk/strings.xml6
-rw-r--r--packages/SystemUI/res/values-km/strings.xml6
-rw-r--r--packages/SystemUI/res/values-kn/strings.xml6
-rw-r--r--packages/SystemUI/res/values-ko/strings.xml6
-rw-r--r--packages/SystemUI/res/values-ky/strings.xml6
-rw-r--r--packages/SystemUI/res/values-lo/strings.xml2
-rw-r--r--packages/SystemUI/res/values-lt/strings.xml6
-rw-r--r--packages/SystemUI/res/values-lv/strings.xml6
-rw-r--r--packages/SystemUI/res/values-mk/strings.xml6
-rw-r--r--packages/SystemUI/res/values-ml/strings.xml6
-rw-r--r--packages/SystemUI/res/values-mn/strings.xml6
-rw-r--r--packages/SystemUI/res/values-mr/strings.xml18
-rw-r--r--packages/SystemUI/res/values-ms/strings.xml6
-rw-r--r--packages/SystemUI/res/values-my/strings.xml6
-rw-r--r--packages/SystemUI/res/values-ne/strings.xml6
-rw-r--r--packages/SystemUI/res/values-nl/strings.xml6
-rw-r--r--packages/SystemUI/res/values-or/strings.xml6
-rw-r--r--packages/SystemUI/res/values-pa/strings.xml6
-rw-r--r--packages/SystemUI/res/values-pl/strings.xml6
-rw-r--r--packages/SystemUI/res/values-ro/strings.xml6
-rw-r--r--packages/SystemUI/res/values-ru/strings.xml6
-rw-r--r--packages/SystemUI/res/values-si/strings.xml6
-rw-r--r--packages/SystemUI/res/values-sk/strings.xml6
-rw-r--r--packages/SystemUI/res/values-sl/strings.xml6
-rw-r--r--packages/SystemUI/res/values-sq/strings.xml6
-rw-r--r--packages/SystemUI/res/values-sr/strings.xml6
-rw-r--r--packages/SystemUI/res/values-sv/strings.xml6
-rw-r--r--packages/SystemUI/res/values-ta/strings.xml6
-rw-r--r--packages/SystemUI/res/values-te/strings.xml6
-rw-r--r--packages/SystemUI/res/values-th/strings.xml6
-rw-r--r--packages/SystemUI/res/values-tl/strings.xml6
-rw-r--r--packages/SystemUI/res/values-tr/strings.xml6
-rw-r--r--packages/SystemUI/res/values-uk/strings.xml6
-rw-r--r--packages/SystemUI/res/values-ur/strings.xml6
-rw-r--r--packages/SystemUI/res/values-uz/strings.xml2
-rw-r--r--packages/SystemUI/res/values-vi/strings.xml6
-rw-r--r--packages/SystemUI/res/values-zh-rCN/strings.xml6
-rw-r--r--packages/SystemUI/res/values-zh-rHK/strings.xml6
-rw-r--r--packages/SystemUI/res/values-zh-rTW/strings.xml6
-rw-r--r--packages/SystemUI/res/values-zu/strings.xml6
-rw-r--r--packages/SystemUI/res/xml/people_space_widget_info.xml24
-rw-r--r--packages/SystemUI/shared/src/com/android/systemui/shared/recents/model/ThumbnailData.java20
-rw-r--r--packages/SystemUI/shared/src/com/android/systemui/shared/system/TaskStackChangeListener.java15
-rw-r--r--packages/SystemUI/shared/src/com/android/systemui/shared/system/TaskStackChangeListeners.java36
-rw-r--r--packages/SystemUI/shared/src/com/android/systemui/shared/system/WindowManagerWrapper.java2
-rw-r--r--packages/SystemUI/src/com/android/keyguard/GradientTextClock.java102
-rw-r--r--packages/SystemUI/src/com/android/keyguard/KeyguardClockSwitch.java39
-rw-r--r--packages/SystemUI/src/com/android/keyguard/KeyguardRootViewController.java2
-rw-r--r--packages/SystemUI/src/com/android/keyguard/KeyguardSliceView.java114
-rw-r--r--packages/SystemUI/src/com/android/keyguard/KeyguardSliceViewController.java94
-rw-r--r--packages/SystemUI/src/com/android/keyguard/KeyguardStatusViewController.java1
-rw-r--r--packages/SystemUI/src/com/android/keyguard/TimeBasedColorsClockController.java178
-rw-r--r--packages/SystemUI/src/com/android/keyguard/dagger/KeyguardBouncerModule.java1
-rw-r--r--packages/SystemUI/src/com/android/systemui/Dependency.java12
-rw-r--r--packages/SystemUI/src/com/android/systemui/SystemUIApplication.java34
-rw-r--r--packages/SystemUI/src/com/android/systemui/SystemUIFactory.java50
-rw-r--r--packages/SystemUI/src/com/android/systemui/bubbles/BubbleController.java29
-rw-r--r--packages/SystemUI/src/com/android/systemui/bubbles/BubbleExpandedView.java158
-rw-r--r--packages/SystemUI/src/com/android/systemui/bubbles/BubbleFlyoutView.java33
-rw-r--r--packages/SystemUI/src/com/android/systemui/bubbles/BubblePositioner.java89
-rw-r--r--packages/SystemUI/src/com/android/systemui/bubbles/BubbleStackView.java306
-rw-r--r--packages/SystemUI/src/com/android/systemui/bubbles/Bubbles.java6
-rw-r--r--packages/SystemUI/src/com/android/systemui/bubbles/MultiWindowTaskListener.java179
-rw-r--r--packages/SystemUI/src/com/android/systemui/bubbles/TaskView.java95
-rw-r--r--packages/SystemUI/src/com/android/systemui/bubbles/animation/ExpandedAnimationController.java177
-rw-r--r--packages/SystemUI/src/com/android/systemui/bubbles/animation/StackAnimationController.java84
-rw-r--r--packages/SystemUI/src/com/android/systemui/dagger/DependencyProvider.java8
-rw-r--r--packages/SystemUI/src/com/android/systemui/dagger/GlobalModule.java45
-rw-r--r--packages/SystemUI/src/com/android/systemui/dagger/GlobalRootComponent.java2
-rw-r--r--packages/SystemUI/src/com/android/systemui/dagger/SysUIComponent.java29
-rw-r--r--packages/SystemUI/src/com/android/systemui/dagger/SystemUIDefaultModule.java4
-rw-r--r--packages/SystemUI/src/com/android/systemui/dagger/SystemUIModule.java4
-rw-r--r--packages/SystemUI/src/com/android/systemui/dagger/WMComponent.java52
-rw-r--r--packages/SystemUI/src/com/android/systemui/dagger/qualifiers/RootView.java (renamed from packages/SystemUI/src/com/android/keyguard/dagger/RootView.java)4
-rw-r--r--packages/SystemUI/src/com/android/systemui/keyguard/KeyguardSliceProvider.java3
-rw-r--r--packages/SystemUI/src/com/android/systemui/media/SeekBarViewModel.kt4
-rw-r--r--packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputAdapter.java47
-rw-r--r--packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputBaseAdapter.java65
-rw-r--r--packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputBaseDialog.java5
-rw-r--r--packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputController.java60
-rw-r--r--packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputDialogFactory.kt5
-rw-r--r--packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputGroupAdapter.java220
-rw-r--r--packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputGroupDialog.java88
-rw-r--r--packages/SystemUI/src/com/android/systemui/people/PeopleSpaceActivity.java67
-rw-r--r--packages/SystemUI/src/com/android/systemui/people/PeopleSpaceUtils.java128
-rw-r--r--packages/SystemUI/src/com/android/systemui/people/widget/PeopleSpaceWidgetProvider.java53
-rw-r--r--packages/SystemUI/src/com/android/systemui/people/widget/PeopleSpaceWidgetRemoteViewsFactory.java158
-rw-r--r--packages/SystemUI/src/com/android/systemui/people/widget/PeopleSpaceWidgetService.java34
-rw-r--r--packages/SystemUI/src/com/android/systemui/privacy/PrivacyItemController.kt28
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/DoubleLineTileLayout.kt10
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/PagedTileLayout.java2
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/QSAnimator.java44
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/QSContainerImplController.java34
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/QSDetail.java5
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/QSFooterView.java (renamed from packages/SystemUI/src/com/android/systemui/qs/QSFooterImpl.java)171
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/QSFooterViewController.java241
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/QSFragment.java87
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/QSPanel.java371
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/QSPanelController.java201
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/QSPanelControllerBase.java250
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/QSSecurityFooter.java11
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/QSTileRevealController.java6
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/QuickQSPanel.java74
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/QuickQSPanelController.java83
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/QuickStatusBarHeader.java7
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/QuickStatusBarHeaderController.java85
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/TileLayout.java2
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/customize/QSCustomizer.java10
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/dagger/QSFragmentComponent.java55
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/dagger/QSFragmentModule.java90
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/dagger/QSModule.java5
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/dagger/QSScope.java32
-rw-r--r--packages/SystemUI/src/com/android/systemui/screenshot/ActionProxyReceiver.java12
-rw-r--r--packages/SystemUI/src/com/android/systemui/screenshot/DeleteScreenshotReceiver.java8
-rw-r--r--packages/SystemUI/src/com/android/systemui/screenshot/GlobalScreenshot.java1191
-rw-r--r--packages/SystemUI/src/com/android/systemui/screenshot/SaveImageInBackgroundTask.java38
-rw-r--r--packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotController.java665
-rw-r--r--packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotNotificationsController.java2
-rw-r--r--packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotSelectorView.java61
-rw-r--r--packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotView.java611
-rw-r--r--packages/SystemUI/src/com/android/systemui/screenshot/SmartActionsReceiver.java6
-rw-r--r--packages/SystemUI/src/com/android/systemui/screenshot/TakeScreenshotService.java10
-rw-r--r--packages/SystemUI/src/com/android/systemui/settings/BrightnessController.java18
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/MediaTransferManager.java212
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/NotificationHeaderUtil.java47
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/ViewTransformationHelper.java16
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRow.java113
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationContentView.java51
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationBigTextTemplateViewWrapper.java2
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationHeaderViewWrapper.java13
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationMediaTemplateViewWrapper.java2
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationTemplateViewWrapper.java6
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationViewWrapper.java20
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationChildrenContainer.java46
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBouncer.java2
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarPolicy.java8
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java33
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/policy/MobileSignalController.java8
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/policy/RemoteInputView.java76
-rw-r--r--packages/SystemUI/src/com/android/systemui/tuner/TunerService.java20
-rw-r--r--packages/SystemUI/src/com/android/systemui/tuner/TunerServiceImpl.java1
-rw-r--r--packages/SystemUI/src/com/android/systemui/tv/TvGlobalRootComponent.java6
-rw-r--r--packages/SystemUI/src/com/android/systemui/tv/TvSysUIComponentModule.java2
-rw-r--r--packages/SystemUI/src/com/android/systemui/tv/TvSystemUIBinder.java2
-rw-r--r--packages/SystemUI/src/com/android/systemui/tv/TvSystemUIModule.java4
-rw-r--r--packages/SystemUI/src/com/android/systemui/tv/TvWMComponent.java40
-rw-r--r--packages/SystemUI/src/com/android/systemui/util/DeviceConfigProxy.java6
-rw-r--r--packages/SystemUI/src/com/android/systemui/util/InjectionInflationController.java6
-rw-r--r--packages/SystemUI/src/com/android/systemui/util/ViewController.java10
-rw-r--r--packages/SystemUI/src/com/android/systemui/wmshell/TvPipModule.java21
-rw-r--r--packages/SystemUI/src/com/android/systemui/wmshell/TvWMShellModule.java7
-rw-r--r--packages/SystemUI/src/com/android/systemui/wmshell/WMShell.java20
-rw-r--r--packages/SystemUI/src/com/android/systemui/wmshell/WMShellBaseModule.java59
-rw-r--r--packages/SystemUI/src/com/android/systemui/wmshell/WMShellModule.java24
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/SysuiTestCase.java7
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/bubbles/BubbleControllerTest.java30
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/bubbles/MultiWindowTaskListenerTest.java181
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/bubbles/NewNotifPipelineBubbleControllerTest.java20
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/bubbles/TaskViewTest.java21
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/bubbles/TestableBubbleController.java5
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/bubbles/animation/ExpandedAnimationControllerTest.java83
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/bubbles/animation/StackAnimationControllerTest.java10
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/globalactions/GlobalActionsDialogTest.java15
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/media/SeekBarViewModelTest.kt17
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/media/dialog/MediaOutputAdapterTest.java51
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/media/dialog/MediaOutputBaseDialogTest.java2
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/media/dialog/MediaOutputControllerTest.java88
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/media/dialog/MediaOutputDialogTest.java2
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/media/dialog/MediaOutputGroupAdapterTest.java248
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/media/dialog/MediaOutputGroupDialogTest.java104
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/privacy/PrivacyItemControllerFlagsTest.kt19
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/qs/QSDetailTest.java2
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/qs/QSFooterImplTest.java109
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/qs/QSFooterViewControllerTest.java144
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/qs/QSFragmentTest.java17
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/qs/QSPanelControllerBaseTest.java141
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/qs/QSPanelControllerTest.java106
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/qs/QSPanelTest.java77
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/qs/TileLayoutTest.java24
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/screenshot/ActionProxyReceiverTest.java8
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/screenshot/DeleteScreenshotReceiverTest.java8
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/screenshot/ScreenshotNotificationSmartActionsTest.java30
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/screenshot/ScrollCaptureTest.java17
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/screenshot/SmartActionsReceiverTest.java6
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRowTest.java4
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationChildrenContainerTest.java19
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerBaseTest.java13
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/utils/leaks/FakeTunerService.java14
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/wmshell/WMShellTest.java15
-rw-r--r--packages/Tethering/src/com/android/networkstack/tethering/PrivateAddressCoordinator.java11
-rw-r--r--packages/Tethering/src/com/android/networkstack/tethering/TetheringConfiguration.java22
-rw-r--r--packages/Tethering/tests/mts/Android.bp56
-rw-r--r--packages/Tethering/tests/mts/AndroidManifest.xml34
-rw-r--r--packages/Tethering/tests/mts/AndroidTest.xml36
-rw-r--r--packages/Tethering/tests/mts/src/android/tethering/mts/TetheringModuleTest.java183
-rw-r--r--packages/Tethering/tests/unit/src/com/android/networkstack/tethering/PrivateAddressCoordinatorTest.java4
-rw-r--r--packages/Tethering/tests/unit/src/com/android/networkstack/tethering/TetheringConfigurationTest.java27
-rw-r--r--packages/Tethering/tests/unit/src/com/android/networkstack/tethering/TetheringTest.java6
-rw-r--r--services/accessibility/java/com/android/server/accessibility/AbstractAccessibilityServiceConnection.java8
-rw-r--r--services/accessibility/java/com/android/server/accessibility/AccessibilityInputFilter.java12
-rw-r--r--services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java7
-rw-r--r--services/accessibility/java/com/android/server/accessibility/AccessibilityUserState.java10
-rw-r--r--services/accessibility/java/com/android/server/accessibility/gestures/GestureManifold.java45
-rw-r--r--services/accessibility/java/com/android/server/accessibility/gestures/TouchExplorer.java88
-rw-r--r--services/appwidget/java/com/android/server/appwidget/AppWidgetServiceImpl.java10
-rw-r--r--services/autofill/java/com/android/server/autofill/AutofillInlineSessionController.java5
-rw-r--r--services/autofill/java/com/android/server/autofill/AutofillManagerServiceImpl.java4
-rw-r--r--services/autofill/java/com/android/server/autofill/Helper.java44
-rw-r--r--services/autofill/java/com/android/server/autofill/Session.java125
-rw-r--r--services/backup/java/com/android/server/backup/UserBackupManagerService.java2
-rw-r--r--services/core/java/android/content/pm/PackageManagerInternal.java47
-rw-r--r--services/core/java/com/android/server/ConnectivityService.java9
-rw-r--r--services/core/java/com/android/server/NetworkTimeUpdateService.java4
-rw-r--r--services/core/java/com/android/server/NsdService.java2
-rw-r--r--services/core/java/com/android/server/SystemServiceManager.java60
-rw-r--r--services/core/java/com/android/server/WiredAccessoryManager.java2
-rw-r--r--services/core/java/com/android/server/am/ActiveServices.java4
-rw-r--r--services/core/java/com/android/server/am/ActivityManagerService.java2
-rw-r--r--services/core/java/com/android/server/am/BatteryStatsService.java72
-rw-r--r--services/core/java/com/android/server/am/CachedAppOptimizer.java41
-rw-r--r--services/core/java/com/android/server/am/CoreSettingsObserver.java12
-rw-r--r--services/core/java/com/android/server/am/EventLogTags.logtags14
-rw-r--r--services/core/java/com/android/server/am/PreBootBroadcaster.java3
-rw-r--r--services/core/java/com/android/server/am/UserController.java20
-rw-r--r--services/core/java/com/android/server/biometrics/sensors/fingerprint/FingerprintService.java4
-rw-r--r--services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/LockoutFrameworkImpl.java2
-rw-r--r--services/core/java/com/android/server/compat/CompatChange.java20
-rw-r--r--services/core/java/com/android/server/compat/CompatConfig.java30
-rw-r--r--services/core/java/com/android/server/compat/OverrideValidatorImpl.java14
-rw-r--r--services/core/java/com/android/server/compat/PlatformCompat.java10
-rw-r--r--services/core/java/com/android/server/connectivity/DataConnectionStats.java27
-rw-r--r--services/core/java/com/android/server/connectivity/DnsManager.java4
-rw-r--r--services/core/java/com/android/server/connectivity/MockableSystemProperties.java9
-rw-r--r--services/core/java/com/android/server/connectivity/Vpn.java14
-rw-r--r--services/core/java/com/android/server/display/AutomaticBrightnessController.java2
-rw-r--r--services/core/java/com/android/server/display/DisplayManagerService.java30
-rw-r--r--services/core/java/com/android/server/display/DisplayModeDirector.java1
-rw-r--r--services/core/java/com/android/server/display/LocalDisplayAdapter.java10
-rw-r--r--services/core/java/com/android/server/display/LogicalDisplayMapper.java50
-rw-r--r--services/core/java/com/android/server/display/utils/History.java2
-rw-r--r--services/core/java/com/android/server/display/utils/RollingBuffer.java2
-rwxr-xr-xservices/core/java/com/android/server/hdmi/HdmiCecLocalDevice.java2
-rw-r--r--services/core/java/com/android/server/hdmi/HdmiCecMessage.java2
-rw-r--r--services/core/java/com/android/server/input/InputShellCommand.java2
-rw-r--r--services/core/java/com/android/server/media/MediaSessionStack.java2
-rw-r--r--services/core/java/com/android/server/om/IdmapManager.java4
-rw-r--r--services/core/java/com/android/server/pm/IncrementalStates.java97
-rw-r--r--services/core/java/com/android/server/pm/PackageInstallerSession.java60
-rw-r--r--services/core/java/com/android/server/pm/PackageManagerService.java739
-rw-r--r--services/core/java/com/android/server/pm/PackageManagerShellCommand.java6
-rw-r--r--services/core/java/com/android/server/pm/PackageSetting.java29
-rw-r--r--services/core/java/com/android/server/pm/PackageSettingBase.java7
-rw-r--r--services/core/java/com/android/server/pm/PackageSignatures.java2
-rw-r--r--services/core/java/com/android/server/pm/PackageUsage.java10
-rw-r--r--services/core/java/com/android/server/pm/Settings.java2
-rw-r--r--services/core/java/com/android/server/pm/UserManagerService.java54
-rw-r--r--services/core/java/com/android/server/pm/permission/BasePermission.java5
-rw-r--r--services/core/java/com/android/server/pm/permission/PermissionManagerService.java8
-rw-r--r--services/core/java/com/android/server/policy/DisplayFoldController.java55
-rw-r--r--services/core/java/com/android/server/policy/PhoneWindowManager.java5
-rw-r--r--services/core/java/com/android/server/rollback/RollbackManagerServiceImpl.java26
-rw-r--r--services/core/java/com/android/server/soundtrigger_middleware/ExternalCaptureStateTracker.java11
-rw-r--r--services/core/java/com/android/server/webkit/SystemImpl.java13
-rw-r--r--services/core/java/com/android/server/webkit/SystemInterface.java3
-rw-r--r--services/core/java/com/android/server/webkit/WebViewUpdateServiceImpl.java27
-rw-r--r--services/core/java/com/android/server/wm/ActivityRecord.java28
-rw-r--r--services/core/java/com/android/server/wm/ActivityStackSupervisor.java14
-rw-r--r--services/core/java/com/android/server/wm/ActivityTaskManagerInternal.java7
-rw-r--r--services/core/java/com/android/server/wm/ActivityTaskManagerService.java45
-rw-r--r--services/core/java/com/android/server/wm/AppTransition.java57
-rw-r--r--services/core/java/com/android/server/wm/AppTransitionController.java10
-rw-r--r--services/core/java/com/android/server/wm/BLASTSyncEngine.java150
-rw-r--r--services/core/java/com/android/server/wm/DisplayContent.java39
-rw-r--r--services/core/java/com/android/server/wm/DisplayPolicy.java138
-rw-r--r--services/core/java/com/android/server/wm/InsetsPolicy.java21
-rw-r--r--services/core/java/com/android/server/wm/InsetsStateController.java30
-rw-r--r--services/core/java/com/android/server/wm/RecentTasks.java8
-rw-r--r--services/core/java/com/android/server/wm/ResetTargetTaskHelper.java5
-rw-r--r--services/core/java/com/android/server/wm/RootWindowContainer.java23
-rw-r--r--services/core/java/com/android/server/wm/Session.java31
-rw-r--r--services/core/java/com/android/server/wm/Task.java33
-rw-r--r--services/core/java/com/android/server/wm/TaskChangeNotificationController.java49
-rw-r--r--services/core/java/com/android/server/wm/TaskDisplayArea.java11
-rw-r--r--services/core/java/com/android/server/wm/TaskOrganizerController.java55
-rw-r--r--services/core/java/com/android/server/wm/TaskSnapshotSurface.java5
-rw-r--r--services/core/java/com/android/server/wm/Transition.java28
-rw-r--r--services/core/java/com/android/server/wm/TransitionController.java1
-rw-r--r--services/core/java/com/android/server/wm/WindowContainer.java211
-rw-r--r--services/core/java/com/android/server/wm/WindowFrames.java22
-rw-r--r--services/core/java/com/android/server/wm/WindowManagerService.java44
-rw-r--r--services/core/java/com/android/server/wm/WindowOrganizerController.java19
-rw-r--r--services/core/java/com/android/server/wm/WindowState.java132
-rw-r--r--services/core/java/com/android/server/wm/WindowStateAnimator.java1
-rw-r--r--services/core/java/com/android/server/wm/WindowSurfaceController.java22
-rw-r--r--services/core/java/com/android/server/wm/WindowToken.java7
-rw-r--r--services/core/jni/Android.bp1
-rw-r--r--services/core/jni/com_android_server_SystemServer.cpp17
-rw-r--r--services/core/jni/com_android_server_location_GnssLocationProvider.cpp249
-rw-r--r--services/core/jni/gnss/GnssConfiguration.cpp264
-rw-r--r--services/core/jni/gnss/GnssConfiguration.h168
-rw-r--r--services/core/xsd/platform-compat-config.xsd1
-rw-r--r--services/core/xsd/platform-compat-schema/current.txt2
-rw-r--r--services/devicepolicy/java/com/android/server/devicepolicy/CertificateMonitor.java5
-rw-r--r--services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java469
-rw-r--r--services/devicepolicy/java/com/android/server/devicepolicy/RemoteBugreportManager.java9
-rw-r--r--services/incremental/BinderIncrementalService.cpp16
-rw-r--r--services/incremental/BinderIncrementalService.h5
-rw-r--r--services/incremental/IncrementalService.cpp79
-rw-r--r--services/incremental/IncrementalService.h8
-rw-r--r--services/incremental/test/IncrementalServiceTest.cpp91
-rw-r--r--services/people/java/com/android/server/people/PeopleService.java2
-rw-r--r--services/profcollect/src/com/android/server/profcollect/ProfcollectForwardingService.java32
-rw-r--r--services/tests/PackageManagerComponentOverrideTests/src/com/android/server/pm/test/override/PackageManagerComponentLabelIconOverrideTest.kt4
-rw-r--r--services/tests/servicestests/src/com/android/server/am/UserControllerTest.java2
-rw-r--r--services/tests/servicestests/src/com/android/server/compat/CompatConfigBuilder.java51
-rw-r--r--services/tests/servicestests/src/com/android/server/compat/CompatConfigTest.java14
-rw-r--r--services/tests/servicestests/src/com/android/server/compat/OverrideValidatorImplTest.java36
-rw-r--r--services/tests/servicestests/src/com/android/server/compat/PlatformCompatTest.java40
-rw-r--r--services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java4
-rw-r--r--services/tests/servicestests/src/com/android/server/hdmi/HdmiCecMessageValidatorTest.java94
-rw-r--r--services/tests/servicestests/src/com/android/server/om/OverlayManagerServiceImplRebootTests.java4
-rw-r--r--services/tests/servicestests/src/com/android/server/om/OverlayManagerServiceImplTests.java48
-rw-r--r--services/tests/servicestests/src/com/android/server/om/OverlayManagerServiceImplTestsBase.java76
-rw-r--r--services/tests/servicestests/src/com/android/server/om/OverlayManagerSettingsTests.java56
-rw-r--r--services/tests/servicestests/src/com/android/server/pm/IncrementalStatesTest.java111
-rw-r--r--services/tests/servicestests/src/com/android/server/pm/PackageManagerServiceTest.java62
-rw-r--r--services/tests/servicestests/src/com/android/server/pm/UserManagerTest.java10
-rw-r--r--services/tests/servicestests/src/com/android/server/webkit/TestSystemImpl.java16
-rw-r--r--services/tests/servicestests/src/com/android/server/webkit/WebViewUpdateServiceTest.java76
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java1
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/ActivityStackTests.java22
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/ActivityTaskManagerServiceTests.java35
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/DisplayPolicyLayoutTests.java58
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/InsetsPolicyTest.java2
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/InsetsStateControllerTest.java42
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/RecentTasksTest.java2
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/SyncEngineTests.java390
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/TaskStackChangedListenerTest.java91
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/TestIWindow.java4
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/WindowOrganizerTests.java190
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/WindowStateTests.java4
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/WindowTestsBase.java4
-rw-r--r--services/usb/java/com/android/server/usb/MtpNotificationManager.java3
-rw-r--r--services/usb/java/com/android/server/usb/UsbDeviceManager.java7
-rw-r--r--services/usb/java/com/android/server/usb/UsbPortManager.java3
-rwxr-xr-xtelecomm/java/android/telecom/Call.java2
-rw-r--r--telecomm/java/android/telecom/CallScreeningService.java2
-rw-r--r--telecomm/java/android/telecom/Conference.java6
-rw-r--r--[-rwxr-xr-x]telecomm/java/android/telecom/Connection.java18
-rw-r--r--telecomm/java/android/telecom/ConnectionRequest.java1
-rw-r--r--telecomm/java/android/telecom/PhoneAccount.java2
-rw-r--r--telecomm/java/android/telecom/PhoneAccountSuggestionService.java2
-rw-r--r--telecomm/java/android/telecom/TelecomManager.java16
-rw-r--r--telephony/api/system-current.txt16
-rw-r--r--telephony/java/android/telephony/AccessNetworkConstants.java6
-rw-r--r--telephony/java/android/telephony/BarringInfo.java1
-rw-r--r--telephony/java/android/telephony/CallQuality.java2
-rw-r--r--[-rwxr-xr-x]telephony/java/android/telephony/CarrierConfigManager.java17
-rw-r--r--telephony/java/android/telephony/CdmaEriInformation.java169
-rw-r--r--telephony/java/android/telephony/DataSpecificRegistrationInfo.java2
-rw-r--r--telephony/java/android/telephony/ImsManager.java21
-rw-r--r--telephony/java/android/telephony/LteVopsSupportInfo.java2
-rw-r--r--telephony/java/android/telephony/ModemActivityInfo.java1
-rw-r--r--telephony/java/android/telephony/NetworkRegistrationInfo.java35
-rw-r--r--telephony/java/android/telephony/PhoneNumberUtils.java3
-rw-r--r--telephony/java/android/telephony/SignalStrength.java4
-rw-r--r--telephony/java/android/telephony/SubscriptionManager.java8
-rw-r--r--telephony/java/android/telephony/TelephonyManager.java93
-rw-r--r--telephony/java/android/telephony/ims/ImsCallForwardInfo.java2
-rw-r--r--telephony/java/android/telephony/ims/ImsCallProfile.java1
-rw-r--r--telephony/java/android/telephony/ims/ImsCallSessionListener.java2
-rw-r--r--telephony/java/android/telephony/ims/ImsConferenceState.java2
-rw-r--r--telephony/java/android/telephony/ims/ImsException.java4
-rw-r--r--telephony/java/android/telephony/ims/ImsExternalCallState.java2
-rw-r--r--telephony/java/android/telephony/ims/ImsMmTelManager.java36
-rw-r--r--telephony/java/android/telephony/ims/ImsService.java16
-rw-r--r--telephony/java/android/telephony/ims/ImsSsData.java2
-rw-r--r--telephony/java/android/telephony/ims/ImsSsInfo.java2
-rw-r--r--telephony/java/android/telephony/ims/ImsStreamMediaProfile.java2
-rw-r--r--telephony/java/android/telephony/ims/ImsSuppServiceNotification.java2
-rw-r--r--telephony/java/android/telephony/ims/ImsUtListener.java2
-rw-r--r--telephony/java/android/telephony/ims/ImsVideoCallProvider.java3
-rw-r--r--telephony/java/android/telephony/ims/ProvisioningManager.java2
-rw-r--r--telephony/java/android/telephony/ims/RcsUceAdapter.java2
-rw-r--r--telephony/java/android/telephony/ims/SipDelegateManager.java93
-rw-r--r--telephony/java/android/telephony/ims/aidl/IImsRcsController.aidl3
-rw-r--r--telephony/java/android/telephony/ims/feature/CapabilityChangeRequest.java2
-rw-r--r--telephony/java/android/telephony/ims/feature/ImsFeature.java23
-rw-r--r--telephony/java/android/telephony/ims/feature/MmTelFeature.java55
-rw-r--r--telephony/java/android/telephony/ims/feature/RcsFeature.java2
-rw-r--r--telephony/java/android/telephony/ims/stub/ImsCallSessionImplBase.java2
-rw-r--r--telephony/java/android/telephony/ims/stub/ImsConfigImplBase.java2
-rw-r--r--telephony/java/android/telephony/ims/stub/ImsEcbmImplBase.java2
-rw-r--r--telephony/java/android/telephony/ims/stub/ImsFeatureConfiguration.java2
-rw-r--r--telephony/java/android/telephony/ims/stub/ImsMultiEndpointImplBase.java2
-rw-r--r--telephony/java/android/telephony/ims/stub/ImsRegistrationImplBase.java2
-rw-r--r--telephony/java/android/telephony/ims/stub/ImsSmsImplBase.java2
-rw-r--r--telephony/java/android/telephony/ims/stub/ImsUtImplBase.java2
-rw-r--r--telephony/java/android/telephony/ims/stub/SipTransportImplBase.java5
-rw-r--r--telephony/java/android/telephony/mbms/DownloadRequest.java2
-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/StreamingServiceInfo.java2
-rw-r--r--telephony/java/android/telephony/mbms/UriPathPair.java2
-rw-r--r--telephony/java/android/telephony/mbms/vendor/MbmsDownloadServiceBase.java4
-rw-r--r--telephony/java/android/telephony/mbms/vendor/MbmsGroupCallServiceBase.java2
-rw-r--r--telephony/java/android/telephony/mbms/vendor/MbmsStreamingServiceBase.java4
-rw-r--r--telephony/java/android/telephony/mbms/vendor/VendorUtils.java2
-rw-r--r--test-mock/api/test-current.txt9
-rw-r--r--tests/RollbackTest/StagedRollbackTest/src/com/android/tests/rollback/host/StagedRollbackTest.java165
-rw-r--r--tests/net/Android.bp1
-rw-r--r--tests/net/common/Android.bp1
-rw-r--r--tests/net/common/java/android/net/LinkPropertiesTest.java52
-rw-r--r--tests/net/jarjar-rules.txt2
-rw-r--r--tests/net/java/com/android/server/ConnectivityServiceTest.java19
-rw-r--r--tests/net/java/com/android/server/connectivity/DnsManagerTest.java3
-rw-r--r--wifi/api/current.txt2
-rw-r--r--wifi/api/system-current.txt6
-rw-r--r--wifi/java/android/net/wifi/SoftApConfiguration.java3
-rw-r--r--wifi/java/android/net/wifi/WifiConfiguration.java26
-rw-r--r--wifi/java/android/net/wifi/aware/Characteristics.java15
-rw-r--r--wifi/java/android/net/wifi/aware/IWifiAwareManager.aidl2
-rw-r--r--wifi/java/android/net/wifi/aware/WifiAwareManager.java41
-rw-r--r--wifi/tests/src/android/net/wifi/aware/WifiAwareManagerTest.java15
1103 files changed, 21494 insertions, 14406 deletions
diff --git a/Android.bp b/Android.bp
index 1c16e466703c..f3225e2e3ad0 100644
--- a/Android.bp
+++ b/Android.bp
@@ -540,8 +540,8 @@ filegroup {
path: "core/java",
}
-java_library {
- name: "framework-minus-apex",
+java_defaults {
+ name: "framework-minus-apex-defaults",
defaults: ["framework-aidl-export-defaults"],
srcs: [
":framework-non-updatable-sources",
@@ -557,7 +557,6 @@ java_library {
"--core-library",
"--multi-dex",
],
- installable: true,
jarjar_rules: ":framework-jarjar-rules",
javac_shard_size: 150,
plugins: [
@@ -590,6 +589,12 @@ java_library {
"mediatranscoding_aidl_interface-java",
"soundtrigger_middleware-aidl-java",
],
+}
+
+java_library {
+ name: "framework-minus-apex",
+ defaults: ["framework-minus-apex-defaults"],
+ installable: true,
// For backwards compatibility.
stem: "framework",
apex_available: ["//apex_available:platform"],
@@ -610,6 +615,12 @@ java_library {
},
}
+java_library {
+ name: "framework-minus-apex-intdefs",
+ defaults: ["framework-minus-apex-defaults"],
+ plugins: ["intdef-annotation-processor"],
+}
+
// This "framework" module is NOT installed to the device. It's
// "framework-minus-apex" that gets installed to the device. Note that
// the filename is still framework.jar (via the stem property) for
diff --git a/apct-tests/perftests/textclassifier/run.sh b/apct-tests/perftests/textclassifier/run.sh
index d36d190a573a..9a0f4f9fab73 100755
--- a/apct-tests/perftests/textclassifier/run.sh
+++ b/apct-tests/perftests/textclassifier/run.sh
@@ -1,8 +1,8 @@
set -e
-build/soong/soong_ui.bash --make-mode TextClassifierPerfTests perf-setup.sh
+build/soong/soong_ui.bash --make-mode TextClassifierPerfTests perf-setup
adb install ${OUT}/testcases/TextClassifierPerfTests/arm64/TextClassifierPerfTests.apk
adb shell cmd package compile -m speed -f com.android.perftests.textclassifier
-adb push ${OUT}/obj/EXECUTABLES/perf-setup.sh_intermediates/perf-setup.sh /data/local/tmp/
+adb push ${OUT}/obj/EXECUTABLES/perf-setup_intermediates/perf-setup.sh /data/local/tmp/
adb shell chmod +x /data/local/tmp/perf-setup.sh
adb shell /data/local/tmp/perf-setup.sh
-adb shell am instrument -w -e package android.view.textclassifier com.android.perftests.textclassifier/androidx.test.runner.AndroidJUnitRunner \ No newline at end of file
+adb shell am instrument -w -e package android.view.textclassifier com.android.perftests.textclassifier/androidx.test.runner.AndroidJUnitRunner
diff --git a/apct-tests/perftests/windowmanager/README.md b/apct-tests/perftests/windowmanager/README.md
index 8b5292fd02a5..7a0019a0c23f 100644
--- a/apct-tests/perftests/windowmanager/README.md
+++ b/apct-tests/perftests/windowmanager/README.md
@@ -4,7 +4,7 @@
To reduce the variance of the test, if `perf-setup.sh` (platform_testing/scripts/perf-setup)
is available, it is better to use the following instructions to lock CPU and GPU frequencies.
```
-m perf-setup.sh
+m perf-setup
PERF_SETUP_PATH=/data/local/tmp/perf-setup.sh
adb push $OUT/$PERF_SETUP_PATH $PERF_SETUP_PATH
adb shell chmod +x $PERF_SETUP_PATH
diff --git a/apct-tests/perftests/windowmanager/src/android/wm/WindowAddRemovePerfTest.java b/apct-tests/perftests/windowmanager/src/android/wm/WindowAddRemovePerfTest.java
index 6f0001dcc0ad..29606030a041 100644
--- a/apct-tests/perftests/windowmanager/src/android/wm/WindowAddRemovePerfTest.java
+++ b/apct-tests/perftests/windowmanager/src/android/wm/WindowAddRemovePerfTest.java
@@ -86,8 +86,6 @@ public class WindowAddRemovePerfTest extends WindowManagerPerfTestBase
final WindowManager.LayoutParams mLayoutParams = new WindowManager.LayoutParams();
final InsetsState mRequestedVisibility = new InsetsState();
final Rect mOutFrame = new Rect();
- final Rect mOutContentInsets = new Rect();
- final Rect mOutStableInsets = new Rect();
final DisplayCutout.ParcelableWrapper mOutDisplayCutout =
new DisplayCutout.ParcelableWrapper();
final InsetsState mOutInsetsState = new InsetsState();
@@ -110,7 +108,6 @@ public class WindowAddRemovePerfTest extends WindowManagerPerfTestBase
long startTime = SystemClock.elapsedRealtimeNanos();
session.addToDisplay(this, mLayoutParams, View.VISIBLE,
Display.DEFAULT_DISPLAY, mRequestedVisibility, mOutFrame,
- mOutContentInsets, mOutStableInsets,
mOutDisplayCutout, inputChannel, mOutInsetsState, mOutControls);
final long elapsedTimeNsOfAdd = SystemClock.elapsedRealtimeNanos() - startTime;
state.addExtraResult("add", elapsedTimeNsOfAdd);
diff --git a/apex/Android.bp b/apex/Android.bp
index 266e6720c1a1..c5b4901a9b79 100644
--- a/apex/Android.bp
+++ b/apex/Android.bp
@@ -107,7 +107,7 @@ java_defaults {
// Hide impl library and stub sources
impl_library_visibility: [
- ":__package__",
+ ":__pkg__",
"//frameworks/base", // For framework-all
],
stubs_source_visibility: ["//visibility:private"],
diff --git a/apex/appsearch/framework/Android.bp b/apex/appsearch/framework/Android.bp
index e10fb074126f..12afde4a0f70 100644
--- a/apex/appsearch/framework/Android.bp
+++ b/apex/appsearch/framework/Android.bp
@@ -26,10 +26,8 @@ java_sdk_library {
srcs: [ ":framework-appsearch-sources" ],
sdk_version: "core_platform", // TODO(b/146218515) should be module_current
impl_only_libs: ["framework-minus-apex"], // TODO(b/146218515) should be removed
- static_libs: ["icing-java-proto-lite"],
defaults: ["framework-module-defaults"],
permitted_packages: ["android.app.appsearch"],
- jarjar_rules: "jarjar-rules.txt",
aidl: {
include_dirs: ["frameworks/base/core/java"], // TODO(b/146218515) should be removed
},
diff --git a/apex/appsearch/framework/jarjar-rules.txt b/apex/appsearch/framework/jarjar-rules.txt
deleted file mode 100644
index acf759a58d56..000000000000
--- a/apex/appsearch/framework/jarjar-rules.txt
+++ /dev/null
@@ -1,2 +0,0 @@
-rule com.google.protobuf.** android.app.appsearch.protobuf.@1
-rule com.google.android.icing.proto.** android.app.appsearch.proto.@1
diff --git a/apex/appsearch/framework/java/android/app/appsearch/AppSearchManager.java b/apex/appsearch/framework/java/android/app/appsearch/AppSearchManager.java
index 67fa6c89ad4a..18bc59b91aa0 100644
--- a/apex/appsearch/framework/java/android/app/appsearch/AppSearchManager.java
+++ b/apex/appsearch/framework/java/android/app/appsearch/AppSearchManager.java
@@ -40,6 +40,7 @@ import java.util.concurrent.ExecutionException;
// TODO(b/148046169): This class header needs a detailed example/tutorial.
@SystemService(Context.APP_SEARCH_SERVICE)
public class AppSearchManager {
+ private static final String DEFAULT_DATABASE = "";
private final IAppSearchManager mService;
/** @hide */
@@ -112,7 +113,7 @@ public class AppSearchManager {
}
AndroidFuture<AppSearchResult> future = new AndroidFuture<>();
try {
- mService.setSchema(schemaBundles, request.isForceOverride(), future);
+ mService.setSchema(DEFAULT_DATABASE, schemaBundles, request.isForceOverride(), future);
} catch (RemoteException e) {
future.completeExceptionally(e);
}
@@ -145,7 +146,7 @@ public class AppSearchManager {
}
AndroidFuture<AppSearchBatchResult> future = new AndroidFuture<>();
try {
- mService.putDocuments(documentBundles, future);
+ mService.putDocuments(DEFAULT_DATABASE, documentBundles, future);
} catch (RemoteException e) {
future.completeExceptionally(e);
}
@@ -172,7 +173,7 @@ public class AppSearchManager {
List<String> uris = new ArrayList<>(request.getUris());
AndroidFuture<AppSearchBatchResult> future = new AndroidFuture<>();
try {
- mService.getDocuments(uris, future);
+ mService.getDocuments(DEFAULT_DATABASE, request.getNamespace(), uris, future);
} catch (RemoteException e) {
future.completeExceptionally(e);
}
@@ -260,7 +261,8 @@ public class AppSearchManager {
// them in one big list.
AndroidFuture<AppSearchResult> searchResultsFuture = new AndroidFuture<>();
try {
- mService.query(queryExpression, searchSpec.getBundle(), searchResultsFuture);
+ mService.query(DEFAULT_DATABASE, queryExpression,
+ searchSpec.getBundle(), searchResultsFuture);
} catch (RemoteException e) {
searchResultsFuture.completeExceptionally(e);
}
@@ -292,7 +294,7 @@ public class AppSearchManager {
List<String> uris = new ArrayList<>(request.getUris());
AndroidFuture<AppSearchBatchResult> future = new AndroidFuture<>();
try {
- mService.delete(uris, future);
+ mService.delete(DEFAULT_DATABASE, request.getNamespace(), uris, future);
} catch (RemoteException e) {
future.completeExceptionally(e);
}
@@ -300,7 +302,7 @@ public class AppSearchManager {
}
/**
- * Deletes {@link android.app.appsearch.AppSearch.Document}s by schema type.
+ * Deletes {@link android.app.appsearch.GenericDocument}s by schema type.
*
* <p>You should not call this method directly; instead, use the
* {@code AppSearch#deleteByType()} API provided by JetPack.
@@ -313,7 +315,7 @@ public class AppSearchManager {
public AppSearchBatchResult<String, Void> deleteByTypes(@NonNull List<String> schemaTypes) {
AndroidFuture<AppSearchBatchResult> future = new AndroidFuture<>();
try {
- mService.deleteByTypes(schemaTypes, future);
+ mService.deleteByTypes(DEFAULT_DATABASE, schemaTypes, future);
} catch (RemoteException e) {
future.completeExceptionally(e);
}
@@ -324,7 +326,7 @@ public class AppSearchManager {
public AppSearchResult<Void> deleteAll() {
AndroidFuture<AppSearchResult> future = new AndroidFuture<>();
try {
- mService.deleteAll(future);
+ mService.deleteAll(DEFAULT_DATABASE, future);
} catch (RemoteException e) {
future.completeExceptionally(e);
}
diff --git a/apex/appsearch/framework/java/android/app/appsearch/IAppSearchManager.aidl b/apex/appsearch/framework/java/android/app/appsearch/IAppSearchManager.aidl
index 8e18346ffece..352a980eef27 100644
--- a/apex/appsearch/framework/java/android/app/appsearch/IAppSearchManager.aidl
+++ b/apex/appsearch/framework/java/android/app/appsearch/IAppSearchManager.aidl
@@ -28,6 +28,7 @@ interface IAppSearchManager {
/**
* Sets the schema.
*
+ * @param databaseName The databaseName this document resides in.
* @param schemaBundles List of AppSearchSchema bundles.
* @param forceOverride Whether to apply the new schema even if it is incompatible. All
* incompatible documents will be deleted.
@@ -35,6 +36,7 @@ interface IAppSearchManager {
* The results of the call.
*/
void setSchema(
+ in String databaseName,
in List<Bundle> schemaBundles,
boolean forceOverride,
in AndroidFuture<AppSearchResult> callback);
@@ -42,6 +44,7 @@ interface IAppSearchManager {
/**
* Inserts documents into the index.
*
+ * @param databaseName The name of the database where this document lives.
* @param documentBundes List of GenericDocument bundles.
* @param callback
* {@link AndroidFuture}&lt;{@link AppSearchBatchResult}&lt;{@link String}, {@link Void}&gt;&gt;.
@@ -51,11 +54,15 @@ interface IAppSearchManager {
* where the keys are document URIs, and the values are {@code null}.
*/
void putDocuments(
- in List<Bundle> documentBundles, in AndroidFuture<AppSearchBatchResult> callback);
+ in String databaseName,
+ in List<Bundle> documentBundles,
+ in AndroidFuture<AppSearchBatchResult> callback);
/**
* Retrieves documents from the index.
*
+ * @param databaseName The databaseName this document resides in.
+ * @param namespace The namespace this document resides in.
* @param uris The URIs of the documents to retrieve
* @param callback
* {@link AndroidFuture}&lt;{@link AppSearchBatchResult}&lt;{@link String}, {@link Bundle}&gt;&gt;.
@@ -64,16 +71,22 @@ interface IAppSearchManager {
* {@link AppSearchBatchResult}&lt;{@link String}, {@link Bundle}&gt;
* where the keys are document URIs, and the values are Document bundles.
*/
- void getDocuments(in List<String> uris, in AndroidFuture<AppSearchBatchResult> callback);
+ void getDocuments(
+ in String databaseName,
+ in String namespace,
+ in List<String> uris,
+ in AndroidFuture<AppSearchBatchResult> callback);
/**
* Searches a document based on a given specifications.
*
+ * @param databaseName The databaseName this query for.
* @param queryExpression String to search for
* @param searchSpecBundle SearchSpec bundle
* @param callback {@link AndroidFuture}&lt;{@link AppSearchResult}&lt;{@link SearchResults}&gt;&gt;
*/
void query(
+ in String databaseName,
in String queryExpression,
in Bundle searchSpecBundle,
in AndroidFuture<AppSearchResult> callback);
@@ -81,6 +94,8 @@ interface IAppSearchManager {
/**
* Deletes documents by URI.
*
+ * @param databaseName The databaseName the document is in.
+ * @param namespace Namespace of the document to remove.
* @param uris The URIs of the documents to delete
* @param callback
* {@link AndroidFuture}&lt;{@link AppSearchBatchResult}&lt;{@link String}, {@link Void}&gt;&gt;.
@@ -90,11 +105,16 @@ interface IAppSearchManager {
* where the keys are document URIs. If a document doesn't exist, it will be reported as a
* failure where the {@code throwable} is {@code null}.
*/
- void delete(in List<String> uris, in AndroidFuture<AppSearchBatchResult> callback);
+ void delete(
+ in String databaseName,
+ in String namespace,
+ in List<String> uris,
+ in AndroidFuture<AppSearchBatchResult> callback);
/**
* Deletes documents by schema type.
*
+ * @param databaseName The databaseName the document is in.
* @param schemaTypes The schema types of the documents to delete
* @param callback
* {@link AndroidFuture}&lt;{@link AppSearchBatchResult}&lt;{@link String}, {@link Void}&gt;&gt;.
@@ -105,13 +125,16 @@ interface IAppSearchManager {
* failure where the {@code throwable} is {@code null}.
*/
void deleteByTypes(
- in List<String> schemaTypes, in AndroidFuture<AppSearchBatchResult> callback);
+ in String databaseName,
+ in List<String> schemaTypes,
+ in AndroidFuture<AppSearchBatchResult> callback);
/**
* Deletes all documents belonging to the calling app.
*
+ * @param databaseName The databaseName to remove all documents from.
* @param callback {@link AndroidFuture}&lt;{@link AppSearchResult}&lt;{@link Void}&gt;&gt;.
* Will be completed with the result of the call.
*/
- void deleteAll(in AndroidFuture<AppSearchResult> callback);
+ void deleteAll(in String databaseName, in AndroidFuture<AppSearchResult> callback);
}
diff --git a/apex/appsearch/service/java/com/android/server/appsearch/AppSearchManagerService.java b/apex/appsearch/service/java/com/android/server/appsearch/AppSearchManagerService.java
index 06612ac31f63..7cd6ee24cb20 100644
--- a/apex/appsearch/service/java/com/android/server/appsearch/AppSearchManagerService.java
+++ b/apex/appsearch/service/java/com/android/server/appsearch/AppSearchManagerService.java
@@ -53,6 +53,7 @@ import java.util.List;
*/
public class AppSearchManagerService extends SystemService {
private static final String TAG = "AppSearchManagerService";
+ private static final char CALLING_NAME_DATABASE_DELIMITER = '$';
public AppSearchManagerService(Context context) {
super(context);
@@ -66,6 +67,7 @@ public class AppSearchManagerService extends SystemService {
private class Stub extends IAppSearchManager.Stub {
@Override
public void setSchema(
+ @NonNull String databaseName,
@NonNull List<Bundle> schemaBundles,
boolean forceOverride,
@NonNull AndroidFuture<AppSearchResult> callback) {
@@ -82,7 +84,7 @@ public class AppSearchManagerService extends SystemService {
schemaProtoBuilder.addTypes(schemaTypeProto);
}
AppSearchImpl impl = ImplInstanceManager.getInstance(getContext(), callingUserId);
- String databaseName = makeDatabaseName(callingUid);
+ databaseName = rewriteDatabaseNameWithUid(databaseName, callingUid);
impl.setSchema(databaseName, schemaProtoBuilder.build(), forceOverride);
callback.complete(AppSearchResult.newSuccessfulResult(/*result=*/ null));
} catch (Throwable t) {
@@ -94,6 +96,7 @@ public class AppSearchManagerService extends SystemService {
@Override
public void putDocuments(
+ @NonNull String databaseName,
@NonNull List<Bundle> documentBundles,
@NonNull AndroidFuture<AppSearchBatchResult> callback) {
Preconditions.checkNotNull(documentBundles);
@@ -103,7 +106,7 @@ public class AppSearchManagerService extends SystemService {
final long callingIdentity = Binder.clearCallingIdentity();
try {
AppSearchImpl impl = ImplInstanceManager.getInstance(getContext(), callingUserId);
- String databaseName = makeDatabaseName(callingUid);
+ databaseName = rewriteDatabaseNameWithUid(databaseName, callingUid);
AppSearchBatchResult.Builder<String, Void> resultBuilder =
new AppSearchBatchResult.Builder<>();
for (int i = 0; i < documentBundles.size(); i++) {
@@ -125,7 +128,7 @@ public class AppSearchManagerService extends SystemService {
}
@Override
- public void getDocuments(
+ public void getDocuments(@NonNull String databaseName, @NonNull String namespace,
@NonNull List<String> uris, @NonNull AndroidFuture<AppSearchBatchResult> callback) {
Preconditions.checkNotNull(uris);
Preconditions.checkNotNull(callback);
@@ -134,14 +137,14 @@ public class AppSearchManagerService extends SystemService {
final long callingIdentity = Binder.clearCallingIdentity();
try {
AppSearchImpl impl = ImplInstanceManager.getInstance(getContext(), callingUserId);
- String databaseName = makeDatabaseName(callingUid);
+ databaseName = rewriteDatabaseNameWithUid(databaseName, callingUid);
AppSearchBatchResult.Builder<String, Bundle> resultBuilder =
new AppSearchBatchResult.Builder<>();
for (int i = 0; i < uris.size(); i++) {
String uri = uris.get(i);
try {
DocumentProto documentProto = impl.getDocument(
- databaseName, GenericDocument.DEFAULT_NAMESPACE, uri);
+ databaseName, namespace, uri);
if (documentProto == null) {
resultBuilder.setFailure(
uri, AppSearchResult.RESULT_NOT_FOUND, /*errorMessage=*/ null);
@@ -165,6 +168,7 @@ public class AppSearchManagerService extends SystemService {
// TODO(sidchhabra): Do this in a threadpool.
@Override
public void query(
+ @NonNull String databaseName,
@NonNull String queryExpression,
@NonNull Bundle searchSpecBundle,
@NonNull AndroidFuture<AppSearchResult> callback) {
@@ -181,7 +185,7 @@ public class AppSearchManagerService extends SystemService {
searchSpecProto = searchSpecProto.toBuilder()
.setQuery(queryExpression).build();
AppSearchImpl impl = ImplInstanceManager.getInstance(getContext(), callingUserId);
- String databaseName = makeDatabaseName(callingUid);
+ databaseName = rewriteDatabaseNameWithUid(databaseName, callingUid);
// TODO(adorokhine): handle pagination
SearchResultProto searchResultProto = impl.query(
databaseName,
@@ -201,7 +205,8 @@ public class AppSearchManagerService extends SystemService {
}
@Override
- public void delete(List<String> uris, AndroidFuture<AppSearchBatchResult> callback) {
+ public void delete(@NonNull String databaseName, @NonNull String namespace,
+ List<String> uris, AndroidFuture<AppSearchBatchResult> callback) {
Preconditions.checkNotNull(uris);
Preconditions.checkNotNull(callback);
int callingUid = Binder.getCallingUidOrThrow();
@@ -209,13 +214,13 @@ public class AppSearchManagerService extends SystemService {
final long callingIdentity = Binder.clearCallingIdentity();
try {
AppSearchImpl impl = ImplInstanceManager.getInstance(getContext(), callingUserId);
- String databaseName = makeDatabaseName(callingUid);
+ databaseName = rewriteDatabaseNameWithUid(databaseName, callingUid);
AppSearchBatchResult.Builder<String, Void> resultBuilder =
new AppSearchBatchResult.Builder<>();
for (int i = 0; i < uris.size(); i++) {
String uri = uris.get(i);
try {
- impl.remove(databaseName, GenericDocument.DEFAULT_NAMESPACE, uri);
+ impl.remove(databaseName, namespace, uri);
resultBuilder.setSuccess(uri, /*result= */null);
} catch (Throwable t) {
resultBuilder.setResult(uri, throwableToFailedResult(t));
@@ -230,7 +235,7 @@ public class AppSearchManagerService extends SystemService {
}
@Override
- public void deleteByTypes(
+ public void deleteByTypes(@NonNull String databaseName,
List<String> schemaTypes, AndroidFuture<AppSearchBatchResult> callback) {
Preconditions.checkNotNull(schemaTypes);
Preconditions.checkNotNull(callback);
@@ -239,7 +244,7 @@ public class AppSearchManagerService extends SystemService {
final long callingIdentity = Binder.clearCallingIdentity();
try {
AppSearchImpl impl = ImplInstanceManager.getInstance(getContext(), callingUserId);
- String databaseName = makeDatabaseName(callingUid);
+ databaseName = rewriteDatabaseNameWithUid(databaseName, callingUid);
AppSearchBatchResult.Builder<String, Void> resultBuilder =
new AppSearchBatchResult.Builder<>();
for (int i = 0; i < schemaTypes.size(); i++) {
@@ -260,14 +265,15 @@ public class AppSearchManagerService extends SystemService {
}
@Override
- public void deleteAll(@NonNull AndroidFuture<AppSearchResult> callback) {
+ public void deleteAll(@NonNull String databaseName,
+ @NonNull AndroidFuture<AppSearchResult> callback) {
Preconditions.checkNotNull(callback);
int callingUid = Binder.getCallingUidOrThrow();
int callingUserId = UserHandle.getUserId(callingUid);
final long callingIdentity = Binder.clearCallingIdentity();
try {
AppSearchImpl impl = ImplInstanceManager.getInstance(getContext(), callingUserId);
- String databaseName = makeDatabaseName(callingUid);
+ databaseName = rewriteDatabaseNameWithUid(databaseName, callingUid);
impl.removeAll(databaseName);
callback.complete(AppSearchResult.newSuccessfulResult(null));
} catch (Throwable t) {
@@ -278,13 +284,13 @@ public class AppSearchManagerService extends SystemService {
}
/**
- * Returns a unique database name for the given uid.
+ * Rewrites the database name by adding a prefix of unique name for the given uid.
*
* <p>The current implementation returns the package name of the app with this uid in a
* format like {@code com.example.package} or {@code com.example.sharedname:5678}.
*/
@NonNull
- private String makeDatabaseName(int callingUid) {
+ private String rewriteDatabaseNameWithUid(String databaseName, int callingUid) {
// For regular apps, this call will return the package name. If callingUid is an
// android:sharedUserId, this value may be another type of name and have a :uid suffix.
String callingUidName = getContext().getPackageManager().getNameForUid(callingUid);
@@ -293,7 +299,7 @@ public class AppSearchManagerService extends SystemService {
throw new IllegalStateException(
"Failed to look up package name for uid " + callingUid);
}
- return callingUidName;
+ return callingUidName + CALLING_NAME_DATABASE_DELIMITER + databaseName;
}
private <ValueType> AppSearchResult<ValueType> throwableToFailedResult(
diff --git a/apex/jobscheduler/framework/java/android/os/DeviceIdleManager.java b/apex/jobscheduler/framework/java/android/os/DeviceIdleManager.java
index ada562ecebc6..752c36e53bf9 100644
--- a/apex/jobscheduler/framework/java/android/os/DeviceIdleManager.java
+++ b/apex/jobscheduler/framework/java/android/os/DeviceIdleManager.java
@@ -29,7 +29,6 @@ import android.content.Context;
*
* @hide
*/
-@TestApi
@SystemApi
@SystemService(Context.DEVICE_IDLE_CONTROLLER)
public class DeviceIdleManager {
diff --git a/apex/jobscheduler/framework/java/android/os/PowerWhitelistManager.java b/apex/jobscheduler/framework/java/android/os/PowerWhitelistManager.java
index 16dcd0674809..ab8722286efc 100644
--- a/apex/jobscheduler/framework/java/android/os/PowerWhitelistManager.java
+++ b/apex/jobscheduler/framework/java/android/os/PowerWhitelistManager.java
@@ -21,7 +21,6 @@ import android.annotation.NonNull;
import android.annotation.RequiresPermission;
import android.annotation.SystemApi;
import android.annotation.SystemService;
-import android.annotation.TestApi;
import android.content.Context;
import java.lang.annotation.Retention;
@@ -39,7 +38,6 @@ import java.util.List;
* @hide
*/
@SystemApi
-@TestApi
@SystemService(Context.POWER_WHITELIST_MANAGER)
public class PowerWhitelistManager {
private final Context mContext;
diff --git a/apex/jobscheduler/service/java/com/android/server/AppStateTrackerImpl.java b/apex/jobscheduler/service/java/com/android/server/AppStateTrackerImpl.java
index 8e26052ee08b..4dc9cf850893 100644
--- a/apex/jobscheduler/service/java/com/android/server/AppStateTrackerImpl.java
+++ b/apex/jobscheduler/service/java/com/android/server/AppStateTrackerImpl.java
@@ -1269,19 +1269,14 @@ public class AppStateTrackerImpl implements AppStateTracker {
}
/**
- * @deprecated use {@link #dump(IndentingPrintWriter)} instead.
- */
- @Deprecated
- public void dump(PrintWriter pw, String prefix) {
- dump(new IndentingPrintWriter(pw, " ").setIndent(prefix));
- }
-
- /**
* Dump the internal state to the given PrintWriter. Can be included in the dump
* of a binder service to be output on the shell command "dumpsys".
*/
public void dump(IndentingPrintWriter pw) {
synchronized (mLock) {
+ pw.println("Current AppStateTracker State:");
+
+ pw.increaseIndent();
pw.println("Forced App Standby Feature enabled: " + mForcedAppStandbyEnabled);
pw.print("Force all apps standby: ");
@@ -1339,6 +1334,7 @@ public class AppStateTrackerImpl implements AppStateTracker {
pw.decreaseIndent();
mStatLogger.dump(pw);
+ pw.decreaseIndent();
}
}
diff --git a/apex/jobscheduler/service/java/com/android/server/alarm/Alarm.java b/apex/jobscheduler/service/java/com/android/server/alarm/Alarm.java
index 45ea23321d15..04feef485048 100644
--- a/apex/jobscheduler/service/java/com/android/server/alarm/Alarm.java
+++ b/apex/jobscheduler/service/java/com/android/server/alarm/Alarm.java
@@ -31,7 +31,6 @@ import android.util.IndentingPrintWriter;
import android.util.TimeUtils;
import android.util.proto.ProtoOutputStream;
-import java.io.PrintWriter;
import java.text.SimpleDateFormat;
import java.util.Date;
@@ -200,15 +199,6 @@ class Alarm {
return sb.toString();
}
- /**
- * @deprecated Use {{@link #dump(IndentingPrintWriter, long, SimpleDateFormat)}} instead.
- */
- @Deprecated
- public void dump(PrintWriter pw, String prefix, long nowELAPSED, SimpleDateFormat sdf) {
- final IndentingPrintWriter ipw = new IndentingPrintWriter(pw, prefix, prefix);
- dump(ipw, nowELAPSED, sdf);
- }
-
private static String policyIndexToString(int index) {
switch (index) {
case REQUESTER_POLICY_INDEX:
diff --git a/apex/jobscheduler/service/java/com/android/server/alarm/AlarmManagerService.java b/apex/jobscheduler/service/java/com/android/server/alarm/AlarmManagerService.java
index 82819dab0f69..f196567bc391 100644
--- a/apex/jobscheduler/service/java/com/android/server/alarm/AlarmManagerService.java
+++ b/apex/jobscheduler/service/java/com/android/server/alarm/AlarmManagerService.java
@@ -345,10 +345,6 @@ public class AlarmManagerService extends SystemService {
return (i < 0) ? 0 : history.get(i);
}
- void dump(PrintWriter pw, String prefix, long nowElapsed) {
- dump(new IndentingPrintWriter(pw, " ").setIndent(prefix), nowElapsed);
- }
-
void dump(IndentingPrintWriter pw, long nowElapsed) {
pw.println("App Alarm history:");
pw.increaseIndent();
@@ -598,10 +594,6 @@ public class AlarmManagerService extends SystemService {
DEFAULT_APP_STANDBY_RESTRICTED_WINDOW));
}
- void dump(PrintWriter pw, String prefix) {
- dump(new IndentingPrintWriter(pw, " ").setIndent(prefix));
- }
-
void dump(IndentingPrintWriter pw) {
pw.println("Settings:");
@@ -1880,7 +1872,7 @@ public class AlarmManagerService extends SystemService {
if (args.length > 0 && "--proto".equals(args[0])) {
dumpProto(fd);
} else {
- dumpImpl(pw);
+ dumpImpl(new IndentingPrintWriter(pw, " "));
}
}
@@ -1892,18 +1884,20 @@ public class AlarmManagerService extends SystemService {
}
};
- void dumpImpl(PrintWriter pw) {
+ void dumpImpl(IndentingPrintWriter pw) {
synchronized (mLock) {
pw.println("Current Alarm Manager state:");
- mConstants.dump(pw, " ");
+ pw.increaseIndent();
+
+ mConstants.dump(pw);
pw.println();
if (mAppStateTracker != null) {
- mAppStateTracker.dump(pw, " ");
+ mAppStateTracker.dump(pw);
pw.println();
}
- pw.println(" App Standby Parole: " + mAppStandbyParole);
+ pw.println("App Standby Parole: " + mAppStandbyParole);
pw.println();
final long nowELAPSED = mInjector.getElapsedRealtime();
@@ -1911,7 +1905,7 @@ public class AlarmManagerService extends SystemService {
final long nowRTC = mInjector.getCurrentTimeMillis();
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS");
- pw.print(" nowRTC=");
+ pw.print("nowRTC=");
pw.print(nowRTC);
pw.print("=");
pw.print(sdf.format(new Date(nowRTC)));
@@ -1919,110 +1913,125 @@ public class AlarmManagerService extends SystemService {
pw.print(nowELAPSED);
pw.println();
- pw.print(" mLastTimeChangeClockTime=");
+ pw.print("mLastTimeChangeClockTime=");
pw.print(mLastTimeChangeClockTime);
pw.print("=");
pw.println(sdf.format(new Date(mLastTimeChangeClockTime)));
- pw.print(" mLastTimeChangeRealtime=");
+ pw.print("mLastTimeChangeRealtime=");
pw.println(mLastTimeChangeRealtime);
- pw.print(" mLastTickReceived=");
+ pw.print("mLastTickReceived=");
pw.println(sdf.format(new Date(mLastTickReceived)));
- pw.print(" mLastTickSet=");
+ pw.print("mLastTickSet=");
pw.println(sdf.format(new Date(mLastTickSet)));
if (RECORD_ALARMS_IN_HISTORY) {
pw.println();
- pw.println(" Recent TIME_TICK history:");
+ pw.println("Recent TIME_TICK history:");
+ pw.increaseIndent();
int i = mNextTickHistory;
do {
i--;
if (i < 0) i = TICK_HISTORY_DEPTH - 1;
final long time = mTickHistory[i];
- pw.print(" ");
pw.println((time > 0)
? sdf.format(new Date(nowRTC - (nowELAPSED - time)))
: "-");
} while (i != mNextTickHistory);
+ pw.decreaseIndent();
}
SystemServiceManager ssm = LocalServices.getService(SystemServiceManager.class);
if (ssm != null) {
pw.println();
- pw.print(" RuntimeStarted=");
+ pw.print("RuntimeStarted=");
pw.print(sdf.format(
new Date(nowRTC - nowELAPSED + ssm.getRuntimeStartElapsedTime())));
if (ssm.isRuntimeRestarted()) {
pw.print(" (Runtime restarted)");
}
pw.println();
- pw.print(" Runtime uptime (elapsed): ");
+
+ pw.print("Runtime uptime (elapsed): ");
TimeUtils.formatDuration(nowELAPSED, ssm.getRuntimeStartElapsedTime(), pw);
pw.println();
- pw.print(" Runtime uptime (uptime): ");
+
+ pw.print("Runtime uptime (uptime): ");
TimeUtils.formatDuration(nowUPTIME, ssm.getRuntimeStartUptime(), pw);
pw.println();
}
pw.println();
if (!mInteractive) {
- pw.print(" Time since non-interactive: ");
+ pw.print("Time since non-interactive: ");
TimeUtils.formatDuration(nowELAPSED - mNonInteractiveStartTime, pw);
pw.println();
}
- pw.print(" Max wakeup delay: ");
+ pw.print("Max wakeup delay: ");
TimeUtils.formatDuration(currentNonWakeupFuzzLocked(nowELAPSED), pw);
pw.println();
- pw.print(" Time since last dispatch: ");
+
+ pw.print("Time since last dispatch: ");
TimeUtils.formatDuration(nowELAPSED - mLastAlarmDeliveryTime, pw);
pw.println();
- pw.print(" Next non-wakeup delivery time: ");
+
+ pw.print("Next non-wakeup delivery time: ");
TimeUtils.formatDuration(mNextNonWakeupDeliveryTime, nowELAPSED, pw);
pw.println();
long nextWakeupRTC = mNextWakeup + (nowRTC - nowELAPSED);
long nextNonWakeupRTC = mNextNonWakeup + (nowRTC - nowELAPSED);
- pw.print(" Next non-wakeup alarm: ");
+ pw.print("Next non-wakeup alarm: ");
TimeUtils.formatDuration(mNextNonWakeup, nowELAPSED, pw);
pw.print(" = ");
pw.print(mNextNonWakeup);
pw.print(" = ");
pw.println(sdf.format(new Date(nextNonWakeupRTC)));
- pw.print(" set at ");
+
+ pw.increaseIndent();
+ pw.print("set at ");
TimeUtils.formatDuration(mNextNonWakeUpSetAt, nowELAPSED, pw);
+ pw.decreaseIndent();
pw.println();
- pw.print(" Next wakeup alarm: ");
+
+ pw.print("Next wakeup alarm: ");
TimeUtils.formatDuration(mNextWakeup, nowELAPSED, pw);
pw.print(" = ");
pw.print(mNextWakeup);
pw.print(" = ");
pw.println(sdf.format(new Date(nextWakeupRTC)));
- pw.print(" set at ");
+
+ pw.increaseIndent();
+ pw.print("set at ");
TimeUtils.formatDuration(mNextWakeUpSetAt, nowELAPSED, pw);
+ pw.decreaseIndent();
pw.println();
- pw.print(" Next kernel non-wakeup alarm: ");
+ pw.print("Next kernel non-wakeup alarm: ");
TimeUtils.formatDuration(mInjector.getNextAlarm(ELAPSED_REALTIME), pw);
pw.println();
- pw.print(" Next kernel wakeup alarm: ");
+ pw.print("Next kernel wakeup alarm: ");
TimeUtils.formatDuration(mInjector.getNextAlarm(ELAPSED_REALTIME_WAKEUP), pw);
pw.println();
- pw.print(" Last wakeup: ");
+ pw.print("Last wakeup: ");
TimeUtils.formatDuration(mLastWakeup, nowELAPSED, pw);
pw.print(" = ");
pw.println(mLastWakeup);
- pw.print(" Last trigger: ");
+
+ pw.print("Last trigger: ");
TimeUtils.formatDuration(mLastTrigger, nowELAPSED, pw);
pw.print(" = ");
pw.println(mLastTrigger);
- pw.print(" Num time change events: ");
+
+ pw.print("Num time change events: ");
pw.println(mNumTimeChanged);
pw.println();
- pw.println(" Next alarm clock information: ");
+ pw.println("Next alarm clock information: ");
+ pw.increaseIndent();
final TreeSet<Integer> users = new TreeSet<>();
for (int i = 0; i < mNextAlarmClockForUser.size(); i++) {
users.add(mNextAlarmClockForUser.keyAt(i));
@@ -2034,7 +2043,7 @@ public class AlarmManagerService extends SystemService {
final AlarmManager.AlarmClockInfo next = mNextAlarmClockForUser.get(user);
final long time = next != null ? next.getTriggerTime() : 0;
final boolean pendingSend = mPendingSendNextAlarmClockChangedForUser.get(user);
- pw.print(" user:");
+ pw.print("user:");
pw.print(user);
pw.print(" pendingSend:");
pw.print(pendingSend);
@@ -2048,26 +2057,31 @@ public class AlarmManagerService extends SystemService {
}
pw.println();
}
+ pw.decreaseIndent();
+
if (mAlarmStore.size() > 0) {
pw.println();
- final IndentingPrintWriter ipw = new IndentingPrintWriter(pw, " ", " ");
- mAlarmStore.dump(ipw, nowELAPSED, sdf);
+ mAlarmStore.dump(pw, nowELAPSED, sdf);
}
pw.println();
- pw.println(" Pending user blocked background alarms: ");
+
+ pw.println("Pending user blocked background alarms: ");
+ pw.increaseIndent();
boolean blocked = false;
for (int i = 0; i < mPendingBackgroundAlarms.size(); i++) {
final ArrayList<Alarm> blockedAlarms = mPendingBackgroundAlarms.valueAt(i);
if (blockedAlarms != null && blockedAlarms.size() > 0) {
blocked = true;
- dumpAlarmList(pw, blockedAlarms, " ", nowELAPSED, sdf);
+ dumpAlarmList(pw, blockedAlarms, nowELAPSED, sdf);
}
}
if (!blocked) {
- pw.println(" none");
+ pw.println("none");
}
+ pw.decreaseIndent();
pw.println();
- pw.print(" Pending alarms per uid: [");
+
+ pw.print("Pending alarms per uid: [");
for (int i = 0; i < mAlarmsPerUid.size(); i++) {
if (i > 0) {
pw.print(", ");
@@ -2079,75 +2093,90 @@ public class AlarmManagerService extends SystemService {
pw.println("]");
pw.println();
- mAppWakeupHistory.dump(pw, " ", nowELAPSED);
+ mAppWakeupHistory.dump(pw, nowELAPSED);
if (mPendingIdleUntil != null || mPendingWhileIdleAlarms.size() > 0) {
pw.println();
- pw.println(" Idle mode state:");
- pw.print(" Idling until: ");
+ pw.println("Idle mode state:");
+
+ pw.increaseIndent();
+ pw.print("Idling until: ");
if (mPendingIdleUntil != null) {
pw.println(mPendingIdleUntil);
- mPendingIdleUntil.dump(pw, " ", nowELAPSED, sdf);
+ mPendingIdleUntil.dump(pw, nowELAPSED, sdf);
} else {
pw.println("null");
}
- pw.println(" Pending alarms:");
- dumpAlarmList(pw, mPendingWhileIdleAlarms, " ", nowELAPSED, sdf);
+ pw.println("Pending alarms:");
+ dumpAlarmList(pw, mPendingWhileIdleAlarms, nowELAPSED, sdf);
+ pw.decreaseIndent();
}
if (mNextWakeFromIdle != null) {
pw.println();
- pw.print(" Next wake from idle: ");
+ pw.print("Next wake from idle: ");
pw.println(mNextWakeFromIdle);
- mNextWakeFromIdle.dump(pw, " ", nowELAPSED, sdf);
+
+ pw.increaseIndent();
+ mNextWakeFromIdle.dump(pw, nowELAPSED, sdf);
+ pw.decreaseIndent();
}
pw.println();
- pw.print(" Past-due non-wakeup alarms: ");
+ pw.print("Past-due non-wakeup alarms: ");
if (mPendingNonWakeupAlarms.size() > 0) {
pw.println(mPendingNonWakeupAlarms.size());
- dumpAlarmList(pw, mPendingNonWakeupAlarms, " ", nowELAPSED, sdf);
+
+ pw.increaseIndent();
+ dumpAlarmList(pw, mPendingNonWakeupAlarms, nowELAPSED, sdf);
+ pw.decreaseIndent();
} else {
pw.println("(none)");
}
- pw.print(" Number of delayed alarms: ");
+ pw.increaseIndent();
+ pw.print("Number of delayed alarms: ");
pw.print(mNumDelayedAlarms);
pw.print(", total delay time: ");
TimeUtils.formatDuration(mTotalDelayTime, pw);
pw.println();
- pw.print(" Max delay time: ");
+
+ pw.print("Max delay time: ");
TimeUtils.formatDuration(mMaxDelayTime, pw);
pw.print(", max non-interactive time: ");
TimeUtils.formatDuration(mNonInteractiveTime, pw);
pw.println();
+ pw.decreaseIndent();
pw.println();
- pw.print(" Broadcast ref count: ");
+ pw.print("Broadcast ref count: ");
pw.println(mBroadcastRefCount);
- pw.print(" PendingIntent send count: ");
+ pw.print("PendingIntent send count: ");
pw.println(mSendCount);
- pw.print(" PendingIntent finish count: ");
+ pw.print("PendingIntent finish count: ");
pw.println(mSendFinishCount);
- pw.print(" Listener send count: ");
+ pw.print("Listener send count: ");
pw.println(mListenerCount);
- pw.print(" Listener finish count: ");
+ pw.print("Listener finish count: ");
pw.println(mListenerFinishCount);
pw.println();
if (mInFlight.size() > 0) {
pw.println("Outstanding deliveries:");
+ pw.increaseIndent();
for (int i = 0; i < mInFlight.size(); i++) {
- pw.print(" #");
+ pw.print("#");
pw.print(i);
pw.print(": ");
pw.println(mInFlight.get(i));
}
+ pw.decreaseIndent();
pw.println();
}
if (mLastAllowWhileIdleDispatch.size() > 0) {
- pw.println(" Last allow while idle dispatch times:");
+ pw.println("Last allow while idle dispatch times:");
+ pw.increaseIndent();
for (int i = 0; i < mLastAllowWhileIdleDispatch.size(); i++) {
- pw.print(" UID ");
+ pw.print("UID ");
final int uid = mLastAllowWhileIdleDispatch.keyAt(i);
UserHandle.formatUid(pw, uid);
pw.print(": ");
@@ -2163,9 +2192,10 @@ public class AlarmManagerService extends SystemService {
pw.println();
}
+ pw.decreaseIndent();
}
- pw.print(" mUseAllowWhileIdleShortTime: [");
+ pw.print("mUseAllowWhileIdleShortTime: [");
for (int i = 0; i < mUseAllowWhileIdleShortTime.size(); i++) {
if (mUseAllowWhileIdleShortTime.valueAt(i)) {
UserHandle.formatUid(pw, mUseAllowWhileIdleShortTime.keyAt(i));
@@ -2175,7 +2205,7 @@ public class AlarmManagerService extends SystemService {
pw.println("]");
pw.println();
- if (mLog.dump(pw, " Recent problems", " ")) {
+ if (mLog.dump(pw, "Recent problems:")) {
pw.println();
}
@@ -2218,10 +2248,10 @@ public class AlarmManagerService extends SystemService {
}
}
if (len > 0) {
- pw.println(" Top Alarms:");
+ pw.println("Top Alarms:");
+ pw.increaseIndent();
for (int i = 0; i < len; i++) {
FilterStats fs = topFilters[i];
- pw.print(" ");
if (fs.nesting > 0) pw.print("*ACTIVE* ");
TimeUtils.formatDuration(fs.aggregateTime, pw);
pw.print(" running, ");
@@ -2233,20 +2263,22 @@ public class AlarmManagerService extends SystemService {
pw.print(":");
pw.print(fs.mBroadcastStats.mPackageName);
pw.println();
- pw.print(" ");
+
+ pw.increaseIndent();
pw.print(fs.mTag);
pw.println();
+ pw.decreaseIndent();
}
+ pw.decreaseIndent();
}
- pw.println(" ");
- pw.println(" Alarm Stats:");
+ pw.println();
+ pw.println("Alarm Stats:");
final ArrayList<FilterStats> tmpFilters = new ArrayList<FilterStats>();
for (int iu = 0; iu < mBroadcastStats.size(); iu++) {
ArrayMap<String, BroadcastStats> uidStats = mBroadcastStats.valueAt(iu);
for (int ip = 0; ip < uidStats.size(); ip++) {
BroadcastStats bs = uidStats.valueAt(ip);
- pw.print(" ");
if (bs.nesting > 0) pw.print("*ACTIVE* ");
UserHandle.formatUid(pw, bs.mUid);
pw.print(":");
@@ -2256,14 +2288,15 @@ public class AlarmManagerService extends SystemService {
pw.print(" running, ");
pw.print(bs.numWakeup);
pw.println(" wakeups:");
+
tmpFilters.clear();
for (int is = 0; is < bs.filterStats.size(); is++) {
tmpFilters.add(bs.filterStats.valueAt(is));
}
Collections.sort(tmpFilters, comparator);
+ pw.increaseIndent();
for (int i = 0; i < tmpFilters.size(); i++) {
FilterStats fs = tmpFilters.get(i);
- pw.print(" ");
if (fs.nesting > 0) pw.print("*ACTIVE* ");
TimeUtils.formatDuration(fs.aggregateTime, pw);
pw.print(" ");
@@ -2273,28 +2306,32 @@ public class AlarmManagerService extends SystemService {
pw.print(" alarms, last ");
TimeUtils.formatDuration(fs.lastTime, nowELAPSED, pw);
pw.println(":");
- pw.print(" ");
+
+ pw.increaseIndent();
pw.print(fs.mTag);
pw.println();
+ pw.decreaseIndent();
}
+ pw.decreaseIndent();
}
}
pw.println();
- mStatLogger.dump(pw, " ");
+ mStatLogger.dump(pw);
if (RECORD_DEVICE_IDLE_ALARMS) {
pw.println();
- pw.println(" Allow while idle dispatches:");
+ pw.println("Allow while idle dispatches:");
+ pw.increaseIndent();
for (int i = 0; i < mAllowWhileIdleDispatches.size(); i++) {
IdleDispatchEntry ent = mAllowWhileIdleDispatches.get(i);
- pw.print(" ");
TimeUtils.formatDuration(ent.elapsedRealtime, nowELAPSED, pw);
pw.print(": ");
UserHandle.formatUid(pw, ent.uid);
pw.print(":");
pw.println(ent.pkg);
+
+ pw.increaseIndent();
if (ent.op != null) {
- pw.print(" ");
pw.print(ent.op);
pw.print(" / ");
pw.print(ent.tag);
@@ -2305,7 +2342,9 @@ public class AlarmManagerService extends SystemService {
}
pw.println();
}
+ pw.decreaseIndent();
}
+ pw.decreaseIndent();
}
}
}
@@ -3044,12 +3083,6 @@ public class AlarmManagerService extends SystemService {
}
}
- private static final void dumpAlarmList(PrintWriter pw, ArrayList<Alarm> list,
- String prefix, long nowELAPSED, SimpleDateFormat sdf) {
- final IndentingPrintWriter ipw = new IndentingPrintWriter(pw, prefix, prefix);
- dumpAlarmList(ipw, list, nowELAPSED, sdf);
- }
-
static final void dumpAlarmList(IndentingPrintWriter ipw, ArrayList<Alarm> list,
long nowELAPSED, SimpleDateFormat sdf) {
for (int i = list.size() - 1; i >= 0; i--) {
diff --git a/api/Android.bp b/api/Android.bp
index 388bb68e8999..21a7166d1354 100644
--- a/api/Android.bp
+++ b/api/Android.bp
@@ -62,11 +62,18 @@ genrule {
out: ["current.txt"],
tools: ["metalava"],
cmd: "$(location metalava) --no-banner --format=v2 $(in) --api $(out)",
- dist: {
- targets: ["sdk", "win_sdk"],
- dir: "apistubs/android/public/api",
- dest: "android.txt",
- },
+ dists: [
+ {
+ targets: ["droidcore"],
+ dir: "api",
+ dest: "current.txt",
+ },
+ {
+ targets: ["sdk", "win_sdk"],
+ dir: "apistubs/android/public/api",
+ dest: "android.txt",
+ },
+ ],
}
genrule {
@@ -87,6 +94,13 @@ genrule {
out: ["removed.txt"],
tools: ["metalava"],
cmd: "$(location metalava) --no-banner --format=v2 $(in) --api $(out)",
+ dists: [
+ {
+ targets: ["droidcore"],
+ dir: "api",
+ dest: "removed.txt",
+ },
+ ],
}
genrule {
@@ -106,11 +120,18 @@ genrule {
out: ["system-current.txt"],
tools: ["metalava"],
cmd: "$(location metalava) --no-banner --format=v2 $(in) --api $(out)",
- dist: {
- targets: ["sdk", "win_sdk"],
- dir: "apistubs/android/system/api",
- dest: "android.txt",
- },
+ dists: [
+ {
+ targets: ["droidcore"],
+ dir: "api",
+ dest: "system-current.txt",
+ },
+ {
+ targets: ["sdk", "win_sdk"],
+ dir: "apistubs/android/system/api",
+ dest: "android.txt",
+ },
+ ],
}
genrule {
@@ -130,6 +151,13 @@ genrule {
out: ["system-removed.txt"],
tools: ["metalava"],
cmd: "$(location metalava) --no-banner --format=v2 $(in) --api $(out)",
+ dists: [
+ {
+ targets: ["droidcore"],
+ dir: "api",
+ dest: "system-removed.txt",
+ },
+ ],
}
genrule {
@@ -149,11 +177,18 @@ genrule {
out: ["module-lib-current.txt"],
tools: ["metalava"],
cmd: "$(location metalava) --no-banner --format=v2 $(in) --api $(out)",
- dist: {
- targets: ["sdk", "win_sdk"],
- dir: "apistubs/android/module-lib/api",
- dest: "android.txt",
- },
+ dists: [
+ {
+ targets: ["droidcore"],
+ dir: "api",
+ dest: "module-lib-current.txt",
+ },
+ {
+ targets: ["sdk", "win_sdk"],
+ dir: "apistubs/android/module-lib/api",
+ dest: "android.txt",
+ },
+ ],
}
genrule {
@@ -173,6 +208,13 @@ genrule {
out: ["module-lib-removed.txt"],
tools: ["metalava"],
cmd: "$(location metalava) --no-banner --format=v2 $(in) --api $(out)",
+ dists: [
+ {
+ targets: ["droidcore"],
+ dir: "api",
+ dest: "module-lib-removed.txt",
+ },
+ ],
}
genrule {
diff --git a/api/current.txt b/api/current.txt
index 6b42af82000e..d8d4adcb78b8 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -2851,6 +2851,7 @@ package android.accessibilityservice {
method public int describeContents();
method public int getDisplayId();
method public int getGestureId();
+ method @NonNull public java.util.List<android.view.MotionEvent> getMotionEvents();
method public void writeToParcel(@NonNull android.os.Parcel, int);
field @NonNull public static final android.os.Parcelable.Creator<android.accessibilityservice.AccessibilityGestureEvent> CREATOR;
}
@@ -2932,6 +2933,7 @@ package android.accessibilityservice {
field public static final int GESTURE_SWIPE_UP_AND_DOWN = 7; // 0x7
field public static final int GESTURE_SWIPE_UP_AND_LEFT = 13; // 0xd
field public static final int GESTURE_SWIPE_UP_AND_RIGHT = 14; // 0xe
+ field public static final int GESTURE_UNKNOWN = 0; // 0x0
field public static final int GLOBAL_ACTION_ACCESSIBILITY_ALL_APPS = 14; // 0xe
field public static final int GLOBAL_ACTION_ACCESSIBILITY_BUTTON = 11; // 0xb
field public static final int GLOBAL_ACTION_ACCESSIBILITY_BUTTON_CHOOSER = 12; // 0xc
@@ -3047,6 +3049,7 @@ package android.accessibilityservice {
field public static final int FLAG_REQUEST_SHORTCUT_WARNING_DIALOG_SPOKEN_FEEDBACK = 1024; // 0x400
field public static final int FLAG_REQUEST_TOUCH_EXPLORATION_MODE = 4; // 0x4
field public static final int FLAG_RETRIEVE_INTERACTIVE_WINDOWS = 64; // 0x40
+ field public static final int FLAG_SEND_MOTION_EVENTS = 16384; // 0x4000
field public static final int FLAG_SERVICE_HANDLES_DOUBLE_TAP = 2048; // 0x800
field public int eventTypes;
field public int feedbackType;
@@ -10668,12 +10671,15 @@ package android.content {
field public static final String ACTION_PACKAGE_CHANGED = "android.intent.action.PACKAGE_CHANGED";
field public static final String ACTION_PACKAGE_DATA_CLEARED = "android.intent.action.PACKAGE_DATA_CLEARED";
field public static final String ACTION_PACKAGE_FIRST_LAUNCH = "android.intent.action.PACKAGE_FIRST_LAUNCH";
+ field public static final String ACTION_PACKAGE_FULLY_LOADED = "android.intent.action.PACKAGE_FULLY_LOADED";
field public static final String ACTION_PACKAGE_FULLY_REMOVED = "android.intent.action.PACKAGE_FULLY_REMOVED";
field @Deprecated public static final String ACTION_PACKAGE_INSTALL = "android.intent.action.PACKAGE_INSTALL";
field public static final String ACTION_PACKAGE_NEEDS_VERIFICATION = "android.intent.action.PACKAGE_NEEDS_VERIFICATION";
field public static final String ACTION_PACKAGE_REMOVED = "android.intent.action.PACKAGE_REMOVED";
field public static final String ACTION_PACKAGE_REPLACED = "android.intent.action.PACKAGE_REPLACED";
field public static final String ACTION_PACKAGE_RESTARTED = "android.intent.action.PACKAGE_RESTARTED";
+ field public static final String ACTION_PACKAGE_STARTABLE = "android.intent.action.PACKAGE_STARTABLE";
+ field public static final String ACTION_PACKAGE_UNSTARTABLE = "android.intent.action.PACKAGE_UNSTARTABLE";
field public static final String ACTION_PACKAGE_VERIFIED = "android.intent.action.PACKAGE_VERIFIED";
field public static final String ACTION_PASTE = "android.intent.action.PASTE";
field public static final String ACTION_PICK = "android.intent.action.PICK";
@@ -10814,7 +10820,6 @@ package android.content {
field public static final String EXTRA_REFERRER = "android.intent.extra.REFERRER";
field public static final String EXTRA_REFERRER_NAME = "android.intent.extra.REFERRER_NAME";
field public static final String EXTRA_REMOTE_INTENT_TOKEN = "android.intent.extra.remote_intent_token";
- field public static final String EXTRA_REMOVED_BY_SYSTEM = "android.intent.extra.REMOVED_BY_SYSTEM";
field public static final String EXTRA_REPLACEMENT_EXTRAS = "android.intent.extra.REPLACEMENT_EXTRAS";
field public static final String EXTRA_REPLACING = "android.intent.extra.REPLACING";
field public static final String EXTRA_RESTRICTIONS_BUNDLE = "android.intent.extra.restrictions_bundle";
@@ -10838,7 +10843,9 @@ package android.content {
field public static final String EXTRA_TIMEZONE = "time-zone";
field public static final String EXTRA_TITLE = "android.intent.extra.TITLE";
field public static final String EXTRA_UID = "android.intent.extra.UID";
+ field public static final String EXTRA_UNSTARTABLE_REASON = "android.intent.extra.UNSTARTABLE_REASON";
field public static final String EXTRA_USER = "android.intent.extra.USER";
+ field public static final String EXTRA_USER_INITIATED = "android.intent.extra.USER_INITIATED";
field public static final int FILL_IN_ACTION = 1; // 0x1
field public static final int FILL_IN_CATEGORIES = 4; // 0x4
field public static final int FILL_IN_CLIP_DATA = 128; // 0x80
@@ -12258,7 +12265,7 @@ package android.content.pm {
field @Deprecated public static final int GET_DISABLED_UNTIL_USED_COMPONENTS = 32768; // 0x8000
field public static final int GET_GIDS = 256; // 0x100
field public static final int GET_INSTRUMENTATION = 16; // 0x10
- field public static final int GET_INTENT_FILTERS = 32; // 0x20
+ field @Deprecated public static final int GET_INTENT_FILTERS = 32; // 0x20
field public static final int GET_META_DATA = 128; // 0x80
field public static final int GET_PERMISSIONS = 4096; // 0x1000
field public static final int GET_PROVIDERS = 8; // 0x8
@@ -12297,6 +12304,9 @@ package android.content.pm {
field public static final int SYNCHRONOUS = 2; // 0x2
field @Nullable public static final java.util.List<java.security.cert.Certificate> TRUST_ALL;
field @NonNull public static final java.util.List<java.security.cert.Certificate> TRUST_NONE;
+ field public static final int UNSTARTABLE_REASON_CONNECTION_ERROR = 1; // 0x1
+ field public static final int UNSTARTABLE_REASON_INSUFFICIENT_STORAGE = 2; // 0x2
+ field public static final int UNSTARTABLE_REASON_UNKNOWN = 0; // 0x0
field public static final int VERIFICATION_ALLOW = 1; // 0x1
field public static final int VERIFICATION_REJECT = -1; // 0xffffffff
field public static final int VERSION_CODE_HIGHEST = -1; // 0xffffffff
@@ -31846,6 +31856,7 @@ package android.net.wifi.aware {
method public int getMaxServiceNameLength();
method public int getMaxServiceSpecificInfoLength();
method public int getSupportedCipherSuites();
+ method public boolean isInstantCommunicationModeSupported();
method public void writeToParcel(android.os.Parcel, int);
field @NonNull public static final android.os.Parcelable.Creator<android.net.wifi.aware.Characteristics> CREATOR;
field public static final int WIFI_AWARE_CIPHER_SUITE_NCS_SK_128 = 1; // 0x1
@@ -31944,6 +31955,7 @@ package android.net.wifi.aware {
method public android.net.wifi.aware.Characteristics getCharacteristics();
method public boolean isAvailable();
method public boolean isDeviceAttached();
+ method public boolean isInstantCommunicationModeEnabled();
field public static final String ACTION_WIFI_AWARE_STATE_CHANGED = "android.net.wifi.aware.action.WIFI_AWARE_STATE_CHANGED";
field public static final int WIFI_AWARE_DATA_PATH_ROLE_INITIATOR = 0; // 0x0
field public static final int WIFI_AWARE_DATA_PATH_ROLE_RESPONDER = 1; // 0x1
@@ -47074,6 +47086,7 @@ package android.telephony {
}
public static final class CarrierConfigManager.Ims {
+ field public static final String KEY_IMS_SINGLE_REGISTRATION_REQUIRED_BOOL = "ims.ims_single_registration_required_bool";
field public static final String KEY_PREFIX = "ims.";
field public static final String KEY_WIFI_OFF_DEFERRING_TIME_MILLIS_INT = "ims.wifi_off_deferring_time_millis_int";
}
@@ -48078,6 +48091,7 @@ package android.telephony {
}
public class SignalStrength implements android.os.Parcelable {
+ ctor public SignalStrength(@NonNull android.telephony.SignalStrength);
method public int describeContents();
method @Deprecated public int getCdmaDbm();
method @Deprecated public int getCdmaEcio();
@@ -48585,6 +48599,9 @@ package android.telephony {
field public static final int DATA_ENABLED_REASON_USER = 0; // 0x0
field public static final int DATA_SUSPENDED = 3; // 0x3
field public static final int DATA_UNKNOWN = -1; // 0xffffffff
+ field public static final int ERI_FLASH = 2; // 0x2
+ field public static final int ERI_OFF = 1; // 0x1
+ field public static final int ERI_ON = 0; // 0x0
field public static final String EXTRA_ACTIVE_SIM_SUPPORTED_COUNT = "android.telephony.extra.ACTIVE_SIM_SUPPORTED_COUNT";
field public static final String EXTRA_CALL_VOICEMAIL_INTENT = "android.telephony.extra.CALL_VOICEMAIL_INTENT";
field public static final String EXTRA_CARRIER_ID = "android.telephony.extra.CARRIER_ID";
diff --git a/api/module-lib-current.txt b/api/module-lib-current.txt
index 993d31fb4161..872f1f2c0591 100644
--- a/api/module-lib-current.txt
+++ b/api/module-lib-current.txt
@@ -157,8 +157,6 @@ package android.os {
public interface Parcelable {
method public default int getStability();
- field public static final int PARCELABLE_STABILITY_LOCAL = 0; // 0x0
- field public static final int PARCELABLE_STABILITY_VINTF = 1; // 0x1
}
public class StatsFrameworkInitializer {
diff --git a/api/system-current.txt b/api/system-current.txt
index 25008f427c03..3207165ac377 100644
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -225,6 +225,7 @@ package android {
field public static final String SET_WALLPAPER_COMPONENT = "android.permission.SET_WALLPAPER_COMPONENT";
field public static final String SHOW_KEYGUARD_MESSAGE = "android.permission.SHOW_KEYGUARD_MESSAGE";
field public static final String SHUTDOWN = "android.permission.SHUTDOWN";
+ field public static final String START_ACTIVITIES_FROM_BACKGROUND = "android.permission.START_ACTIVITIES_FROM_BACKGROUND";
field public static final String STATUS_BAR_SERVICE = "android.permission.STATUS_BAR_SERVICE";
field public static final String STOP_APP_SWITCHES = "android.permission.STOP_APP_SWITCHES";
field public static final String SUBSTITUTE_NOTIFICATION_APP_NAME = "android.permission.SUBSTITUTE_NOTIFICATION_APP_NAME";
@@ -594,7 +595,7 @@ package android.app {
public class BroadcastOptions {
method public static android.app.BroadcastOptions makeBasic();
- method @RequiresPermission("android.permission.START_ACTIVITIES_FROM_BACKGROUND") public void setBackgroundActivityStartsAllowed(boolean);
+ method @RequiresPermission(android.Manifest.permission.START_ACTIVITIES_FROM_BACKGROUND) public void setBackgroundActivityStartsAllowed(boolean);
method public void setDontSendToRestrictedApps(boolean);
method @RequiresPermission(android.Manifest.permission.CHANGE_DEVICE_IDLE_TEMP_WHITELIST) public void setTemporaryAppWhitelistDuration(long);
method public android.os.Bundle toBundle();
@@ -915,6 +916,7 @@ package android.app.admin {
field public static final int PROVISIONING_TRIGGER_QR_CODE = 2; // 0x2
field public static final int PROVISIONING_TRIGGER_UNSPECIFIED = 0; // 0x0
field public static final int STATE_USER_PROFILE_COMPLETE = 4; // 0x4
+ field public static final int STATE_USER_PROFILE_FINALIZED = 5; // 0x5
field public static final int STATE_USER_SETUP_COMPLETE = 2; // 0x2
field public static final int STATE_USER_SETUP_FINALIZED = 3; // 0x3
field public static final int STATE_USER_SETUP_INCOMPLETE = 1; // 0x1
@@ -1802,6 +1804,7 @@ package android.content {
field public static final String APP_PREDICTION_SERVICE = "app_prediction";
field public static final String BACKUP_SERVICE = "backup";
field public static final String BATTERY_STATS_SERVICE = "batterystats";
+ field public static final int BIND_ALLOW_BACKGROUND_ACTIVITY_STARTS = 1048576; // 0x100000
field public static final String BUGREPORT_SERVICE = "bugreport";
field public static final String CONTENT_SUGGESTIONS_SERVICE = "content_suggestions";
field public static final String CONTEXTHUB_SERVICE = "contexthub";
@@ -5208,12 +5211,45 @@ package android.media.tv.tuner.filter {
public class AvSettings extends android.media.tv.tuner.filter.Settings {
method @NonNull public static android.media.tv.tuner.filter.AvSettings.Builder builder(int, boolean);
+ method public int getAudioStreamType();
+ method public int getVideoStreamType();
method public boolean isPassthrough();
+ field public static final int AUDIO_STREAM_TYPE_AAC = 6; // 0x6
+ field public static final int AUDIO_STREAM_TYPE_AC3 = 7; // 0x7
+ field public static final int AUDIO_STREAM_TYPE_AC4 = 9; // 0x9
+ field public static final int AUDIO_STREAM_TYPE_DRA = 15; // 0xf
+ field public static final int AUDIO_STREAM_TYPE_DTS = 10; // 0xa
+ field public static final int AUDIO_STREAM_TYPE_DTS_HD = 11; // 0xb
+ field public static final int AUDIO_STREAM_TYPE_EAC3 = 8; // 0x8
+ field public static final int AUDIO_STREAM_TYPE_MP3 = 2; // 0x2
+ field public static final int AUDIO_STREAM_TYPE_MPEG1 = 3; // 0x3
+ field public static final int AUDIO_STREAM_TYPE_MPEG2 = 4; // 0x4
+ field public static final int AUDIO_STREAM_TYPE_MPEGH = 5; // 0x5
+ field public static final int AUDIO_STREAM_TYPE_OPUS = 13; // 0xd
+ field public static final int AUDIO_STREAM_TYPE_PCM = 1; // 0x1
+ field public static final int AUDIO_STREAM_TYPE_UNDEFINED = 0; // 0x0
+ field public static final int AUDIO_STREAM_TYPE_VORBIS = 14; // 0xe
+ field public static final int AUDIO_STREAM_TYPE_WMA = 12; // 0xc
+ field public static final int VIDEO_STREAM_TYPE_AV1 = 10; // 0xa
+ field public static final int VIDEO_STREAM_TYPE_AVC = 5; // 0x5
+ field public static final int VIDEO_STREAM_TYPE_AVS = 11; // 0xb
+ field public static final int VIDEO_STREAM_TYPE_AVS2 = 12; // 0xc
+ field public static final int VIDEO_STREAM_TYPE_HEVC = 6; // 0x6
+ field public static final int VIDEO_STREAM_TYPE_MPEG1 = 2; // 0x2
+ field public static final int VIDEO_STREAM_TYPE_MPEG2 = 3; // 0x3
+ field public static final int VIDEO_STREAM_TYPE_MPEG4P2 = 4; // 0x4
+ field public static final int VIDEO_STREAM_TYPE_RESERVED = 1; // 0x1
+ field public static final int VIDEO_STREAM_TYPE_UNDEFINED = 0; // 0x0
+ field public static final int VIDEO_STREAM_TYPE_VC1 = 7; // 0x7
+ field public static final int VIDEO_STREAM_TYPE_VP8 = 8; // 0x8
+ field public static final int VIDEO_STREAM_TYPE_VP9 = 9; // 0x9
}
public static class AvSettings.Builder {
method @NonNull public android.media.tv.tuner.filter.AvSettings build();
+ method @NonNull public android.media.tv.tuner.filter.AvSettings.Builder setAudioStreamType(int);
method @NonNull public android.media.tv.tuner.filter.AvSettings.Builder setPassthrough(boolean);
+ method @NonNull public android.media.tv.tuner.filter.AvSettings.Builder setVideoStreamType(int);
}
public class DownloadEvent extends android.media.tv.tuner.filter.FilterEvent {
@@ -5291,7 +5327,7 @@ package android.media.tv.tuner.filter {
method @NonNull public static android.media.tv.tuner.filter.IpFilterConfiguration.Builder builder();
method @NonNull @Size(min=4, max=16) public byte[] getDstIpAddress();
method public int getDstPort();
- method public int getIpFilterContextId();
+ method @IntRange(from=0, to=61439) public int getIpFilterContextId();
method @NonNull @Size(min=4, max=16) public byte[] getSrcIpAddress();
method public int getSrcPort();
method public int getType();
@@ -5327,6 +5363,7 @@ package android.media.tv.tuner.filter {
method public boolean isPrivateData();
method public boolean isPtsPresent();
method public boolean isSecureMemory();
+ method public void release();
}
public final class MmtpFilterConfiguration extends android.media.tv.tuner.filter.FilterConfiguration {
@@ -5833,6 +5870,7 @@ package android.media.tv.tuner.frontend {
method public int getSymbolRate();
method public int getType();
method public int getVcmMode();
+ method public boolean isDiseqcRxMessage();
field public static final int MODULATION_AUTO = 1; // 0x1
field public static final int MODULATION_MOD_128APSK = 2048; // 0x800
field public static final int MODULATION_MOD_16APSK = 256; // 0x100
@@ -5876,6 +5914,7 @@ package android.media.tv.tuner.frontend {
public static class DvbsFrontendSettings.Builder {
method @NonNull public android.media.tv.tuner.frontend.DvbsFrontendSettings build();
method @NonNull public android.media.tv.tuner.frontend.DvbsFrontendSettings.Builder setCodeRate(@Nullable android.media.tv.tuner.frontend.DvbsCodeRate);
+ method @NonNull public android.media.tv.tuner.frontend.DvbsFrontendSettings.Builder setDiseqcRxMessage(boolean);
method @IntRange(from=1) @NonNull public android.media.tv.tuner.frontend.DvbsFrontendSettings.Builder setFrequency(int);
method @NonNull public android.media.tv.tuner.frontend.DvbsFrontendSettings.Builder setInputStreamId(int);
method @NonNull public android.media.tv.tuner.frontend.DvbsFrontendSettings.Builder setModulation(int);
@@ -6077,14 +6116,21 @@ package android.media.tv.tuner.frontend {
public class FrontendStatus {
method public int getAgc();
method @NonNull public android.media.tv.tuner.frontend.FrontendStatus.Atsc3PlpTuningInfo[] getAtsc3PlpTuningInfo();
+ method public int getBandwidth();
method public int getBer();
+ method @NonNull public int[] getBers();
+ method @NonNull public int[] getCodeRates();
method public int getFreqOffset();
+ method public int getGuardInterval();
method public int getHierarchy();
method public long getInnerFec();
+ method @NonNull public int[] getInterleaving();
+ method @NonNull public int[] getIsdbtSegment();
method @NonNull public boolean[] getLayerErrors();
method public int getLnbVoltage();
method public int getMer();
method public int getModulation();
+ method @NonNull public int[] getModulationsExt();
method public int getPer();
method public int getPerBer();
method public int getPlpId();
@@ -6093,23 +6139,34 @@ package android.media.tv.tuner.frontend {
method public int getSnr();
method public int getSpectralInversion();
method public int getSymbolRate();
+ method public int getSystemId();
+ method public int getTransmissionMode();
+ method @NonNull public int[] getTsDataRate();
+ method public int getUec();
method public boolean isDemodLocked();
method public boolean isEwbs();
method public boolean isLnaOn();
method public boolean isRfLocked();
field public static final int FRONTEND_STATUS_TYPE_AGC = 14; // 0xe
field public static final int FRONTEND_STATUS_TYPE_ATSC3_PLP_INFO = 21; // 0x15
+ field public static final int FRONTEND_STATUS_TYPE_BANDWIDTH = 25; // 0x19
field public static final int FRONTEND_STATUS_TYPE_BER = 2; // 0x2
+ field public static final int FRONTEND_STATUS_TYPE_BERS = 23; // 0x17
+ field public static final int FRONTEND_STATUS_TYPE_CODERATES = 24; // 0x18
field public static final int FRONTEND_STATUS_TYPE_DEMOD_LOCK = 0; // 0x0
field public static final int FRONTEND_STATUS_TYPE_EWBS = 13; // 0xd
field public static final int FRONTEND_STATUS_TYPE_FEC = 8; // 0x8
field public static final int FRONTEND_STATUS_TYPE_FREQ_OFFSET = 18; // 0x12
+ field public static final int FRONTEND_STATUS_TYPE_GUARD_INTERVAL = 26; // 0x1a
field public static final int FRONTEND_STATUS_TYPE_HIERARCHY = 19; // 0x13
+ field public static final int FRONTEND_STATUS_TYPE_INTERLEAVINGS = 30; // 0x1e
+ field public static final int FRONTEND_STATUS_TYPE_ISDBT_SEGMENTS = 31; // 0x1f
field public static final int FRONTEND_STATUS_TYPE_LAYER_ERROR = 16; // 0x10
field public static final int FRONTEND_STATUS_TYPE_LNA = 15; // 0xf
field public static final int FRONTEND_STATUS_TYPE_LNB_VOLTAGE = 11; // 0xb
field public static final int FRONTEND_STATUS_TYPE_MER = 17; // 0x11
field public static final int FRONTEND_STATUS_TYPE_MODULATION = 9; // 0x9
+ field public static final int FRONTEND_STATUS_TYPE_MODULATIONS_EXT = 22; // 0x16
field public static final int FRONTEND_STATUS_TYPE_PER = 3; // 0x3
field public static final int FRONTEND_STATUS_TYPE_PLP_ID = 12; // 0xc
field public static final int FRONTEND_STATUS_TYPE_PRE_BER = 4; // 0x4
@@ -6119,6 +6176,10 @@ package android.media.tv.tuner.frontend {
field public static final int FRONTEND_STATUS_TYPE_SNR = 1; // 0x1
field public static final int FRONTEND_STATUS_TYPE_SPECTRAL = 10; // 0xa
field public static final int FRONTEND_STATUS_TYPE_SYMBOL_RATE = 7; // 0x7
+ field public static final int FRONTEND_STATUS_TYPE_T2_SYSTEM_ID = 29; // 0x1d
+ field public static final int FRONTEND_STATUS_TYPE_TRANSMISSION_MODE = 27; // 0x1b
+ field public static final int FRONTEND_STATUS_TYPE_TS_DATA_RATES = 32; // 0x20
+ field public static final int FRONTEND_STATUS_TYPE_UEC = 28; // 0x1c
}
public static class FrontendStatus.Atsc3PlpTuningInfo {
@@ -6282,7 +6343,9 @@ package android.media.tv.tuner.frontend {
method public void onHierarchyReported(int);
method public void onInputStreamIdsReported(@NonNull int[]);
method public void onLocked();
+ method public default void onModulationReported(int);
method public void onPlpIdsReported(@NonNull int[]);
+ method public default void onPriorityReported(boolean);
method public void onProgress(@IntRange(from=0, to=100) int);
method public void onScanStopped();
method public void onSignalTypeReported(int);
@@ -7437,7 +7500,7 @@ package android.net.wifi {
field public static final int BAND_2GHZ = 1; // 0x1
field public static final int BAND_5GHZ = 2; // 0x2
field public static final int BAND_6GHZ = 4; // 0x4
- field public static final int BAND_ANY = 7; // 0x7
+ field @Deprecated public static final int BAND_ANY = 7; // 0x7
field public static final int RANDOMIZATION_NONE = 0; // 0x0
field public static final int RANDOMIZATION_PERSISTENT = 1; // 0x1
}
@@ -8011,6 +8074,10 @@ package android.net.wifi.aware {
method @Deprecated public android.net.NetworkSpecifier createNetworkSpecifierPmk(@NonNull android.net.wifi.aware.PeerHandle, @NonNull byte[]);
}
+ public class WifiAwareManager {
+ method public void enableInstantCommunicationMode(boolean);
+ }
+
public class WifiAwareSession implements java.lang.AutoCloseable {
method public android.net.NetworkSpecifier createNetworkSpecifierPmk(int, @NonNull byte[], @NonNull byte[]);
}
@@ -8744,6 +8811,22 @@ package android.os {
method public boolean hasSingleFileDescriptor();
}
+ public interface Parcelable {
+ field public static final int PARCELABLE_STABILITY_LOCAL = 0; // 0x0
+ field public static final int PARCELABLE_STABILITY_VINTF = 1; // 0x1
+ }
+
+ public final class ParcelableHolder implements android.os.Parcelable {
+ ctor public ParcelableHolder(int);
+ method public int describeContents();
+ method @Nullable public <T extends android.os.Parcelable> T getParcelable(@NonNull Class<T>);
+ method public int getStability();
+ method public void readFromParcel(@NonNull android.os.Parcel);
+ method public boolean setParcelable(@Nullable android.os.Parcelable);
+ method public void writeToParcel(@NonNull android.os.Parcel, int);
+ field @NonNull public static final android.os.Parcelable.Creator<android.os.ParcelableHolder> CREATOR;
+ }
+
public final class PowerManager {
method @RequiresPermission(allOf={android.Manifest.permission.READ_DREAM_STATE, android.Manifest.permission.WRITE_DREAM_STATE}) public void dream(long);
method @RequiresPermission(android.Manifest.permission.DEVICE_POWER) public boolean forceSuspend();
@@ -11670,6 +11753,7 @@ package android.telephony {
method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public int getCarrierPrivilegeStatus(int);
method @NonNull @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public java.util.List<java.lang.String> getCarrierPrivilegedPackagesForAllActiveSubscriptions();
method @Nullable @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public android.telephony.CarrierRestrictionRules getCarrierRestrictionRules();
+ method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public int getCdmaEnhancedRoamingIndicatorIconIndex();
method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public String getCdmaMdn();
method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public String getCdmaMdn(int);
method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public String getCdmaMin();
@@ -12403,6 +12487,10 @@ package android.telephony.ims {
field @NonNull public static final android.os.Parcelable.Creator<android.telephony.ims.ImsExternalCallState> CREATOR;
}
+ public class ImsManager {
+ method @NonNull public android.telephony.ims.SipDelegateManager getSipDelegateManager(int);
+ }
+
public class ImsMmTelManager implements android.telephony.ims.RegistrationManager {
method @Deprecated @NonNull @RequiresPermission(anyOf={android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE, android.Manifest.permission.READ_PRECISE_PHONE_STATE}) public static android.telephony.ims.ImsMmTelManager createForSubscriptionId(int);
method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public void getFeatureState(@NonNull java.util.concurrent.Executor, @NonNull java.util.function.Consumer<java.lang.Integer>) throws android.telephony.ims.ImsException;
@@ -12438,10 +12526,13 @@ package android.telephony.ims {
method public void disableIms(int);
method public void enableIms(int);
method public android.telephony.ims.stub.ImsConfigImplBase getConfig(int);
+ method public long getImsServiceCapabilities();
method public android.telephony.ims.stub.ImsRegistrationImplBase getRegistration(int);
+ method @Nullable public android.telephony.ims.stub.SipTransportImplBase getSipTransport(int);
method public final void onUpdateSupportedImsFeatures(android.telephony.ims.stub.ImsFeatureConfiguration) throws android.os.RemoteException;
method public android.telephony.ims.stub.ImsFeatureConfiguration querySupportedImsFeatures();
method public void readyForFeatureCreation();
+ field public static final long CAPABILITY_SIP_DELEGATE_CREATION = 2L; // 0x2L
}
public final class ImsSsData implements android.os.Parcelable {
@@ -12687,6 +12778,10 @@ package android.telephony.ims {
method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setUceSettingEnabled(boolean) throws android.telephony.ims.ImsException;
}
+ public class SipDelegateManager {
+ method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public boolean isSupported() throws android.telephony.ims.ImsException;
+ }
+
}
package android.telephony.ims.feature {
@@ -12936,6 +13031,10 @@ package android.telephony.ims.stub {
method public int updateColr(int);
}
+ public class SipTransportImplBase {
+ ctor public SipTransportImplBase(@NonNull java.util.concurrent.Executor);
+ }
+
}
package android.telephony.mbms {
diff --git a/api/test-current.txt b/api/test-current.txt
index d61526a93e8a..8bf8c64c5c55 100644
--- a/api/test-current.txt
+++ b/api/test-current.txt
@@ -81,21 +81,14 @@ package android.app {
public class ActivityManager {
method @RequiresPermission(android.Manifest.permission.SET_ACTIVITY_WATCHER) public void addHomeVisibilityListener(@NonNull java.util.concurrent.Executor, @NonNull android.app.HomeVisibilityListener);
- method @RequiresPermission(android.Manifest.permission.PACKAGE_USAGE_STATS) public void addOnUidImportanceListener(android.app.ActivityManager.OnUidImportanceListener, int);
method public void alwaysShowUnsupportedCompileSdkWarning(android.content.ComponentName);
- method @RequiresPermission(android.Manifest.permission.FORCE_STOP_PACKAGES) public void forceStopPackage(String);
- method @RequiresPermission(android.Manifest.permission.PACKAGE_USAGE_STATS) public int getPackageImportance(String);
method public long getTotalRam();
- method @RequiresPermission(android.Manifest.permission.PACKAGE_USAGE_STATS) public int getUidImportance(int);
method @RequiresPermission(android.Manifest.permission.INJECT_EVENTS) public void holdLock(int);
method public static boolean isHighEndGfx();
- method @RequiresPermission(android.Manifest.permission.FORCE_STOP_PACKAGES) public void killProcessesWhenImperceptible(@NonNull int[], @NonNull String);
method @RequiresPermission(android.Manifest.permission.SET_ACTIVITY_WATCHER) public void removeHomeVisibilityListener(@NonNull android.app.HomeVisibilityListener);
- method @RequiresPermission(android.Manifest.permission.PACKAGE_USAGE_STATS) public void removeOnUidImportanceListener(android.app.ActivityManager.OnUidImportanceListener);
method @RequiresPermission(android.Manifest.permission.RESET_APP_ERRORS) public void resetAppErrors();
method public static void resumeAppSwitches() throws android.os.RemoteException;
method @RequiresPermission(android.Manifest.permission.CHANGE_CONFIGURATION) public void scheduleApplicationInfoChanged(java.util.List<java.lang.String>, int);
- method @RequiresPermission(android.Manifest.permission.MANAGE_USERS) public boolean switchUser(@NonNull android.os.UserHandle);
field public static final int PROCESS_CAPABILITY_ALL = 7; // 0x7
field public static final int PROCESS_CAPABILITY_ALL_EXPLICIT = 1; // 0x1
field public static final int PROCESS_CAPABILITY_ALL_IMPLICIT = 6; // 0x6
@@ -105,10 +98,6 @@ package android.app {
field public static final int PROCESS_CAPABILITY_NONE = 0; // 0x0
}
- public static interface ActivityManager.OnUidImportanceListener {
- method public void onUidImportance(int, int);
- }
-
public static class ActivityManager.RunningAppProcessInfo implements android.os.Parcelable {
field public static final int IMPORTANCE_CANT_SAVE_STATE_PRE_26 = 170; // 0xaa
}
@@ -147,7 +136,6 @@ package android.app {
method @RequiresPermission(android.Manifest.permission.MANAGE_ACTIVITY_STACKS) public void requestPictureInPictureMode(@NonNull android.os.IBinder);
method @RequiresPermission(android.Manifest.permission.MANAGE_ACTIVITY_STACKS) public void resizePrimarySplitScreen(@NonNull android.graphics.Rect, @NonNull android.graphics.Rect);
method @RequiresPermission(android.Manifest.permission.MANAGE_ACTIVITY_STACKS) public void resizeTask(int, android.graphics.Rect);
- method @RequiresPermission(android.Manifest.permission.MANAGE_ACTIVITY_STACKS) public void setDisplayToSingleTaskInstance(int);
method @RequiresPermission(android.Manifest.permission.MANAGE_ACTIVITY_STACKS) public boolean setTaskWindowingMode(int, int, boolean) throws java.lang.SecurityException;
method @RequiresPermission(android.Manifest.permission.MANAGE_ACTIVITY_STACKS) public boolean setTaskWindowingModeSplitScreenPrimary(int, int, boolean, boolean, android.graphics.Rect, boolean) throws java.lang.SecurityException;
method @RequiresPermission(android.Manifest.permission.MANAGE_ACTIVITY_STACKS) public void startSystemLockTaskMode(int);
@@ -163,7 +151,7 @@ package android.app {
public class ActivityView extends android.view.ViewGroup {
ctor public ActivityView(android.content.Context);
ctor public ActivityView(android.content.Context, android.util.AttributeSet);
- ctor public ActivityView(@NonNull android.content.Context, @NonNull android.util.AttributeSet, int, boolean, boolean);
+ ctor public ActivityView(@NonNull android.content.Context, @NonNull android.util.AttributeSet, int, boolean);
method public int getVirtualDisplayId();
method public void onLayout(boolean, int, int, int, int);
method public void onLocationChanged();
@@ -183,7 +171,6 @@ package android.app {
method @NonNull public android.app.ActivityView.Builder setAttributeSet(@Nullable android.util.AttributeSet);
method @NonNull public android.app.ActivityView.Builder setDefaultStyle(int);
method @NonNull public android.app.ActivityView.Builder setDisableSurfaceViewBackgroundLayer(boolean);
- method @NonNull public android.app.ActivityView.Builder setSingleInstance(boolean);
method @NonNull public android.app.ActivityView.Builder setUsePublicVirtualDisplay(boolean);
method @NonNull public android.app.ActivityView.Builder setUseTrustedDisplay(boolean);
}
@@ -204,15 +191,10 @@ package android.app {
public class AppOpsManager {
method @RequiresPermission("android.permission.MANAGE_APPOPS") public void addHistoricalOps(@NonNull android.app.AppOpsManager.HistoricalOps);
method @RequiresPermission("android.permission.MANAGE_APPOPS") public void clearHistory();
- method @Nullable @RequiresPermission(android.Manifest.permission.GET_APP_OPS_STATS) public android.app.RuntimeAppOpAccessMessage collectRuntimeAppOpAccessMessage();
- method @RequiresPermission(android.Manifest.permission.GET_APP_OPS_STATS) public void getHistoricalOps(@NonNull android.app.AppOpsManager.HistoricalOpsRequest, @NonNull java.util.concurrent.Executor, @NonNull java.util.function.Consumer<android.app.AppOpsManager.HistoricalOps>);
method @RequiresPermission("android.permission.MANAGE_APPOPS") public void getHistoricalOpsFromDiskRaw(@NonNull android.app.AppOpsManager.HistoricalOpsRequest, @Nullable java.util.concurrent.Executor, @NonNull java.util.function.Consumer<android.app.AppOpsManager.HistoricalOps>);
method public static int getNumOps();
- method public static String[] getOpStrs();
- method @NonNull @RequiresPermission(android.Manifest.permission.GET_APP_OPS_STATS) public java.util.List<android.app.AppOpsManager.PackageOps> getOpsForPackage(int, @NonNull String, @Nullable java.lang.String...);
method public boolean isOperationActive(int, int, String);
method @RequiresPermission("android.permission.MANAGE_APPOPS") public void offsetHistory(long);
- method public static int opToDefaultMode(@NonNull String);
method public static String opToPermission(int);
method public static int permissionToOpCode(String);
method @RequiresPermission("android.permission.MANAGE_APPOPS") public void rebootHistory(long);
@@ -220,8 +202,6 @@ package android.app {
method @RequiresPermission("android.permission.MANAGE_APPOPS") public void resetHistoryParameters();
method @RequiresPermission("android.permission.MANAGE_APPOPS") public void setHistoryParameters(int, long, int);
method @RequiresPermission("android.permission.MANAGE_APP_OPS_MODES") public void setMode(int, int, String, int);
- method @RequiresPermission("android.permission.MANAGE_APP_OPS_MODES") public void setMode(@NonNull String, int, @Nullable String, int);
- method @RequiresPermission("android.permission.MANAGE_APP_OPS_MODES") public void setUidMode(@NonNull String, int, int);
method public static int strOpToOp(@NonNull String);
field public static final int HISTORICAL_MODE_DISABLED = 0; // 0x0
field public static final int HISTORICAL_MODE_ENABLED_ACTIVE = 1; // 0x1
@@ -229,225 +209,19 @@ package android.app {
field public static final String KEY_BG_STATE_SETTLE_TIME = "bg_state_settle_time";
field public static final String KEY_FG_SERVICE_STATE_SETTLE_TIME = "fg_service_state_settle_time";
field public static final String KEY_TOP_STATE_SETTLE_TIME = "top_state_settle_time";
- field public static final String OPSTR_ACCEPT_HANDOVER = "android:accept_handover";
- field public static final String OPSTR_ACCESS_NOTIFICATIONS = "android:access_notifications";
- field public static final String OPSTR_ACTIVATE_VPN = "android:activate_vpn";
- field public static final String OPSTR_ASSIST_SCREENSHOT = "android:assist_screenshot";
- field public static final String OPSTR_ASSIST_STRUCTURE = "android:assist_structure";
- field public static final String OPSTR_AUDIO_ACCESSIBILITY_VOLUME = "android:audio_accessibility_volume";
- field public static final String OPSTR_AUDIO_ALARM_VOLUME = "android:audio_alarm_volume";
- field public static final String OPSTR_AUDIO_BLUETOOTH_VOLUME = "android:audio_bluetooth_volume";
- field public static final String OPSTR_AUDIO_MASTER_VOLUME = "android:audio_master_volume";
- field public static final String OPSTR_AUDIO_MEDIA_VOLUME = "android:audio_media_volume";
- field public static final String OPSTR_AUDIO_NOTIFICATION_VOLUME = "android:audio_notification_volume";
- field public static final String OPSTR_AUDIO_RING_VOLUME = "android:audio_ring_volume";
- field public static final String OPSTR_AUDIO_VOICE_VOLUME = "android:audio_voice_volume";
- field public static final String OPSTR_BIND_ACCESSIBILITY_SERVICE = "android:bind_accessibility_service";
- field public static final String OPSTR_CHANGE_WIFI_STATE = "android:change_wifi_state";
- field public static final String OPSTR_GET_ACCOUNTS = "android:get_accounts";
- field public static final String OPSTR_GPS = "android:gps";
- field public static final String OPSTR_INSTANT_APP_START_FOREGROUND = "android:instant_app_start_foreground";
- field public static final String OPSTR_LEGACY_STORAGE = "android:legacy_storage";
- field public static final String OPSTR_MANAGE_EXTERNAL_STORAGE = "android:manage_external_storage";
- field public static final String OPSTR_MANAGE_IPSEC_TUNNELS = "android:manage_ipsec_tunnels";
- field public static final String OPSTR_MUTE_MICROPHONE = "android:mute_microphone";
- field public static final String OPSTR_NEIGHBORING_CELLS = "android:neighboring_cells";
- field public static final String OPSTR_PLAY_AUDIO = "android:play_audio";
- field public static final String OPSTR_POST_NOTIFICATION = "android:post_notification";
- field public static final String OPSTR_PROJECT_MEDIA = "android:project_media";
- field public static final String OPSTR_READ_CLIPBOARD = "android:read_clipboard";
- field public static final String OPSTR_READ_ICC_SMS = "android:read_icc_sms";
- field public static final String OPSTR_READ_MEDIA_AUDIO = "android:read_media_audio";
- field public static final String OPSTR_READ_MEDIA_IMAGES = "android:read_media_images";
- field public static final String OPSTR_READ_MEDIA_VIDEO = "android:read_media_video";
- field public static final String OPSTR_RECEIVE_EMERGENCY_BROADCAST = "android:receive_emergency_broadcast";
- field public static final String OPSTR_REQUEST_DELETE_PACKAGES = "android:request_delete_packages";
- field public static final String OPSTR_REQUEST_INSTALL_PACKAGES = "android:request_install_packages";
- field public static final String OPSTR_RUN_ANY_IN_BACKGROUND = "android:run_any_in_background";
- field public static final String OPSTR_RUN_IN_BACKGROUND = "android:run_in_background";
- field public static final String OPSTR_START_FOREGROUND = "android:start_foreground";
- field public static final String OPSTR_TAKE_AUDIO_FOCUS = "android:take_audio_focus";
- field public static final String OPSTR_TAKE_MEDIA_BUTTONS = "android:take_media_buttons";
- field public static final String OPSTR_TOAST_WINDOW = "android:toast_window";
- field public static final String OPSTR_TURN_SCREEN_ON = "android:turn_screen_on";
- field public static final String OPSTR_VIBRATE = "android:vibrate";
- field public static final String OPSTR_WAKE_LOCK = "android:wake_lock";
- field public static final String OPSTR_WIFI_SCAN = "android:wifi_scan";
- field public static final String OPSTR_WRITE_CLIPBOARD = "android:write_clipboard";
- field public static final String OPSTR_WRITE_ICC_SMS = "android:write_icc_sms";
- field public static final String OPSTR_WRITE_MEDIA_AUDIO = "android:write_media_audio";
- field public static final String OPSTR_WRITE_MEDIA_IMAGES = "android:write_media_images";
- field public static final String OPSTR_WRITE_MEDIA_VIDEO = "android:write_media_video";
- field public static final String OPSTR_WRITE_SMS = "android:write_sms";
- field public static final String OPSTR_WRITE_WALLPAPER = "android:write_wallpaper";
field public static final int OP_COARSE_LOCATION = 0; // 0x0
- field public static final int OP_FLAGS_ALL = 31; // 0x1f
- field public static final int OP_FLAG_SELF = 1; // 0x1
- field public static final int OP_FLAG_TRUSTED_PROXIED = 8; // 0x8
- field public static final int OP_FLAG_TRUSTED_PROXY = 2; // 0x2
- field public static final int OP_FLAG_UNTRUSTED_PROXIED = 16; // 0x10
- field public static final int OP_FLAG_UNTRUSTED_PROXY = 4; // 0x4
field public static final int OP_RECORD_AUDIO = 27; // 0x1b
field public static final int OP_START_FOREGROUND = 76; // 0x4c
field public static final int OP_SYSTEM_ALERT_WINDOW = 24; // 0x18
field public static final long SECURITY_EXCEPTION_ON_INVALID_ATTRIBUTION_TAG_CHANGE = 151105954L; // 0x901b1a2L
- field public static final int UID_STATE_BACKGROUND = 600; // 0x258
- field public static final int UID_STATE_CACHED = 700; // 0x2bc
- field public static final int UID_STATE_FOREGROUND = 500; // 0x1f4
- field public static final int UID_STATE_FOREGROUND_SERVICE = 400; // 0x190
- field @Deprecated public static final int UID_STATE_FOREGROUND_SERVICE_LOCATION = 300; // 0x12c
- field public static final int UID_STATE_PERSISTENT = 100; // 0x64
- field public static final int UID_STATE_TOP = 200; // 0xc8
- }
-
- public static final class AppOpsManager.AttributedHistoricalOps implements android.os.Parcelable {
- method public int describeContents();
- method @Nullable public android.app.AppOpsManager.HistoricalOp getOp(@NonNull String);
- method @NonNull public android.app.AppOpsManager.HistoricalOp getOpAt(@IntRange(from=0) int);
- method @IntRange(from=0) public int getOpCount();
- method @Nullable public String getTag();
- method public void writeToParcel(@NonNull android.os.Parcel, int);
- field @NonNull public static final android.os.Parcelable.Creator<android.app.AppOpsManager.AttributedHistoricalOps> CREATOR;
- }
-
- public static final class AppOpsManager.AttributedOpEntry implements android.os.Parcelable {
- method public int describeContents();
- method public long getLastAccessBackgroundTime(int);
- method public long getLastAccessForegroundTime(int);
- method public long getLastAccessTime(int);
- method public long getLastAccessTime(int, int, int);
- method public long getLastBackgroundDuration(int);
- method @Nullable public android.app.AppOpsManager.OpEventProxyInfo getLastBackgroundProxyInfo(int);
- method public long getLastDuration(int);
- method public long getLastDuration(int, int, int);
- method public long getLastForegroundDuration(int);
- method @Nullable public android.app.AppOpsManager.OpEventProxyInfo getLastForegroundProxyInfo(int);
- method @Nullable public android.app.AppOpsManager.OpEventProxyInfo getLastProxyInfo(int);
- method @Nullable public android.app.AppOpsManager.OpEventProxyInfo getLastProxyInfo(int, int, int);
- method public long getLastRejectBackgroundTime(int);
- method public long getLastRejectForegroundTime(int);
- method public long getLastRejectTime(int);
- method public long getLastRejectTime(int, int, int);
- method public boolean isRunning();
- method public void writeToParcel(@NonNull android.os.Parcel, int);
- field @NonNull public static final android.os.Parcelable.Creator<android.app.AppOpsManager.AttributedOpEntry> CREATOR;
- }
-
- public static final class AppOpsManager.HistoricalOp implements android.os.Parcelable {
- method public int describeContents();
- method public long getAccessCount(int, int, int);
- method public long getAccessDuration(int, int, int);
- method public long getBackgroundAccessCount(int);
- method public long getBackgroundAccessDuration(int);
- method public long getBackgroundRejectCount(int);
- method public long getForegroundAccessCount(int);
- method public long getForegroundAccessDuration(int);
- method public long getForegroundRejectCount(int);
- method @NonNull public String getOpName();
- method public long getRejectCount(int, int, int);
- method public void writeToParcel(android.os.Parcel, int);
- field @NonNull public static final android.os.Parcelable.Creator<android.app.AppOpsManager.HistoricalOp> CREATOR;
}
public static final class AppOpsManager.HistoricalOps implements android.os.Parcelable {
ctor public AppOpsManager.HistoricalOps(long, long);
- method public int describeContents();
- method public long getBeginTimeMillis();
- method public long getEndTimeMillis();
- method @IntRange(from=0) public int getUidCount();
- method @Nullable public android.app.AppOpsManager.HistoricalUidOps getUidOps(int);
- method @NonNull public android.app.AppOpsManager.HistoricalUidOps getUidOpsAt(@IntRange(from=0) int);
method public void increaseAccessCount(int, int, @NonNull String, @Nullable String, int, int, long);
method public void increaseAccessDuration(int, int, @NonNull String, @Nullable String, int, int, long);
method public void increaseRejectCount(int, int, @NonNull String, @Nullable String, int, int, long);
method public void offsetBeginAndEndTime(long);
- method public void writeToParcel(android.os.Parcel, int);
- field @NonNull public static final android.os.Parcelable.Creator<android.app.AppOpsManager.HistoricalOps> CREATOR;
- }
-
- public static final class AppOpsManager.HistoricalOpsRequest {
- }
-
- public static final class AppOpsManager.HistoricalOpsRequest.Builder {
- ctor public AppOpsManager.HistoricalOpsRequest.Builder(long, long);
- method @NonNull public android.app.AppOpsManager.HistoricalOpsRequest build();
- method @NonNull public android.app.AppOpsManager.HistoricalOpsRequest.Builder setAttributionTag(@Nullable String);
- method @NonNull public android.app.AppOpsManager.HistoricalOpsRequest.Builder setFlags(int);
- method @NonNull public android.app.AppOpsManager.HistoricalOpsRequest.Builder setOpNames(@Nullable java.util.List<java.lang.String>);
- method @NonNull public android.app.AppOpsManager.HistoricalOpsRequest.Builder setPackageName(@Nullable String);
- method @NonNull public android.app.AppOpsManager.HistoricalOpsRequest.Builder setUid(int);
- }
-
- public static final class AppOpsManager.HistoricalPackageOps implements android.os.Parcelable {
- method public int describeContents();
- method @Nullable public android.app.AppOpsManager.AttributedHistoricalOps getAttributedOps(@NonNull String);
- method @NonNull public android.app.AppOpsManager.AttributedHistoricalOps getAttributedOpsAt(@IntRange(from=0) int);
- method @IntRange(from=0) public int getAttributedOpsCount();
- method @Nullable public android.app.AppOpsManager.HistoricalOp getOp(@NonNull String);
- method @NonNull public android.app.AppOpsManager.HistoricalOp getOpAt(@IntRange(from=0) int);
- method @IntRange(from=0) public int getOpCount();
- method @NonNull public String getPackageName();
- method public void writeToParcel(@NonNull android.os.Parcel, int);
- field @NonNull public static final android.os.Parcelable.Creator<android.app.AppOpsManager.HistoricalPackageOps> CREATOR;
- }
-
- public static final class AppOpsManager.HistoricalUidOps implements android.os.Parcelable {
- method public int describeContents();
- method @IntRange(from=0) public int getPackageCount();
- method @Nullable public android.app.AppOpsManager.HistoricalPackageOps getPackageOps(@NonNull String);
- method @NonNull public android.app.AppOpsManager.HistoricalPackageOps getPackageOpsAt(@IntRange(from=0) int);
- method public int getUid();
- method public void writeToParcel(android.os.Parcel, int);
- field @NonNull public static final android.os.Parcelable.Creator<android.app.AppOpsManager.HistoricalUidOps> CREATOR;
- }
-
- public static final class AppOpsManager.OpEntry implements android.os.Parcelable {
- method public int describeContents();
- method @NonNull public java.util.Map<java.lang.String,android.app.AppOpsManager.AttributedOpEntry> getAttributedOpEntries();
- method @Deprecated public long getDuration();
- method public long getLastAccessBackgroundTime(int);
- method public long getLastAccessForegroundTime(int);
- method public long getLastAccessTime(int);
- method public long getLastAccessTime(int, int, int);
- method public long getLastBackgroundDuration(int);
- method @Nullable public android.app.AppOpsManager.OpEventProxyInfo getLastBackgroundProxyInfo(int);
- method public long getLastDuration(int);
- method public long getLastDuration(int, int, int);
- method public long getLastForegroundDuration(int);
- method @Nullable public android.app.AppOpsManager.OpEventProxyInfo getLastForegroundProxyInfo(int);
- method @Nullable public android.app.AppOpsManager.OpEventProxyInfo getLastProxyInfo(int);
- method @Nullable public android.app.AppOpsManager.OpEventProxyInfo getLastProxyInfo(int, int, int);
- method public long getLastRejectBackgroundTime(int);
- method public long getLastRejectForegroundTime(int);
- method public long getLastRejectTime(int);
- method public long getLastRejectTime(int, int, int);
- method public int getMode();
- method @NonNull public String getOpStr();
- method @Deprecated @Nullable public String getProxyPackageName();
- method @Deprecated @Nullable public String getProxyPackageName(int, int);
- method @Deprecated public int getProxyUid();
- method @Deprecated public int getProxyUid(int, int);
- method public boolean isRunning();
- method public void writeToParcel(android.os.Parcel, int);
- field @NonNull public static final android.os.Parcelable.Creator<android.app.AppOpsManager.OpEntry> CREATOR;
- }
-
- public static final class AppOpsManager.OpEventProxyInfo implements android.os.Parcelable {
- method public int describeContents();
- method @Nullable public String getAttributionTag();
- method @Nullable public String getPackageName();
- method @IntRange(from=0) public int getUid();
- method public void writeToParcel(@NonNull android.os.Parcel, int);
- field @NonNull public static final android.os.Parcelable.Creator<android.app.AppOpsManager.OpEventProxyInfo> CREATOR;
- }
-
- public static final class AppOpsManager.PackageOps implements android.os.Parcelable {
- method public int describeContents();
- method @NonNull public java.util.List<android.app.AppOpsManager.OpEntry> getOps();
- method @NonNull public String getPackageName();
- method public int getUid();
- method public void writeToParcel(@NonNull android.os.Parcel, int);
- field @NonNull public static final android.os.Parcelable.Creator<android.app.AppOpsManager.PackageOps> CREATOR;
}
public class DownloadManager {
@@ -472,7 +246,6 @@ package android.app {
method public boolean isImportanceLockedByCriticalDeviceFunction();
method public boolean isImportanceLockedByOEM();
method public void lockFields(int);
- method public void setBlockable(boolean);
method public void setDeleted(boolean);
method public void setDemoted(boolean);
method public void setFgServiceShown(boolean);
@@ -480,7 +253,6 @@ package android.app {
method public void setImportanceLockedByOEM(boolean);
method public void setImportantConversation(boolean);
method public void setOriginalImportance(int);
- field public static final int USER_LOCKED_SOUND = 32; // 0x20
}
public final class NotificationChannelGroup implements android.os.Parcelable {
@@ -492,14 +264,8 @@ package android.app {
public class NotificationManager {
method public void allowAssistantAdjustment(String);
method public void disallowAssistantAdjustment(String);
- method @NonNull public java.util.List<java.lang.String> getAllowedAssistantAdjustments();
- method @Nullable public android.content.ComponentName getAllowedNotificationAssistant();
method public android.content.ComponentName getEffectsSuppressor();
- method @NonNull @RequiresPermission(android.Manifest.permission.MANAGE_NOTIFICATION_LISTENERS) public java.util.List<android.content.ComponentName> getEnabledNotificationListeners();
- method public boolean isNotificationAssistantAccessGranted(@NonNull android.content.ComponentName);
method public boolean matchesCallFilter(android.os.Bundle);
- method public void setNotificationAssistantAccessGranted(@Nullable android.content.ComponentName, boolean);
- method @RequiresPermission(android.Manifest.permission.MANAGE_NOTIFICATION_LISTENERS) public void setNotificationListenerAccessGranted(@NonNull android.content.ComponentName, boolean);
method public void updateNotificationChannel(@NonNull String, int, @NonNull android.app.NotificationChannel);
}
@@ -509,36 +275,12 @@ package android.app {
method public android.graphics.Rect getSourceRectHint();
}
- public final class RuntimeAppOpAccessMessage implements android.os.Parcelable {
- ctor public RuntimeAppOpAccessMessage(@IntRange(from=0L) int, @IntRange(from=0L) int, @NonNull String, @Nullable String, @NonNull String, int);
- method public int describeContents();
- method @Nullable public String getAttributionTag();
- method @NonNull public String getMessage();
- method @NonNull public String getOp();
- method @NonNull public String getPackageName();
- method public int getSamplingStrategy();
- method @IntRange(from=0L) public int getUid();
- method public void writeToParcel(@NonNull android.os.Parcel, int);
- field @NonNull public static final android.os.Parcelable.Creator<android.app.RuntimeAppOpAccessMessage> CREATOR;
- }
-
public class StatusBarManager {
method public void collapsePanels();
method public void expandNotificationsPanel();
- method @NonNull @RequiresPermission(android.Manifest.permission.STATUS_BAR) public android.app.StatusBarManager.DisableInfo getDisableInfo();
- method @RequiresPermission(android.Manifest.permission.STATUS_BAR) public void setDisabledForSetup(boolean);
method @RequiresPermission(android.Manifest.permission.STATUS_BAR) public void setExpansionDisabledForSimNetworkLock(boolean);
}
- public static final class StatusBarManager.DisableInfo {
- method public boolean areAllComponentsEnabled();
- method public boolean isNavigateToHomeDisabled();
- method public boolean isNotificationPeekingDisabled();
- method public boolean isRecentsDisabled();
- method public boolean isSearchDisabled();
- method public boolean isStatusBarExpansionDisabled();
- }
-
public class TaskInfo {
method @NonNull public android.content.res.Configuration getConfiguration();
method @NonNull public android.window.WindowContainerToken getToken();
@@ -557,14 +299,12 @@ package android.app {
}
public class UiModeManager {
- method @RequiresPermission(android.Manifest.permission.ENTER_CAR_MODE_PRIORITIZED) public void enableCarMode(@IntRange(from=0) int, int);
method public boolean isNightModeLocked();
method public boolean isUiModeLocked();
}
public class WallpaperManager {
method @Nullable public android.graphics.Bitmap getBitmap();
- method @RequiresPermission(android.Manifest.permission.SET_WALLPAPER_COMPONENT) public boolean setWallpaperComponent(android.content.ComponentName);
method public boolean shouldEnableWideColorGamut();
method @RequiresPermission(android.Manifest.permission.READ_EXTERNAL_STORAGE) public boolean wallpaperSupportsWcg(int);
}
@@ -609,18 +349,13 @@ package android.app {
package android.app.admin {
public class DevicePolicyManager {
- method @Nullable public CharSequence getDeviceOwnerOrganizationName();
method public long getLastBugReportRequestTime();
method public long getLastNetworkLogRetrievalTime();
method public long getLastSecurityLogRetrievalTime();
method public java.util.List<java.lang.String> getOwnerInstalledCaCerts(@NonNull android.os.UserHandle);
method public boolean isCurrentInputMethodSetByOwner();
- method public boolean isDeviceManaged();
method public boolean isFactoryResetProtectionPolicySupported();
- field public static final String ACCOUNT_FEATURE_DEVICE_OR_PROFILE_OWNER_ALLOWED = "android.account.DEVICE_OR_PROFILE_OWNER_ALLOWED";
- field public static final String ACCOUNT_FEATURE_DEVICE_OR_PROFILE_OWNER_DISALLOWED = "android.account.DEVICE_OR_PROFILE_OWNER_DISALLOWED";
field public static final String ACTION_DATA_SHARING_RESTRICTION_APPLIED = "android.app.action.DATA_SHARING_RESTRICTION_APPLIED";
- field public static final String EXTRA_RESTRICTION = "android.app.extra.RESTRICTION";
}
public static final class SecurityLog.SecurityEvent implements android.os.Parcelable {
@@ -629,26 +364,6 @@ package android.app.admin {
}
-package android.app.assist {
-
- public static class AssistStructure.ViewNode {
- ctor public AssistStructure.ViewNode();
- }
-
-}
-
-package android.app.backup {
-
- public class BackupManager {
- method @RequiresPermission(android.Manifest.permission.BACKUP) public android.content.Intent getConfigurationIntent(String);
- method @RequiresPermission(android.Manifest.permission.BACKUP) public android.content.Intent getDataManagementIntent(String);
- method @Nullable @RequiresPermission(android.Manifest.permission.BACKUP) public CharSequence getDataManagementIntentLabel(@NonNull String);
- method @Deprecated @Nullable @RequiresPermission(android.Manifest.permission.BACKUP) public String getDataManagementLabel(@NonNull String);
- method @RequiresPermission(android.Manifest.permission.BACKUP) public String getDestinationString(String);
- }
-
-}
-
package android.app.blob {
public class BlobStoreManager {
@@ -671,150 +386,27 @@ package android.app.blob {
package android.app.prediction {
- public final class AppPredictionContext implements android.os.Parcelable {
- method public int describeContents();
- method @Nullable public android.os.Bundle getExtras();
- method @NonNull public String getPackageName();
- method @IntRange(from=0) public int getPredictedTargetCount();
- method @NonNull public String getUiSurface();
- method public void writeToParcel(@NonNull android.os.Parcel, int);
- field @NonNull public static final android.os.Parcelable.Creator<android.app.prediction.AppPredictionContext> CREATOR;
- }
-
- public static final class AppPredictionContext.Builder {
- ctor public AppPredictionContext.Builder(@NonNull android.content.Context);
- method @NonNull public android.app.prediction.AppPredictionContext build();
- method @NonNull public android.app.prediction.AppPredictionContext.Builder setExtras(@Nullable android.os.Bundle);
- method @NonNull public android.app.prediction.AppPredictionContext.Builder setPredictedTargetCount(@IntRange(from=0) int);
- method @NonNull public android.app.prediction.AppPredictionContext.Builder setUiSurface(@NonNull String);
- }
-
- public final class AppPredictionManager {
- method @NonNull public android.app.prediction.AppPredictor createAppPredictionSession(@NonNull android.app.prediction.AppPredictionContext);
- }
-
- public final class AppPredictionSessionId implements android.os.Parcelable {
- method public int describeContents();
- method public void writeToParcel(android.os.Parcel, int);
- field @NonNull public static final android.os.Parcelable.Creator<android.app.prediction.AppPredictionSessionId> CREATOR;
- }
-
public final class AppPredictor {
- method public void destroy();
method public android.app.prediction.AppPredictionSessionId getSessionId();
- method public void notifyAppTargetEvent(@NonNull android.app.prediction.AppTargetEvent);
- method public void notifyLaunchLocationShown(@NonNull String, @NonNull java.util.List<android.app.prediction.AppTargetId>);
- method public void registerPredictionUpdates(@NonNull java.util.concurrent.Executor, @NonNull android.app.prediction.AppPredictor.Callback);
- method public void requestPredictionUpdate();
- method @Nullable public void sortTargets(@NonNull java.util.List<android.app.prediction.AppTarget>, @NonNull java.util.concurrent.Executor, @NonNull java.util.function.Consumer<java.util.List<android.app.prediction.AppTarget>>);
- method public void unregisterPredictionUpdates(@NonNull android.app.prediction.AppPredictor.Callback);
- }
-
- public static interface AppPredictor.Callback {
- method public void onTargetsAvailable(@NonNull java.util.List<android.app.prediction.AppTarget>);
- }
-
- public final class AppTarget implements android.os.Parcelable {
- method public int describeContents();
- method @Nullable public String getClassName();
- method @NonNull public android.app.prediction.AppTargetId getId();
- method @NonNull public String getPackageName();
- method @IntRange(from=0) public int getRank();
- method @Nullable public android.content.pm.ShortcutInfo getShortcutInfo();
- method @NonNull public android.os.UserHandle getUser();
- method public void writeToParcel(android.os.Parcel, int);
- field @NonNull public static final android.os.Parcelable.Creator<android.app.prediction.AppTarget> CREATOR;
- }
-
- public static final class AppTarget.Builder {
- ctor public AppTarget.Builder(@NonNull android.app.prediction.AppTargetId, @NonNull String, @NonNull android.os.UserHandle);
- ctor public AppTarget.Builder(@NonNull android.app.prediction.AppTargetId, @NonNull android.content.pm.ShortcutInfo);
- method @NonNull public android.app.prediction.AppTarget build();
- method @NonNull public android.app.prediction.AppTarget.Builder setClassName(@NonNull String);
- method @NonNull public android.app.prediction.AppTarget.Builder setRank(@IntRange(from=0) int);
- }
-
- public final class AppTargetEvent implements android.os.Parcelable {
- method public int describeContents();
- method public int getAction();
- method @Nullable public String getLaunchLocation();
- method @Nullable public android.app.prediction.AppTarget getTarget();
- method public void writeToParcel(android.os.Parcel, int);
- field public static final int ACTION_DISMISS = 2; // 0x2
- field public static final int ACTION_LAUNCH = 1; // 0x1
- field public static final int ACTION_PIN = 3; // 0x3
- field public static final int ACTION_UNPIN = 4; // 0x4
- field @NonNull public static final android.os.Parcelable.Creator<android.app.prediction.AppTargetEvent> CREATOR;
- }
-
- public static final class AppTargetEvent.Builder {
- ctor public AppTargetEvent.Builder(@Nullable android.app.prediction.AppTarget, int);
- method @NonNull public android.app.prediction.AppTargetEvent build();
- method @NonNull public android.app.prediction.AppTargetEvent.Builder setLaunchLocation(@Nullable String);
- }
-
- public final class AppTargetId implements android.os.Parcelable {
- ctor public AppTargetId(@NonNull String);
- method public int describeContents();
- method public void writeToParcel(android.os.Parcel, int);
- field @NonNull public static final android.os.Parcelable.Creator<android.app.prediction.AppTargetId> CREATOR;
}
}
package android.app.role {
- public interface OnRoleHoldersChangedListener {
- method public void onRoleHoldersChanged(@NonNull String, @NonNull android.os.UserHandle);
- }
-
public class RoleControllerManager {
method @RequiresPermission(android.Manifest.permission.MANAGE_ROLE_HOLDERS) public void isApplicationVisibleForRole(@NonNull String, @NonNull String, @NonNull java.util.concurrent.Executor, @NonNull java.util.function.Consumer<java.lang.Boolean>);
method @RequiresPermission(android.Manifest.permission.MANAGE_ROLE_HOLDERS) public void isRoleVisible(@NonNull String, @NonNull java.util.concurrent.Executor, @NonNull java.util.function.Consumer<java.lang.Boolean>);
}
public final class RoleManager {
- method @RequiresPermission(android.Manifest.permission.OBSERVE_ROLE_HOLDERS) public void addOnRoleHoldersChangedListenerAsUser(@NonNull java.util.concurrent.Executor, @NonNull android.app.role.OnRoleHoldersChangedListener, @NonNull android.os.UserHandle);
- method @RequiresPermission(android.Manifest.permission.MANAGE_ROLE_HOLDERS) public void addRoleHolderAsUser(@NonNull String, @NonNull String, int, @NonNull android.os.UserHandle, @NonNull java.util.concurrent.Executor, @NonNull java.util.function.Consumer<java.lang.Boolean>);
- method @RequiresPermission("com.android.permissioncontroller.permission.MANAGE_ROLES_FROM_CONTROLLER") public boolean addRoleHolderFromController(@NonNull String, @NonNull String);
- method @RequiresPermission(android.Manifest.permission.MANAGE_ROLE_HOLDERS) public void clearRoleHoldersAsUser(@NonNull String, int, @NonNull android.os.UserHandle, @NonNull java.util.concurrent.Executor, @NonNull java.util.function.Consumer<java.lang.Boolean>);
- method @NonNull @RequiresPermission("com.android.permissioncontroller.permission.MANAGE_ROLES_FROM_CONTROLLER") public java.util.List<java.lang.String> getHeldRolesFromController(@NonNull String);
- method @NonNull @RequiresPermission(android.Manifest.permission.MANAGE_ROLE_HOLDERS) public java.util.List<java.lang.String> getRoleHolders(@NonNull String);
- method @NonNull @RequiresPermission(android.Manifest.permission.MANAGE_ROLE_HOLDERS) public java.util.List<java.lang.String> getRoleHoldersAsUser(@NonNull String, @NonNull android.os.UserHandle);
method @Nullable public String getSmsRoleHolder(int);
- method @RequiresPermission(android.Manifest.permission.OBSERVE_ROLE_HOLDERS) public void removeOnRoleHoldersChangedListenerAsUser(@NonNull android.app.role.OnRoleHoldersChangedListener, @NonNull android.os.UserHandle);
- method @RequiresPermission(android.Manifest.permission.MANAGE_ROLE_HOLDERS) public void removeRoleHolderAsUser(@NonNull String, @NonNull String, int, @NonNull android.os.UserHandle, @NonNull java.util.concurrent.Executor, @NonNull java.util.function.Consumer<java.lang.Boolean>);
- method @RequiresPermission("com.android.permissioncontroller.permission.MANAGE_ROLES_FROM_CONTROLLER") public boolean removeRoleHolderFromController(@NonNull String, @NonNull String);
- method @RequiresPermission("com.android.permissioncontroller.permission.MANAGE_ROLES_FROM_CONTROLLER") public void setRoleNamesFromController(@NonNull java.util.List<java.lang.String>);
- field public static final int MANAGE_HOLDERS_FLAG_DONT_KILL_APP = 1; // 0x1
}
}
package android.app.usage {
- public final class CacheQuotaHint implements android.os.Parcelable {
- ctor public CacheQuotaHint(@NonNull android.app.usage.CacheQuotaHint.Builder);
- method public int describeContents();
- method public long getQuota();
- method public int getUid();
- method @Nullable public android.app.usage.UsageStats getUsageStats();
- method @Nullable public String getVolumeUuid();
- method public void writeToParcel(@NonNull android.os.Parcel, int);
- field @NonNull public static final android.os.Parcelable.Creator<android.app.usage.CacheQuotaHint> CREATOR;
- field public static final long QUOTA_NOT_SET = -1L; // 0xffffffffffffffffL
- }
-
- public static final class CacheQuotaHint.Builder {
- ctor public CacheQuotaHint.Builder();
- ctor public CacheQuotaHint.Builder(@NonNull android.app.usage.CacheQuotaHint);
- method @NonNull public android.app.usage.CacheQuotaHint build();
- method @NonNull public android.app.usage.CacheQuotaHint.Builder setQuota(long);
- method @NonNull public android.app.usage.CacheQuotaHint.Builder setUid(int);
- method @NonNull public android.app.usage.CacheQuotaHint.Builder setUsageStats(@Nullable android.app.usage.UsageStats);
- method @NonNull public android.app.usage.CacheQuotaHint.Builder setVolumeUuid(@Nullable String);
- }
-
public class NetworkStatsManager {
method public void setPollForce(boolean);
}
@@ -845,23 +437,8 @@ package android.bluetooth {
}
-package android.companion {
-
- public final class CompanionDeviceManager {
- method @RequiresPermission("android.permission.MANAGE_COMPANION_DEVICES") public boolean isDeviceAssociatedForWifiConnection(@NonNull String, @NonNull android.net.MacAddress, @NonNull android.os.UserHandle);
- }
-
-}
-
package android.content {
- public class ApexEnvironment {
- method @NonNull public static android.content.ApexEnvironment getApexEnvironment(@NonNull String);
- method @NonNull public java.io.File getCredentialProtectedDataDirForUser(@NonNull android.os.UserHandle);
- method @NonNull public java.io.File getDeviceProtectedDataDir();
- method @NonNull public java.io.File getDeviceProtectedDataDirForUser(@NonNull android.os.UserHandle);
- }
-
public final class AutofillOptions implements android.os.Parcelable {
ctor public AutofillOptions(int, boolean);
method public int describeContents();
@@ -897,36 +474,21 @@ package android.content {
method @NonNull public static android.os.UserHandle getUserHandleFromUri(@NonNull android.net.Uri);
}
- public class ContentProviderClient implements java.lang.AutoCloseable {
- method @RequiresPermission(android.Manifest.permission.REMOVE_TASKS) public void setDetectNotResponding(long);
- }
-
public abstract class ContentResolver {
- method @NonNull public static android.net.Uri decodeFromFile(@NonNull java.io.File);
- method @NonNull public static java.io.File encodeToFile(@NonNull android.net.Uri);
method public static String[] getSyncAdapterPackagesForAuthorityAsUser(String, int);
}
public abstract class Context {
- method @NonNull public android.content.Context createContextAsUser(@NonNull android.os.UserHandle, int);
- method @NonNull public android.content.Context createPackageContextAsUser(@NonNull String, int, @NonNull android.os.UserHandle) throws android.content.pm.PackageManager.NameNotFoundException;
method @NonNull public java.io.File getCrateDir(@NonNull String);
method public abstract int getDisplayId();
method public android.os.UserHandle getUser();
method public int getUserId();
method public void setAutofillOptions(@Nullable android.content.AutofillOptions);
method public void setContentCaptureOptions(@Nullable android.content.ContentCaptureOptions);
- method @RequiresPermission(android.Manifest.permission.INTERACT_ACROSS_USERS) public void startActivityAsUser(@NonNull @RequiresPermission android.content.Intent, @NonNull android.os.UserHandle);
- field public static final String APP_INTEGRITY_SERVICE = "app_integrity";
- field public static final String BUGREPORT_SERVICE = "bugreport";
field public static final String CONTENT_CAPTURE_MANAGER_SERVICE = "content_capture";
field public static final String DEVICE_IDLE_CONTROLLER = "deviceidle";
field public static final String DREAM_SERVICE = "dream";
- field public static final String ETHERNET_SERVICE = "ethernet";
- field public static final String PERMISSION_SERVICE = "permission";
field public static final String POWER_WHITELIST_MANAGER = "power_whitelist";
- field public static final String ROLLBACK_SERVICE = "rollback";
- field public static final String STATUS_BAR_SERVICE = "statusbar";
field public static final String TEST_NETWORK_SERVICE = "test_network";
}
@@ -934,75 +496,13 @@ package android.content {
method public int getDisplayId();
}
- public class Intent implements java.lang.Cloneable android.os.Parcelable {
- field @RequiresPermission(android.Manifest.permission.MANAGE_ROLE_HOLDERS) public static final String ACTION_MANAGE_DEFAULT_APP = "android.intent.action.MANAGE_DEFAULT_APP";
- field public static final String ACTION_ROLLBACK_COMMITTED = "android.intent.action.ROLLBACK_COMMITTED";
- field public static final String EXTRA_ORIGINATING_UID = "android.intent.extra.ORIGINATING_UID";
- field public static final String EXTRA_ROLE_NAME = "android.intent.extra.ROLE_NAME";
- }
-
}
package android.content.integrity {
public class AppIntegrityManager {
method @NonNull public android.content.integrity.RuleSet getCurrentRuleSet();
- method @NonNull public String getCurrentRuleSetProvider();
- method @NonNull public String getCurrentRuleSetVersion();
method @NonNull public java.util.List<java.lang.String> getWhitelistedRuleProviders();
- method public void updateRuleSet(@NonNull android.content.integrity.RuleSet, @NonNull android.content.IntentSender);
- field public static final String EXTRA_STATUS = "android.content.integrity.extra.STATUS";
- field public static final int STATUS_FAILURE = 1; // 0x1
- field public static final int STATUS_SUCCESS = 0; // 0x0
- }
-
- public abstract class IntegrityFormula {
- method @NonNull public static android.content.integrity.IntegrityFormula all(@NonNull android.content.integrity.IntegrityFormula...);
- method @NonNull public static android.content.integrity.IntegrityFormula any(@NonNull android.content.integrity.IntegrityFormula...);
- method @NonNull public static android.content.integrity.IntegrityFormula not(@NonNull android.content.integrity.IntegrityFormula);
- }
-
- public static final class IntegrityFormula.Application {
- method @NonNull public static android.content.integrity.IntegrityFormula certificatesContain(@NonNull String);
- method @NonNull public static android.content.integrity.IntegrityFormula isPreInstalled();
- method @NonNull public static android.content.integrity.IntegrityFormula packageNameEquals(@NonNull String);
- method @NonNull public static android.content.integrity.IntegrityFormula versionCodeEquals(@NonNull long);
- method @NonNull public static android.content.integrity.IntegrityFormula versionCodeGreaterThan(@NonNull long);
- method @NonNull public static android.content.integrity.IntegrityFormula versionCodeGreaterThanOrEqualTo(@NonNull long);
- }
-
- public static final class IntegrityFormula.Installer {
- method @NonNull public static android.content.integrity.IntegrityFormula certificatesContain(@NonNull String);
- method @NonNull public static android.content.integrity.IntegrityFormula notAllowedByManifest();
- method @NonNull public static android.content.integrity.IntegrityFormula packageNameEquals(@NonNull String);
- }
-
- public static final class IntegrityFormula.SourceStamp {
- method @NonNull public static android.content.integrity.IntegrityFormula notTrusted();
- method @NonNull public static android.content.integrity.IntegrityFormula stampCertificateHashEquals(@NonNull String);
- }
-
- public final class Rule implements android.os.Parcelable {
- ctor public Rule(@NonNull android.content.integrity.IntegrityFormula, int);
- method public int describeContents();
- method public int getEffect();
- method @NonNull public android.content.integrity.IntegrityFormula getFormula();
- method public void writeToParcel(@NonNull android.os.Parcel, int);
- field @NonNull public static final android.os.Parcelable.Creator<android.content.integrity.Rule> CREATOR;
- field public static final int DENY = 0; // 0x0
- field public static final int FORCE_ALLOW = 1; // 0x1
- }
-
- public class RuleSet {
- method @NonNull public java.util.List<android.content.integrity.Rule> getRules();
- method @NonNull public String getVersion();
- }
-
- public static class RuleSet.Builder {
- ctor public RuleSet.Builder();
- method @NonNull public android.content.integrity.RuleSet.Builder addRules(@NonNull java.util.List<android.content.integrity.Rule>);
- method @NonNull public android.content.integrity.RuleSet build();
- method @NonNull public android.content.integrity.RuleSet.Builder setVersion(@NonNull String);
}
}
@@ -1019,95 +519,38 @@ package android.content.pm {
method public boolean isSystemApp();
field public static final int PRIVATE_FLAG_PRIVILEGED = 8; // 0x8
field public int privateFlags;
- field public int targetSandboxVersion;
}
public class LauncherApps {
ctor public LauncherApps(android.content.Context);
}
- public static class PackageInstaller.SessionInfo implements android.os.Parcelable {
- method public int getAutoRevokePermissionsMode();
- method public int getRollbackDataPolicy();
- method @NonNull public java.util.Set<java.lang.String> getWhitelistedRestrictedPermissions();
- }
-
public static class PackageInstaller.SessionParams implements android.os.Parcelable {
- method public void setEnableRollback(boolean);
- method public void setEnableRollback(boolean, int);
- method @RequiresPermission(android.Manifest.permission.INSTALL_GRANT_RUNTIME_PERMISSIONS) public void setGrantedRuntimePermissions(String[]);
- method @RequiresPermission(android.Manifest.permission.INSTALL_PACKAGES) public void setInstallAsApex();
- method public void setInstallAsInstantApp(boolean);
method public void setInstallerPackageName(@Nullable String);
- method public void setRequestDowngrade(boolean);
- method @RequiresPermission(android.Manifest.permission.INSTALL_PACKAGES) public void setStaged();
}
public abstract class PackageManager {
- method @RequiresPermission("android.permission.OBSERVE_GRANT_REVOKE_PERMISSIONS") public abstract void addOnPermissionsChangeListener(@NonNull android.content.pm.PackageManager.OnPermissionsChangedListener);
- method public abstract boolean arePermissionsIndividuallyControlled();
method @Nullable public String getContentCaptureServicePackageName();
- method @Nullable @RequiresPermission(android.Manifest.permission.INTERACT_ACROSS_USERS_FULL) public abstract String getDefaultBrowserPackageNameAsUser(int);
method @Nullable public String getDefaultTextClassifierPackageName();
- method @Nullable public String getIncidentReportApproverPackageName();
method public abstract int getInstallReason(@NonNull String, @NonNull android.os.UserHandle);
method @NonNull public abstract java.util.List<android.content.pm.ApplicationInfo> getInstalledApplicationsAsUser(int, int);
- method @NonNull @RequiresPermission(android.Manifest.permission.INTERACT_ACROSS_USERS_FULL) public abstract java.util.List<android.content.pm.PackageInfo> getInstalledPackagesAsUser(int, int);
method @Nullable public abstract String[] getNamesForUids(int[]);
method @NonNull public abstract String getPermissionControllerPackageName();
- method @android.content.pm.PackageManager.PermissionFlags @RequiresPermission(anyOf={android.Manifest.permission.GRANT_RUNTIME_PERMISSIONS, android.Manifest.permission.REVOKE_RUNTIME_PERMISSIONS, android.Manifest.permission.GET_RUNTIME_PERMISSIONS}) public abstract int getPermissionFlags(@NonNull String, @NonNull String, @NonNull android.os.UserHandle);
method @NonNull public abstract String getServicesSystemSharedLibraryPackageName();
method @NonNull public abstract String getSharedSystemSharedLibraryPackageName();
method @Nullable public String getSystemTextClassifierPackageName();
method @Nullable public String getWellbeingPackageName();
- method @RequiresPermission(android.Manifest.permission.GRANT_RUNTIME_PERMISSIONS) public abstract void grantRuntimePermission(@NonNull String, @NonNull String, @NonNull android.os.UserHandle);
method @RequiresPermission(android.Manifest.permission.INJECT_EVENTS) public void holdLock(int);
- method @RequiresPermission("android.permission.OBSERVE_GRANT_REVOKE_PERMISSIONS") public abstract void removeOnPermissionsChangeListener(@NonNull android.content.pm.PackageManager.OnPermissionsChangedListener);
- method @RequiresPermission(android.Manifest.permission.REVOKE_RUNTIME_PERMISSIONS) public abstract void revokeRuntimePermission(@NonNull String, @NonNull String, @NonNull android.os.UserHandle);
- method @RequiresPermission(android.Manifest.permission.REVOKE_RUNTIME_PERMISSIONS) public void revokeRuntimePermission(@NonNull String, @NonNull String, @NonNull android.os.UserHandle, @NonNull String);
- 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);
field public static final String FEATURE_ADOPTABLE_STORAGE = "android.software.adoptable_storage";
field public static final String FEATURE_FILE_BASED_ENCRYPTION = "android.software.file_based_encryption";
- field public static final int FLAG_PERMISSION_APPLY_RESTRICTION = 16384; // 0x4000
- field public static final int FLAG_PERMISSION_GRANTED_BY_DEFAULT = 32; // 0x20
- field public static final int FLAG_PERMISSION_GRANTED_BY_ROLE = 32768; // 0x8000
- field public static final int FLAG_PERMISSION_ONE_TIME = 65536; // 0x10000
- field public static final int FLAG_PERMISSION_POLICY_FIXED = 4; // 0x4
- field public static final int FLAG_PERMISSION_RESTRICTION_INSTALLER_EXEMPT = 2048; // 0x800
- field public static final int FLAG_PERMISSION_RESTRICTION_ROLE_EXEMPT = 262144; // 0x40000
- field public static final int FLAG_PERMISSION_RESTRICTION_SYSTEM_EXEMPT = 4096; // 0x1000
- field public static final int FLAG_PERMISSION_RESTRICTION_UPGRADE_EXEMPT = 8192; // 0x2000
- field public static final int FLAG_PERMISSION_REVIEW_REQUIRED = 64; // 0x40
- field public static final int FLAG_PERMISSION_REVOKED_COMPAT = 8; // 0x8
- field @Deprecated public static final int FLAG_PERMISSION_REVOKE_ON_UPGRADE = 8; // 0x8
field public static final int FLAG_PERMISSION_REVOKE_WHEN_REQUESTED = 128; // 0x80
- field public static final int FLAG_PERMISSION_SYSTEM_FIXED = 16; // 0x10
- field public static final int FLAG_PERMISSION_USER_FIXED = 2; // 0x2
- field public static final int FLAG_PERMISSION_USER_SET = 1; // 0x1
- field public static final int MATCH_FACTORY_ONLY = 2097152; // 0x200000
field public static final int MATCH_KNOWN_PACKAGES = 4202496; // 0x402000
- field public static final int MODULE_APEX_NAME = 1; // 0x1
field public static final String SYSTEM_SHARED_LIBRARY_SERVICES = "android.ext.services";
field public static final String SYSTEM_SHARED_LIBRARY_SHARED = "android.ext.shared";
}
- public static interface PackageManager.OnPermissionsChangedListener {
- method public void onPermissionsChanged(int);
- }
-
public class PermissionInfo extends android.content.pm.PackageItemInfo implements android.os.Parcelable {
- field public static final int FLAG_REMOVED = 2; // 0x2
- field public static final int PROTECTION_FLAG_APP_PREDICTOR = 2097152; // 0x200000
- field public static final int PROTECTION_FLAG_COMPANION = 8388608; // 0x800000
- field public static final int PROTECTION_FLAG_CONFIGURATOR = 524288; // 0x80000
- field public static final int PROTECTION_FLAG_DOCUMENTER = 262144; // 0x40000
- field public static final int PROTECTION_FLAG_INCIDENT_REPORT_APPROVER = 1048576; // 0x100000
- field public static final int PROTECTION_FLAG_OEM = 16384; // 0x4000
- field public static final int PROTECTION_FLAG_RETAIL_DEMO = 16777216; // 0x1000000
- field public static final int PROTECTION_FLAG_SYSTEM_TEXT_CLASSIFIER = 65536; // 0x10000
field public static final int PROTECTION_FLAG_VENDOR_PRIVILEGED = 32768; // 0x8000
- field public static final int PROTECTION_FLAG_WELLBEING = 131072; // 0x20000
- field @Nullable public final String backgroundPermission;
}
public final class ProviderInfoList implements android.os.Parcelable {
@@ -1146,40 +589,11 @@ package android.content.res {
package android.content.rollback {
- public final class PackageRollbackInfo implements android.os.Parcelable {
- method public int describeContents();
- method @NonNull public String getPackageName();
- method @NonNull public android.content.pm.VersionedPackage getVersionRolledBackFrom();
- method @NonNull public android.content.pm.VersionedPackage getVersionRolledBackTo();
- method public void writeToParcel(android.os.Parcel, int);
- field @NonNull public static final android.os.Parcelable.Creator<android.content.rollback.PackageRollbackInfo> CREATOR;
- }
-
- public final class RollbackInfo implements android.os.Parcelable {
- method public int describeContents();
- method @NonNull public java.util.List<android.content.pm.VersionedPackage> getCausePackages();
- method public int getCommittedSessionId();
- method @NonNull public java.util.List<android.content.rollback.PackageRollbackInfo> getPackages();
- method public int getRollbackId();
- method public boolean isStaged();
- method public void writeToParcel(android.os.Parcel, int);
- field @NonNull public static final android.os.Parcelable.Creator<android.content.rollback.RollbackInfo> CREATOR;
- }
-
public final class RollbackManager {
method @RequiresPermission(android.Manifest.permission.TEST_MANAGE_ROLLBACKS) public void blockRollbackManager(long);
- method @RequiresPermission(anyOf={android.Manifest.permission.MANAGE_ROLLBACKS, android.Manifest.permission.TEST_MANAGE_ROLLBACKS}) public void commitRollback(int, @NonNull java.util.List<android.content.pm.VersionedPackage>, @NonNull android.content.IntentSender);
method @RequiresPermission(android.Manifest.permission.TEST_MANAGE_ROLLBACKS) public void expireRollbackForPackage(@NonNull String);
- method @NonNull @RequiresPermission(anyOf={android.Manifest.permission.MANAGE_ROLLBACKS, android.Manifest.permission.TEST_MANAGE_ROLLBACKS}) public java.util.List<android.content.rollback.RollbackInfo> getAvailableRollbacks();
- method @NonNull @RequiresPermission(anyOf={android.Manifest.permission.MANAGE_ROLLBACKS, android.Manifest.permission.TEST_MANAGE_ROLLBACKS}) public java.util.List<android.content.rollback.RollbackInfo> getRecentlyCommittedRollbacks();
method @RequiresPermission(android.Manifest.permission.TEST_MANAGE_ROLLBACKS) public void reloadPersistedData();
- field public static final String EXTRA_STATUS = "android.content.rollback.extra.STATUS";
- field public static final String EXTRA_STATUS_MESSAGE = "android.content.rollback.extra.STATUS_MESSAGE";
field public static final String PROPERTY_ROLLBACK_LIFETIME_MILLIS = "rollback_lifetime_in_millis";
- field public static final int STATUS_FAILURE = 1; // 0x1
- field public static final int STATUS_FAILURE_INSTALL = 3; // 0x3
- field public static final int STATUS_FAILURE_ROLLBACK_UNAVAILABLE = 2; // 0x2
- field public static final int STATUS_SUCCESS = 0; // 0x0
}
}
@@ -1272,8 +686,8 @@ package android.hardware.biometrics {
method @RequiresPermission(android.Manifest.permission.TEST_BIOMETRIC) public void cleanupInternalState(int);
method @RequiresPermission(android.Manifest.permission.TEST_BIOMETRIC) public void close();
method @RequiresPermission(android.Manifest.permission.TEST_BIOMETRIC) public void finishEnroll(int);
- method @RequiresPermission(android.Manifest.permission.TEST_BIOMETRIC) public void notifyAcquired(int);
- method @RequiresPermission(android.Manifest.permission.TEST_BIOMETRIC) public void notifyError(int);
+ method @RequiresPermission(android.Manifest.permission.TEST_BIOMETRIC) public void notifyAcquired(int, int);
+ method @RequiresPermission(android.Manifest.permission.TEST_BIOMETRIC) public void notifyError(int, int);
method @RequiresPermission(android.Manifest.permission.TEST_BIOMETRIC) public void rejectAuthentication(int);
method @RequiresPermission(android.Manifest.permission.TEST_BIOMETRIC) public void startEnroll(int);
}
@@ -1290,13 +704,6 @@ package android.hardware.biometrics {
package android.hardware.camera2 {
- public abstract class CameraDevice implements java.lang.AutoCloseable {
- method @Deprecated public abstract void createCustomCaptureSession(android.hardware.camera2.params.InputConfiguration, @NonNull java.util.List<android.hardware.camera2.params.OutputConfiguration>, int, @NonNull android.hardware.camera2.CameraCaptureSession.StateCallback, @Nullable android.os.Handler) throws android.hardware.camera2.CameraAccessException;
- field public static final int SESSION_OPERATION_MODE_CONSTRAINED_HIGH_SPEED = 1; // 0x1
- field public static final int SESSION_OPERATION_MODE_NORMAL = 0; // 0x0
- field public static final int SESSION_OPERATION_MODE_VENDOR_START = 32768; // 0x8000
- }
-
public final class CameraManager {
method public String[] getCameraIdListNoLazy() throws android.hardware.camera2.CameraAccessException;
}
@@ -1305,15 +712,6 @@ package android.hardware.camera2 {
package android.hardware.display {
- public final class AmbientBrightnessDayStats implements android.os.Parcelable {
- method public int describeContents();
- method public float[] getBucketBoundaries();
- method public java.time.LocalDate getLocalDate();
- method public float[] getStats();
- method public void writeToParcel(android.os.Parcel, int);
- field @NonNull public static final android.os.Parcelable.Creator<android.hardware.display.AmbientBrightnessDayStats> CREATOR;
- }
-
public class AmbientDisplayConfiguration {
ctor public AmbientDisplayConfiguration(android.content.Context);
method public boolean alwaysOnAvailable();
@@ -1321,70 +719,8 @@ package android.hardware.display {
method public boolean alwaysOnEnabled(int);
}
- public final class BrightnessChangeEvent implements android.os.Parcelable {
- method public int describeContents();
- method public void writeToParcel(android.os.Parcel, int);
- field @NonNull public static final android.os.Parcelable.Creator<android.hardware.display.BrightnessChangeEvent> CREATOR;
- field public final float batteryLevel;
- field public final float brightness;
- field public final long colorSampleDuration;
- field public final int colorTemperature;
- field @Nullable public final long[] colorValueBuckets;
- field public final boolean isDefaultBrightnessConfig;
- field public final boolean isUserSetBrightness;
- field public final float lastBrightness;
- field public final long[] luxTimestamps;
- field public final float[] luxValues;
- field public final boolean nightMode;
- field public final String packageName;
- field public final float powerBrightnessFactor;
- field public final long timeStamp;
- }
-
- public final class BrightnessConfiguration implements android.os.Parcelable {
- method public int describeContents();
- method @Nullable public android.hardware.display.BrightnessCorrection getCorrectionByCategory(int);
- method @Nullable public android.hardware.display.BrightnessCorrection getCorrectionByPackageName(@NonNull String);
- method public android.util.Pair<float[],float[]> getCurve();
- method public float getShortTermModelLowerLuxMultiplier();
- method public long getShortTermModelTimeoutMillis();
- method public float getShortTermModelUpperLuxMultiplier();
- method public boolean shouldCollectColorSamples();
- method public void writeToParcel(android.os.Parcel, int);
- field @NonNull public static final android.os.Parcelable.Creator<android.hardware.display.BrightnessConfiguration> CREATOR;
- field public static final long SHORT_TERM_TIMEOUT_UNSET = -1L; // 0xffffffffffffffffL
- }
-
- public static class BrightnessConfiguration.Builder {
- ctor public BrightnessConfiguration.Builder(float[], float[]);
- method @NonNull public android.hardware.display.BrightnessConfiguration.Builder addCorrectionByCategory(int, @NonNull android.hardware.display.BrightnessCorrection);
- method @NonNull public android.hardware.display.BrightnessConfiguration.Builder addCorrectionByPackageName(@NonNull String, @NonNull android.hardware.display.BrightnessCorrection);
- method @NonNull public android.hardware.display.BrightnessConfiguration build();
- method public int getMaxCorrectionsByCategory();
- method public int getMaxCorrectionsByPackageName();
- method @NonNull public android.hardware.display.BrightnessConfiguration.Builder setDescription(@Nullable String);
- method @NonNull public android.hardware.display.BrightnessConfiguration.Builder setShortTermModelLowerLuxMultiplier(@FloatRange(from=0.0f) float);
- method @NonNull public android.hardware.display.BrightnessConfiguration.Builder setShortTermModelTimeoutMillis(long);
- method @NonNull public android.hardware.display.BrightnessConfiguration.Builder setShortTermModelUpperLuxMultiplier(@FloatRange(from=0.0f) float);
- method @NonNull public android.hardware.display.BrightnessConfiguration.Builder setShouldCollectColorSamples(boolean);
- }
-
- public final class BrightnessCorrection implements android.os.Parcelable {
- method @FloatRange(from=0.0) public float apply(@FloatRange(from=0.0) float);
- method @NonNull public static android.hardware.display.BrightnessCorrection createScaleAndTranslateLog(float, float);
- method public int describeContents();
- method public void writeToParcel(android.os.Parcel, int);
- field @NonNull public static final android.os.Parcelable.Creator<android.hardware.display.BrightnessCorrection> CREATOR;
- }
-
public final class DisplayManager {
- method @RequiresPermission(android.Manifest.permission.ACCESS_AMBIENT_LIGHT_STATS) public java.util.List<android.hardware.display.AmbientBrightnessDayStats> getAmbientBrightnessStats();
- method @RequiresPermission(android.Manifest.permission.CONFIGURE_DISPLAY_BRIGHTNESS) public android.hardware.display.BrightnessConfiguration getBrightnessConfiguration();
- method @RequiresPermission(android.Manifest.permission.BRIGHTNESS_SLIDER_USAGE) public java.util.List<android.hardware.display.BrightnessChangeEvent> getBrightnessEvents();
- method @Nullable @RequiresPermission(android.Manifest.permission.CONFIGURE_DISPLAY_BRIGHTNESS) public android.hardware.display.BrightnessConfiguration getDefaultBrightnessConfiguration();
- method public android.graphics.Point getStableDisplaySize();
method public boolean isMinimalPostProcessingRequested(int);
- method @RequiresPermission(android.Manifest.permission.CONFIGURE_DISPLAY_BRIGHTNESS) public void setBrightnessConfiguration(android.hardware.display.BrightnessConfiguration);
method @RequiresPermission(android.Manifest.permission.OVERRIDE_DISPLAY_MODE_REQUESTS) public void setShouldAlwaysRespectAppRequestedMode(boolean);
method @RequiresPermission(android.Manifest.permission.OVERRIDE_DISPLAY_MODE_REQUESTS) public boolean shouldAlwaysRespectAppRequestedMode();
field public static final int VIRTUAL_DISPLAY_FLAG_SHOULD_SHOW_SYSTEM_DECORATIONS = 512; // 0x200
@@ -1404,97 +740,6 @@ package android.hardware.fingerprint {
package android.hardware.hdmi {
- public final class HdmiControlManager {
- method @Nullable public android.hardware.hdmi.HdmiSwitchClient getSwitchClient();
- method @RequiresPermission(android.Manifest.permission.HDMI_CEC) public void setStandbyMode(boolean);
- field public static final String ACTION_OSD_MESSAGE = "android.hardware.hdmi.action.OSD_MESSAGE";
- field public static final int AVR_VOLUME_MUTED = 101; // 0x65
- field public static final int CLEAR_TIMER_STATUS_CEC_DISABLE = 162; // 0xa2
- field public static final int CLEAR_TIMER_STATUS_CHECK_RECORDER_CONNECTION = 160; // 0xa0
- field public static final int CLEAR_TIMER_STATUS_FAIL_TO_CLEAR_SELECTED_SOURCE = 161; // 0xa1
- field public static final int CLEAR_TIMER_STATUS_TIMER_CLEARED = 128; // 0x80
- field public static final int CLEAR_TIMER_STATUS_TIMER_NOT_CLEARED_NO_INFO_AVAILABLE = 2; // 0x2
- field public static final int CLEAR_TIMER_STATUS_TIMER_NOT_CLEARED_NO_MATCHING = 1; // 0x1
- field public static final int CLEAR_TIMER_STATUS_TIMER_NOT_CLEARED_RECORDING = 0; // 0x0
- field public static final int CONTROL_STATE_CHANGED_REASON_SETTING = 1; // 0x1
- field public static final int CONTROL_STATE_CHANGED_REASON_STANDBY = 3; // 0x3
- field public static final int CONTROL_STATE_CHANGED_REASON_START = 0; // 0x0
- field public static final int CONTROL_STATE_CHANGED_REASON_WAKEUP = 2; // 0x2
- field public static final int DEVICE_EVENT_ADD_DEVICE = 1; // 0x1
- field public static final int DEVICE_EVENT_REMOVE_DEVICE = 2; // 0x2
- field public static final int DEVICE_EVENT_UPDATE_DEVICE = 3; // 0x3
- field public static final String EXTRA_MESSAGE_EXTRA_PARAM1 = "android.hardware.hdmi.extra.MESSAGE_EXTRA_PARAM1";
- field public static final String EXTRA_MESSAGE_ID = "android.hardware.hdmi.extra.MESSAGE_ID";
- field public static final int ONE_TOUCH_RECORD_ALREADY_RECORDING = 18; // 0x12
- field public static final int ONE_TOUCH_RECORD_CEC_DISABLED = 51; // 0x33
- field public static final int ONE_TOUCH_RECORD_CHECK_RECORDER_CONNECTION = 49; // 0x31
- field public static final int ONE_TOUCH_RECORD_DISALLOW_TO_COPY = 13; // 0xd
- field public static final int ONE_TOUCH_RECORD_DISALLOW_TO_FUTHER_COPIES = 14; // 0xe
- field public static final int ONE_TOUCH_RECORD_FAIL_TO_RECORD_DISPLAYED_SCREEN = 50; // 0x32
- field public static final int ONE_TOUCH_RECORD_INVALID_EXTERNAL_PHYSICAL_ADDRESS = 10; // 0xa
- field public static final int ONE_TOUCH_RECORD_INVALID_EXTERNAL_PLUG_NUMBER = 9; // 0x9
- field public static final int ONE_TOUCH_RECORD_MEDIA_PROBLEM = 21; // 0x15
- field public static final int ONE_TOUCH_RECORD_MEDIA_PROTECTED = 19; // 0x13
- field public static final int ONE_TOUCH_RECORD_NOT_ENOUGH_SPACE = 22; // 0x16
- field public static final int ONE_TOUCH_RECORD_NO_MEDIA = 16; // 0x10
- field public static final int ONE_TOUCH_RECORD_NO_OR_INSUFFICIENT_CA_ENTITLEMENTS = 12; // 0xc
- field public static final int ONE_TOUCH_RECORD_NO_SOURCE_SIGNAL = 20; // 0x14
- field public static final int ONE_TOUCH_RECORD_OTHER_REASON = 31; // 0x1f
- field public static final int ONE_TOUCH_RECORD_PARENT_LOCK_ON = 23; // 0x17
- field public static final int ONE_TOUCH_RECORD_PLAYING = 17; // 0x11
- field public static final int ONE_TOUCH_RECORD_PREVIOUS_RECORDING_IN_PROGRESS = 48; // 0x30
- field public static final int ONE_TOUCH_RECORD_RECORDING_ALREADY_TERMINATED = 27; // 0x1b
- field public static final int ONE_TOUCH_RECORD_RECORDING_ANALOGUE_SERVICE = 3; // 0x3
- field public static final int ONE_TOUCH_RECORD_RECORDING_CURRENTLY_SELECTED_SOURCE = 1; // 0x1
- field public static final int ONE_TOUCH_RECORD_RECORDING_DIGITAL_SERVICE = 2; // 0x2
- field public static final int ONE_TOUCH_RECORD_RECORDING_EXTERNAL_INPUT = 4; // 0x4
- field public static final int ONE_TOUCH_RECORD_RECORDING_TERMINATED_NORMALLY = 26; // 0x1a
- field public static final int ONE_TOUCH_RECORD_UNABLE_ANALOGUE_SERVICE = 6; // 0x6
- field public static final int ONE_TOUCH_RECORD_UNABLE_DIGITAL_SERVICE = 5; // 0x5
- field public static final int ONE_TOUCH_RECORD_UNABLE_SELECTED_SERVICE = 7; // 0x7
- field public static final int ONE_TOUCH_RECORD_UNSUPPORTED_CA = 11; // 0xb
- field public static final int OSD_MESSAGE_ARC_CONNECTED_INVALID_PORT = 1; // 0x1
- field public static final int OSD_MESSAGE_AVR_VOLUME_CHANGED = 2; // 0x2
- field public static final int POWER_STATUS_ON = 0; // 0x0
- field public static final int POWER_STATUS_STANDBY = 1; // 0x1
- field public static final int POWER_STATUS_TRANSIENT_TO_ON = 2; // 0x2
- field public static final int POWER_STATUS_TRANSIENT_TO_STANDBY = 3; // 0x3
- field public static final int POWER_STATUS_UNKNOWN = -1; // 0xffffffff
- field @Deprecated public static final int RESULT_ALREADY_IN_PROGRESS = 4; // 0x4
- field public static final int RESULT_COMMUNICATION_FAILED = 7; // 0x7
- field public static final int RESULT_EXCEPTION = 5; // 0x5
- field public static final int RESULT_INCORRECT_MODE = 6; // 0x6
- field public static final int RESULT_SOURCE_NOT_AVAILABLE = 2; // 0x2
- field public static final int RESULT_SUCCESS = 0; // 0x0
- field public static final int RESULT_TARGET_NOT_AVAILABLE = 3; // 0x3
- field public static final int RESULT_TIMEOUT = 1; // 0x1
- field public static final int TIMER_RECORDING_RESULT_EXTRA_CEC_DISABLED = 3; // 0x3
- field public static final int TIMER_RECORDING_RESULT_EXTRA_CHECK_RECORDER_CONNECTION = 1; // 0x1
- field public static final int TIMER_RECORDING_RESULT_EXTRA_FAIL_TO_RECORD_SELECTED_SOURCE = 2; // 0x2
- field public static final int TIMER_RECORDING_RESULT_EXTRA_NO_ERROR = 0; // 0x0
- field public static final int TIMER_RECORDING_TYPE_ANALOGUE = 2; // 0x2
- field public static final int TIMER_RECORDING_TYPE_DIGITAL = 1; // 0x1
- field public static final int TIMER_RECORDING_TYPE_EXTERNAL = 3; // 0x3
- field public static final int TIMER_STATUS_MEDIA_INFO_NOT_PRESENT = 2; // 0x2
- field public static final int TIMER_STATUS_MEDIA_INFO_PRESENT_NOT_PROTECTED = 0; // 0x0
- field public static final int TIMER_STATUS_MEDIA_INFO_PRESENT_PROTECTED = 1; // 0x1
- field public static final int TIMER_STATUS_NOT_PROGRAMMED_CA_NOT_SUPPORTED = 6; // 0x6
- field public static final int TIMER_STATUS_NOT_PROGRAMMED_CLOCK_FAILURE = 10; // 0xa
- field public static final int TIMER_STATUS_NOT_PROGRAMMED_DATE_OUT_OF_RANGE = 2; // 0x2
- field public static final int TIMER_STATUS_NOT_PROGRAMMED_DUPLICATED = 14; // 0xe
- field public static final int TIMER_STATUS_NOT_PROGRAMMED_INVALID_EXTERNAL_PHYSICAL_NUMBER = 5; // 0x5
- field public static final int TIMER_STATUS_NOT_PROGRAMMED_INVALID_EXTERNAL_PLUG_NUMBER = 4; // 0x4
- field public static final int TIMER_STATUS_NOT_PROGRAMMED_INVALID_SEQUENCE = 3; // 0x3
- field public static final int TIMER_STATUS_NOT_PROGRAMMED_NO_CA_ENTITLEMENTS = 7; // 0x7
- field public static final int TIMER_STATUS_NOT_PROGRAMMED_NO_FREE_TIME = 1; // 0x1
- field public static final int TIMER_STATUS_NOT_PROGRAMMED_PARENTAL_LOCK_ON = 9; // 0x9
- field public static final int TIMER_STATUS_NOT_PROGRAMMED_UNSUPPORTED_RESOLUTION = 8; // 0x8
- field public static final int TIMER_STATUS_PROGRAMMED_INFO_ENOUGH_SPACE = 8; // 0x8
- field public static final int TIMER_STATUS_PROGRAMMED_INFO_MIGHT_NOT_ENOUGH_SPACE = 11; // 0xb
- field public static final int TIMER_STATUS_PROGRAMMED_INFO_NOT_ENOUGH_SPACE = 9; // 0x9
- field public static final int TIMER_STATUS_PROGRAMMED_INFO_NO_MEDIA_INFO = 10; // 0xa
- }
-
public final class HdmiControlServiceWrapper {
ctor public HdmiControlServiceWrapper();
method @NonNull public android.hardware.hdmi.HdmiControlManager createHdmiControlManager();
@@ -1503,25 +748,6 @@ package android.hardware.hdmi {
field public static final int DEVICE_PURE_CEC_SWITCH = 6; // 0x6
}
- public final class HdmiPortInfo implements android.os.Parcelable {
- ctor public HdmiPortInfo(int, int, int, boolean, boolean, boolean);
- method public int describeContents();
- method public int getAddress();
- method public int getId();
- method public int getType();
- method public boolean isArcSupported();
- method public boolean isCecSupported();
- method public boolean isMhlSupported();
- field @NonNull public static final android.os.Parcelable.Creator<android.hardware.hdmi.HdmiPortInfo> CREATOR;
- field public static final int PORT_INPUT = 0; // 0x0
- field public static final int PORT_OUTPUT = 1; // 0x1
- }
-
- public class HdmiSwitchClient extends android.hardware.hdmi.HdmiClient {
- method public int getDeviceType();
- method @NonNull public java.util.List<android.hardware.hdmi.HdmiPortInfo> getPortInfo();
- }
-
}
package android.hardware.input {
@@ -1538,43 +764,8 @@ package android.hardware.input {
package android.hardware.lights {
- public final class Light implements android.os.Parcelable {
- method public int describeContents();
- method public int getId();
- method public int getOrdinal();
- method public int getType();
- method public void writeToParcel(@NonNull android.os.Parcel, int);
- field @NonNull public static final android.os.Parcelable.Creator<android.hardware.lights.Light> CREATOR;
- }
-
- public final class LightState implements android.os.Parcelable {
- ctor public LightState(@ColorInt int);
- method public int describeContents();
- method @ColorInt public int getColor();
- method public void writeToParcel(@NonNull android.os.Parcel, int);
- field @NonNull public static final android.os.Parcelable.Creator<android.hardware.lights.LightState> CREATOR;
- }
-
public final class LightsManager {
method @NonNull @RequiresPermission(android.Manifest.permission.CONTROL_DEVICE_LIGHTS) public android.hardware.lights.LightState getLightState(@NonNull android.hardware.lights.Light);
- method @NonNull @RequiresPermission(android.Manifest.permission.CONTROL_DEVICE_LIGHTS) public java.util.List<android.hardware.lights.Light> getLights();
- method @NonNull @RequiresPermission(android.Manifest.permission.CONTROL_DEVICE_LIGHTS) public android.hardware.lights.LightsManager.LightsSession openSession();
- field public static final int LIGHT_TYPE_MICROPHONE = 8; // 0x8
- }
-
- public final class LightsManager.LightsSession implements java.lang.AutoCloseable {
- method @RequiresPermission(android.Manifest.permission.CONTROL_DEVICE_LIGHTS) public void close();
- method @RequiresPermission(android.Manifest.permission.CONTROL_DEVICE_LIGHTS) public void requestLights(@NonNull android.hardware.lights.LightsRequest);
- }
-
- public final class LightsRequest {
- }
-
- public static final class LightsRequest.Builder {
- ctor public LightsRequest.Builder();
- method @NonNull public android.hardware.lights.LightsRequest build();
- method @NonNull public android.hardware.lights.LightsRequest.Builder clearLight(@NonNull android.hardware.lights.Light);
- method @NonNull public android.hardware.lights.LightsRequest.Builder setLight(@NonNull android.hardware.lights.Light, @NonNull android.hardware.lights.LightState);
}
}
@@ -1605,84 +796,16 @@ package android.hardware.soundtrigger {
field @NonNull public static final android.os.Parcelable.Creator<android.hardware.soundtrigger.KeyphraseMetadata> CREATOR;
}
- public class SoundTrigger {
- field public static final int RECOGNITION_MODE_GENERIC = 8; // 0x8
- field public static final int RECOGNITION_MODE_USER_AUTHENTICATION = 4; // 0x4
- field public static final int RECOGNITION_MODE_USER_IDENTIFICATION = 2; // 0x2
- field public static final int RECOGNITION_MODE_VOICE_TRIGGER = 1; // 0x1
- field public static final int STATUS_OK = 0; // 0x0
- }
-
- public static final class SoundTrigger.Keyphrase implements android.os.Parcelable {
- ctor public SoundTrigger.Keyphrase(int, int, @NonNull java.util.Locale, @NonNull String, @Nullable int[]);
- method public int getId();
- method @NonNull public java.util.Locale getLocale();
- method public int getRecognitionModes();
- method @NonNull public String getText();
- method @NonNull public int[] getUsers();
- method @NonNull public static android.hardware.soundtrigger.SoundTrigger.Keyphrase readFromParcel(@NonNull android.os.Parcel);
- method public void writeToParcel(@NonNull android.os.Parcel, int);
- field @NonNull public static final android.os.Parcelable.Creator<android.hardware.soundtrigger.SoundTrigger.Keyphrase> CREATOR;
- }
-
- public static final class SoundTrigger.KeyphraseSoundModel extends android.hardware.soundtrigger.SoundTrigger.SoundModel implements android.os.Parcelable {
- ctor public SoundTrigger.KeyphraseSoundModel(@NonNull java.util.UUID, @NonNull java.util.UUID, @Nullable byte[], @Nullable android.hardware.soundtrigger.SoundTrigger.Keyphrase[], int);
- ctor public SoundTrigger.KeyphraseSoundModel(@NonNull java.util.UUID, @NonNull java.util.UUID, @Nullable byte[], @Nullable android.hardware.soundtrigger.SoundTrigger.Keyphrase[]);
- method @NonNull public android.hardware.soundtrigger.SoundTrigger.Keyphrase[] getKeyphrases();
- method @NonNull public static android.hardware.soundtrigger.SoundTrigger.KeyphraseSoundModel readFromParcel(@NonNull android.os.Parcel);
- method public void writeToParcel(@NonNull android.os.Parcel, int);
- field @NonNull public static final android.os.Parcelable.Creator<android.hardware.soundtrigger.SoundTrigger.KeyphraseSoundModel> CREATOR;
- }
-
public static final class SoundTrigger.ModelParamRange implements android.os.Parcelable {
ctor public SoundTrigger.ModelParamRange(int, int);
- method public int getEnd();
- method public int getStart();
- method public void writeToParcel(@NonNull android.os.Parcel, int);
- field @NonNull public static final android.os.Parcelable.Creator<android.hardware.soundtrigger.SoundTrigger.ModelParamRange> CREATOR;
}
public static final class SoundTrigger.ModuleProperties implements android.os.Parcelable {
ctor public SoundTrigger.ModuleProperties(int, @NonNull String, @NonNull String, @NonNull String, int, @NonNull String, int, int, int, int, boolean, int, boolean, int, boolean, int);
- method public int describeContents();
- method public int getAudioCapabilities();
- method @NonNull public String getDescription();
- method public int getId();
- method @NonNull public String getImplementor();
- method public int getMaxBufferMillis();
- method public int getMaxKeyphrases();
- method public int getMaxSoundModels();
- method public int getMaxUsers();
- method public int getPowerConsumptionMw();
- method public int getRecognitionModes();
- method @NonNull public String getSupportedModelArch();
- method @NonNull public java.util.UUID getUuid();
- method public int getVersion();
- method public boolean isCaptureTransitionSupported();
- method public boolean isConcurrentCaptureSupported();
- method public boolean isTriggerReturnedInEvent();
- method public void writeToParcel(android.os.Parcel, int);
- field public static final int AUDIO_CAPABILITY_ECHO_CANCELLATION = 1; // 0x1
- field public static final int AUDIO_CAPABILITY_NOISE_SUPPRESSION = 2; // 0x2
- field @NonNull public static final android.os.Parcelable.Creator<android.hardware.soundtrigger.SoundTrigger.ModuleProperties> CREATOR;
}
public static class SoundTrigger.RecognitionEvent {
ctor public SoundTrigger.RecognitionEvent(int, int, boolean, int, int, int, boolean, @NonNull android.media.AudioFormat, @Nullable byte[]);
- method @Nullable public android.media.AudioFormat getCaptureFormat();
- method public int getCaptureSession();
- method public byte[] getData();
- method public boolean isCaptureAvailable();
- }
-
- public static class SoundTrigger.SoundModel {
- method @NonNull public byte[] getData();
- method public int getType();
- method @NonNull public java.util.UUID getUuid();
- method @NonNull public java.util.UUID getVendorUuid();
- method public int getVersion();
- field public static final int TYPE_GENERIC_SOUND = 1; // 0x1
- field public static final int TYPE_KEYPHRASE = 0; // 0x0
}
}
@@ -1781,59 +904,17 @@ package android.location {
method public void setType(int);
}
- public class Location implements android.os.Parcelable {
- method public void makeComplete();
- field @Deprecated public static final String EXTRA_NO_GPS_LOCATION = "noGPSLocation";
- }
-
public class LocationManager {
method @NonNull public String[] getBackgroundThrottlingWhitelist();
- method @Deprecated @RequiresPermission(anyOf={android.Manifest.permission.ACCESS_COARSE_LOCATION, android.Manifest.permission.ACCESS_FINE_LOCATION}) public void getCurrentLocation(@NonNull android.location.LocationRequest, @Nullable android.os.CancellationSignal, @NonNull java.util.concurrent.Executor, @NonNull java.util.function.Consumer<android.location.Location>);
method @NonNull public String[] getIgnoreSettingsWhitelist();
method @Deprecated @Nullable @RequiresPermission(android.Manifest.permission.READ_DEVICE_CONFIG) public java.util.List<java.lang.String> getProviderPackages(@NonNull String);
- method @Deprecated @RequiresPermission(anyOf={android.Manifest.permission.ACCESS_COARSE_LOCATION, android.Manifest.permission.ACCESS_FINE_LOCATION}) public void requestLocationUpdates(@Nullable android.location.LocationRequest, @NonNull android.location.LocationListener, @Nullable android.os.Looper);
- method @Deprecated @RequiresPermission(anyOf={android.Manifest.permission.ACCESS_COARSE_LOCATION, android.Manifest.permission.ACCESS_FINE_LOCATION}) public void requestLocationUpdates(@Nullable android.location.LocationRequest, @NonNull java.util.concurrent.Executor, @NonNull android.location.LocationListener);
- method @Deprecated @RequiresPermission(anyOf={android.Manifest.permission.ACCESS_COARSE_LOCATION, android.Manifest.permission.ACCESS_FINE_LOCATION}) public void requestLocationUpdates(@Nullable android.location.LocationRequest, @NonNull android.app.PendingIntent);
- method @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS) public void setLocationEnabledForUser(boolean, @NonNull android.os.UserHandle);
field public static final String FUSED_PROVIDER = "fused";
}
- public final class LocationRequest implements android.os.Parcelable {
- method @NonNull public android.os.WorkSource getWorkSource();
- method public boolean isHiddenFromAppOps();
- method public boolean isLocationSettingsIgnored();
- method public boolean isLowPower();
- field @Deprecated public static final int ACCURACY_BLOCK = 102; // 0x66
- field @Deprecated public static final int ACCURACY_CITY = 104; // 0x68
- field @Deprecated public static final int ACCURACY_FINE = 100; // 0x64
- field @Deprecated public static final int POWER_HIGH = 203; // 0xcb
- field @Deprecated public static final int POWER_LOW = 201; // 0xc9
- }
-
- public static final class LocationRequest.Builder {
- method @NonNull @RequiresPermission(android.Manifest.permission.UPDATE_APP_OPS_STATS) public android.location.LocationRequest.Builder setHiddenFromAppOps(boolean);
- method @NonNull @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS) public android.location.LocationRequest.Builder setLocationSettingsIgnored(boolean);
- method @NonNull @RequiresPermission(android.Manifest.permission.LOCATION_HARDWARE) public android.location.LocationRequest.Builder setLowPower(boolean);
- method @NonNull @RequiresPermission(android.Manifest.permission.UPDATE_DEVICE_STATS) public android.location.LocationRequest.Builder setWorkSource(@Nullable android.os.WorkSource);
- }
-
}
package android.media {
- public final class AudioFocusInfo implements android.os.Parcelable {
- method public int describeContents();
- method @NonNull public android.media.AudioAttributes getAttributes();
- method @NonNull public String getClientId();
- method public int getClientUid();
- method public int getFlags();
- method public int getGainRequest();
- method public int getLossReceived();
- method @NonNull public String getPackageName();
- method public void writeToParcel(android.os.Parcel, int);
- field @NonNull public static final android.os.Parcelable.Creator<android.media.AudioFocusInfo> CREATOR;
- }
-
public final class AudioFocusRequest {
method @Nullable public android.media.AudioManager.OnAudioFocusChangeListener getOnAudioFocusChangeListener();
}
@@ -1846,13 +927,7 @@ package android.media {
}
public class AudioManager {
- method @RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING) public int dispatchAudioFocusChange(@NonNull android.media.AudioFocusInfo, int, @NonNull android.media.audiopolicy.AudioPolicy);
method public boolean hasRegisteredDynamicPolicy();
- method @RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING) public int registerAudioPolicy(@NonNull android.media.audiopolicy.AudioPolicy);
- method @RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING) public void setFocusRequestResult(@NonNull android.media.AudioFocusInfo, int, @NonNull android.media.audiopolicy.AudioPolicy);
- method @RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING) public void unregisterAudioPolicy(@NonNull android.media.audiopolicy.AudioPolicy);
- method @RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING) public void unregisterAudioPolicyAsync(@NonNull android.media.audiopolicy.AudioPolicy);
- field public static final int SUCCESS = 0; // 0x0
}
public static final class AudioRecord.MetricsConstants {
@@ -1908,68 +983,6 @@ package android.media {
method @NonNull public String getOriginalId();
}
- public final class MediaTranscodeManager {
- method @NonNull public android.media.MediaTranscodeManager.TranscodingJob enqueueRequest(@NonNull android.media.MediaTranscodeManager.TranscodingRequest, @NonNull java.util.concurrent.Executor, @NonNull android.media.MediaTranscodeManager.OnTranscodingFinishedListener) throws java.io.FileNotFoundException, android.media.MediaTranscodingException.ServiceNotAvailableException;
- field public static final int PRIORITY_REALTIME = 1; // 0x1
- field public static final int TRANSCODING_TYPE_VIDEO = 1; // 0x1
- }
-
- @java.lang.FunctionalInterface public static interface MediaTranscodeManager.OnTranscodingFinishedListener {
- method public void onTranscodingFinished(@NonNull android.media.MediaTranscodeManager.TranscodingJob);
- }
-
- public static final class MediaTranscodeManager.TranscodingJob {
- method public void cancel();
- method public int getJobId();
- method @IntRange(from=0, to=100) public int getProgress();
- method public int getResult();
- method public int getStatus();
- method public void setOnProgressUpdateListener(@NonNull java.util.concurrent.Executor, @Nullable android.media.MediaTranscodeManager.TranscodingJob.OnProgressUpdateListener);
- method public void setOnProgressUpdateListener(int, @NonNull java.util.concurrent.Executor, @Nullable android.media.MediaTranscodeManager.TranscodingJob.OnProgressUpdateListener);
- field public static final int RESULT_CANCELED = 4; // 0x4
- field public static final int RESULT_ERROR = 3; // 0x3
- field public static final int RESULT_NONE = 1; // 0x1
- field public static final int RESULT_SUCCESS = 2; // 0x2
- field public static final int STATUS_FINISHED = 3; // 0x3
- field public static final int STATUS_PAUSED = 4; // 0x4
- field public static final int STATUS_PENDING = 1; // 0x1
- field public static final int STATUS_RUNNING = 2; // 0x2
- }
-
- @java.lang.FunctionalInterface public static interface MediaTranscodeManager.TranscodingJob.OnProgressUpdateListener {
- method public void onProgressUpdate(@NonNull android.media.MediaTranscodeManager.TranscodingJob, @IntRange(from=0, to=100) int);
- }
-
- public static final class MediaTranscodeManager.TranscodingRequest {
- method public int getClientPid();
- method public int getClientUid();
- method @NonNull public android.net.Uri getDestinationUri();
- method public int getPriority();
- method @NonNull public android.net.Uri getSourceUri();
- method public int getType();
- method @Nullable public android.media.MediaFormat getVideoTrackFormat();
- }
-
- public static final class MediaTranscodeManager.TranscodingRequest.Builder {
- ctor public MediaTranscodeManager.TranscodingRequest.Builder();
- method @NonNull public android.media.MediaTranscodeManager.TranscodingRequest build();
- method @NonNull public android.media.MediaTranscodeManager.TranscodingRequest.Builder setClientPid(int);
- method @NonNull public android.media.MediaTranscodeManager.TranscodingRequest.Builder setClientUid(int);
- method @NonNull public android.media.MediaTranscodeManager.TranscodingRequest.Builder setDestinationUri(@NonNull android.net.Uri);
- method @NonNull public android.media.MediaTranscodeManager.TranscodingRequest.Builder setPriority(int);
- method @NonNull public android.media.MediaTranscodeManager.TranscodingRequest.Builder setSourceUri(@NonNull android.net.Uri);
- method @NonNull public android.media.MediaTranscodeManager.TranscodingRequest.Builder setType(int);
- method @NonNull public android.media.MediaTranscodeManager.TranscodingRequest.Builder setVideoTrackFormat(@NonNull android.media.MediaFormat);
- }
-
- public static class MediaTranscodeManager.TranscodingRequest.MediaFormatResolver {
- ctor public MediaTranscodeManager.TranscodingRequest.MediaFormatResolver();
- method @Nullable public android.media.MediaFormat resolveVideoFormat();
- method @NonNull public android.media.MediaTranscodeManager.TranscodingRequest.MediaFormatResolver setSourceVideoFormatHint(@NonNull android.media.MediaFormat);
- method public boolean shouldTranscode();
- field public static final String CAPS_SUPPORTS_HEVC = "support-hevc";
- }
-
public final class PlaybackParams implements android.os.Parcelable {
method public int getAudioStretchMode();
method public android.media.PlaybackParams setAudioStretchMode(int);
@@ -2018,141 +1031,8 @@ package android.media.audiofx {
package android.media.audiopolicy {
- public class AudioMix {
- method public int getMixState();
- field public static final int MIX_STATE_DISABLED = -1; // 0xffffffff
- field public static final int MIX_STATE_IDLE = 0; // 0x0
- field public static final int MIX_STATE_MIXING = 1; // 0x1
- field public static final int ROUTE_FLAG_LOOP_BACK = 2; // 0x2
- field public static final int ROUTE_FLAG_RENDER = 1; // 0x1
- }
-
- public static class AudioMix.Builder {
- ctor public AudioMix.Builder(android.media.audiopolicy.AudioMixingRule) throws java.lang.IllegalArgumentException;
- method public android.media.audiopolicy.AudioMix build() throws java.lang.IllegalArgumentException;
- method public android.media.audiopolicy.AudioMix.Builder setDevice(@NonNull android.media.AudioDeviceInfo) throws java.lang.IllegalArgumentException;
- method public android.media.audiopolicy.AudioMix.Builder setFormat(android.media.AudioFormat) throws java.lang.IllegalArgumentException;
- method public android.media.audiopolicy.AudioMix.Builder setRouteFlags(int) throws java.lang.IllegalArgumentException;
- }
-
- public class AudioMixingRule {
- field public static final int RULE_MATCH_ATTRIBUTE_CAPTURE_PRESET = 2; // 0x2
- field public static final int RULE_MATCH_ATTRIBUTE_USAGE = 1; // 0x1
- field public static final int RULE_MATCH_UID = 4; // 0x4
- field public static final int RULE_MATCH_USERID = 8; // 0x8
- }
-
- public static class AudioMixingRule.Builder {
- ctor public AudioMixingRule.Builder();
- method public android.media.audiopolicy.AudioMixingRule.Builder addMixRule(int, Object) throws java.lang.IllegalArgumentException;
- method public android.media.audiopolicy.AudioMixingRule.Builder addRule(android.media.AudioAttributes, int) throws java.lang.IllegalArgumentException;
- method @NonNull public android.media.audiopolicy.AudioMixingRule.Builder allowPrivilegedPlaybackCapture(boolean);
- method public android.media.audiopolicy.AudioMixingRule build();
- method public android.media.audiopolicy.AudioMixingRule.Builder excludeMixRule(int, Object) throws java.lang.IllegalArgumentException;
- method public android.media.audiopolicy.AudioMixingRule.Builder excludeRule(android.media.AudioAttributes, int) throws java.lang.IllegalArgumentException;
- }
-
- public class AudioPolicy {
- method public int attachMixes(@NonNull java.util.List<android.media.audiopolicy.AudioMix>);
- method public android.media.AudioRecord createAudioRecordSink(android.media.audiopolicy.AudioMix) throws java.lang.IllegalArgumentException;
- method public android.media.AudioTrack createAudioTrackSource(android.media.audiopolicy.AudioMix) throws java.lang.IllegalArgumentException;
- method public int detachMixes(@NonNull java.util.List<android.media.audiopolicy.AudioMix>);
- method public int getFocusDuckingBehavior();
- method public int getStatus();
- method public boolean removeUidDeviceAffinity(int);
- method public boolean removeUserIdDeviceAffinity(int);
- method public int setFocusDuckingBehavior(int) throws java.lang.IllegalArgumentException, java.lang.IllegalStateException;
- method public void setRegistration(String);
- method public boolean setUidDeviceAffinity(int, @NonNull java.util.List<android.media.AudioDeviceInfo>);
- method public boolean setUserIdDeviceAffinity(int, @NonNull java.util.List<android.media.AudioDeviceInfo>);
- method public String toLogFriendlyString();
- field public static final int FOCUS_POLICY_DUCKING_DEFAULT = 0; // 0x0
- field public static final int FOCUS_POLICY_DUCKING_IN_APP = 0; // 0x0
- field public static final int FOCUS_POLICY_DUCKING_IN_POLICY = 1; // 0x1
- field public static final int POLICY_STATUS_REGISTERED = 2; // 0x2
- field public static final int POLICY_STATUS_UNREGISTERED = 1; // 0x1
- }
-
- public abstract static class AudioPolicy.AudioPolicyFocusListener {
- ctor public AudioPolicy.AudioPolicyFocusListener();
- method public void onAudioFocusAbandon(android.media.AudioFocusInfo);
- method public void onAudioFocusGrant(android.media.AudioFocusInfo, int);
- method public void onAudioFocusLoss(android.media.AudioFocusInfo, boolean);
- method public void onAudioFocusRequest(android.media.AudioFocusInfo, int);
- }
-
- public abstract static class AudioPolicy.AudioPolicyStatusListener {
- ctor public AudioPolicy.AudioPolicyStatusListener();
- method public void onMixStateUpdate(android.media.audiopolicy.AudioMix);
- method public void onStatusChange();
- }
-
- public abstract static class AudioPolicy.AudioPolicyVolumeCallback {
- ctor public AudioPolicy.AudioPolicyVolumeCallback();
- method public void onVolumeAdjustment(int);
- }
-
public static class AudioPolicy.Builder {
- ctor public AudioPolicy.Builder(android.content.Context);
- method @NonNull public android.media.audiopolicy.AudioPolicy.Builder addMix(@NonNull android.media.audiopolicy.AudioMix) throws java.lang.IllegalArgumentException;
- method @NonNull public android.media.audiopolicy.AudioPolicy build();
- method public void setAudioPolicyFocusListener(android.media.audiopolicy.AudioPolicy.AudioPolicyFocusListener);
- method public void setAudioPolicyStatusListener(android.media.audiopolicy.AudioPolicy.AudioPolicyStatusListener);
- method @NonNull public android.media.audiopolicy.AudioPolicy.Builder setAudioPolicyVolumeCallback(@NonNull android.media.audiopolicy.AudioPolicy.AudioPolicyVolumeCallback);
- method @NonNull public android.media.audiopolicy.AudioPolicy.Builder setIsAudioFocusPolicy(boolean);
method @NonNull public android.media.audiopolicy.AudioPolicy.Builder setIsTestFocusPolicy(boolean);
- method @NonNull public android.media.audiopolicy.AudioPolicy.Builder setLooper(@NonNull android.os.Looper) throws java.lang.IllegalArgumentException;
- }
-
-}
-
-package android.media.musicrecognition {
-
- public class MusicRecognitionManager {
- field public static final int RECOGNITION_FAILED_AUDIO_UNAVAILABLE = 7; // 0x7
- field public static final int RECOGNITION_FAILED_NOT_FOUND = 1; // 0x1
- field public static final int RECOGNITION_FAILED_NO_CONNECTIVITY = 2; // 0x2
- field public static final int RECOGNITION_FAILED_SERVICE_KILLED = 5; // 0x5
- field public static final int RECOGNITION_FAILED_SERVICE_UNAVAILABLE = 3; // 0x3
- field public static final int RECOGNITION_FAILED_TIMEOUT = 6; // 0x6
- field public static final int RECOGNITION_FAILED_UNKNOWN = -1; // 0xffffffff
- }
-
- public static interface MusicRecognitionManager.RecognitionCallback {
- method public void onAudioStreamClosed();
- method public void onRecognitionFailed(@NonNull android.media.musicrecognition.RecognitionRequest, int);
- method public void onRecognitionSucceeded(@NonNull android.media.musicrecognition.RecognitionRequest, @NonNull android.media.MediaMetadata, @Nullable android.os.Bundle);
- }
-
- public abstract class MusicRecognitionService extends android.app.Service {
- ctor public MusicRecognitionService();
- method public abstract void onRecognize(@NonNull android.os.ParcelFileDescriptor, @NonNull android.media.AudioFormat, @NonNull android.media.musicrecognition.MusicRecognitionService.Callback);
- }
-
- public static interface MusicRecognitionService.Callback {
- method public void onRecognitionFailed(int);
- method public void onRecognitionSucceeded(@NonNull android.media.MediaMetadata, @Nullable android.os.Bundle);
- }
-
- public final class RecognitionRequest implements android.os.Parcelable {
- method public int describeContents();
- method @NonNull public android.media.AudioAttributes getAudioAttributes();
- method @NonNull public android.media.AudioFormat getAudioFormat();
- method public int getCaptureSession();
- method public int getIgnoreBeginningFrames();
- method public int getMaxAudioLengthSeconds();
- method public void writeToParcel(@NonNull android.os.Parcel, int);
- field @NonNull public static final android.os.Parcelable.Creator<android.media.musicrecognition.RecognitionRequest> CREATOR;
- }
-
- public static final class RecognitionRequest.Builder {
- ctor public RecognitionRequest.Builder();
- method @NonNull public android.media.musicrecognition.RecognitionRequest build();
- method @NonNull public android.media.musicrecognition.RecognitionRequest.Builder setAudioAttributes(@NonNull android.media.AudioAttributes);
- method @NonNull public android.media.musicrecognition.RecognitionRequest.Builder setAudioFormat(@NonNull android.media.AudioFormat);
- method @NonNull public android.media.musicrecognition.RecognitionRequest.Builder setCaptureSession(int);
- method @NonNull public android.media.musicrecognition.RecognitionRequest.Builder setIgnoreBeginningFrames(int);
- method @NonNull public android.media.musicrecognition.RecognitionRequest.Builder setMaxAudioLengthSeconds(int);
}
}
@@ -2171,242 +1051,33 @@ package android.media.tv.tuner {
public final class TunerVersionChecker {
method public static int getMajorVersion(int);
method public static int getMinorVersion(int);
- method public static int getTunerVersion();
method public static boolean isHigherOrEqualVersionTo(int);
method public static boolean supportTunerVersion(int);
- field public static final int TUNER_VERSION_1_0 = 65536; // 0x10000
- field public static final int TUNER_VERSION_1_1 = 65537; // 0x10001
- field public static final int TUNER_VERSION_UNKNOWN = 0; // 0x0
- }
-
-}
-
-package android.metrics {
-
- public class LogMaker {
- ctor public LogMaker(int);
- ctor public LogMaker(Object[]);
- method public android.metrics.LogMaker addTaggedData(int, Object);
- method public android.metrics.LogMaker clearCategory();
- method public android.metrics.LogMaker clearPackageName();
- method public android.metrics.LogMaker clearSubtype();
- method public android.metrics.LogMaker clearTaggedData(int);
- method public android.metrics.LogMaker clearType();
- method public void deserialize(Object[]);
- method public int getCategory();
- method public long getCounterBucket();
- method public String getCounterName();
- method public int getCounterValue();
- method public String getPackageName();
- method public int getProcessId();
- method public int getSubtype();
- method public Object getTaggedData(int);
- method public long getTimestamp();
- method public int getType();
- method public int getUid();
- method public boolean isLongCounterBucket();
- method public boolean isSubsetOf(android.metrics.LogMaker);
- method public boolean isValidValue(Object);
- method public Object[] serialize();
- method public android.metrics.LogMaker setCategory(int);
- method public android.metrics.LogMaker setPackageName(String);
- method public android.metrics.LogMaker setSubtype(int);
- method public android.metrics.LogMaker setType(int);
- }
-
- public class MetricsReader {
- ctor public MetricsReader();
- method public void checkpoint();
- method public boolean hasNext();
- method public android.metrics.LogMaker next();
- method public void read(long);
- method public void reset();
}
}
package android.net {
- public class CaptivePortal implements android.os.Parcelable {
- method public void logEvent(int, @NonNull String);
- method @RequiresPermission(android.Manifest.permission.NETWORK_STACK) public void reevaluateNetwork();
- method public void useNetwork();
- field public static final int APP_REQUEST_REEVALUATION_REQUIRED = 100; // 0x64
- field public static final int APP_RETURN_DISMISSED = 0; // 0x0
- field public static final int APP_RETURN_UNWANTED = 1; // 0x1
- field public static final int APP_RETURN_WANTED_AS_IS = 2; // 0x2
- }
-
- public final class CaptivePortalData implements android.os.Parcelable {
- method public int describeContents();
- method public long getByteLimit();
- method public long getExpiryTimeMillis();
- method public long getRefreshTimeMillis();
- method @Nullable public android.net.Uri getUserPortalUrl();
- method @Nullable public android.net.Uri getVenueInfoUrl();
- method public boolean isCaptive();
- method public boolean isSessionExtendable();
- method public void writeToParcel(@NonNull android.os.Parcel, int);
- field @NonNull public static final android.os.Parcelable.Creator<android.net.CaptivePortalData> CREATOR;
- }
-
- public static class CaptivePortalData.Builder {
- ctor public CaptivePortalData.Builder();
- ctor public CaptivePortalData.Builder(@Nullable android.net.CaptivePortalData);
- method @NonNull public android.net.CaptivePortalData build();
- method @NonNull public android.net.CaptivePortalData.Builder setBytesRemaining(long);
- method @NonNull public android.net.CaptivePortalData.Builder setCaptive(boolean);
- method @NonNull public android.net.CaptivePortalData.Builder setExpiryTime(long);
- method @NonNull public android.net.CaptivePortalData.Builder setRefreshTime(long);
- method @NonNull public android.net.CaptivePortalData.Builder setSessionExtendable(boolean);
- method @NonNull public android.net.CaptivePortalData.Builder setUserPortalUrl(@Nullable android.net.Uri);
- method @NonNull public android.net.CaptivePortalData.Builder setVenueInfoUrl(@Nullable android.net.Uri);
- }
-
public class ConnectivityManager {
method @RequiresPermission(anyOf={"android.permission.MANAGE_TEST_NETWORKS", android.Manifest.permission.NETWORK_STACK}) public void simulateDataStall(int, long, @NonNull android.net.Network, @NonNull android.os.PersistableBundle);
- method @RequiresPermission(android.net.NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK) public void startCaptivePortalApp(@NonNull android.net.Network, @NonNull android.os.Bundle);
- field public static final String EXTRA_CAPTIVE_PORTAL_PROBE_SPEC = "android.net.extra.CAPTIVE_PORTAL_PROBE_SPEC";
- field public static final String EXTRA_CAPTIVE_PORTAL_USER_AGENT = "android.net.extra.CAPTIVE_PORTAL_USER_AGENT";
}
public class EthernetManager {
- method @NonNull @RequiresPermission(anyOf={android.Manifest.permission.NETWORK_STACK, android.net.NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK}) public android.net.EthernetManager.TetheredInterfaceRequest requestTetheredInterface(@NonNull java.util.concurrent.Executor, @NonNull android.net.EthernetManager.TetheredInterfaceCallback);
method public void setIncludeTestInterfaces(boolean);
}
- public static interface EthernetManager.TetheredInterfaceCallback {
- method public void onAvailable(@NonNull String);
- method public void onUnavailable();
- }
-
- public static class EthernetManager.TetheredInterfaceRequest {
- method public void release();
- }
-
- public final class IpPrefix implements android.os.Parcelable {
- ctor public IpPrefix(@NonNull java.net.InetAddress, @IntRange(from=0, to=128) int);
- ctor public IpPrefix(@NonNull String);
- }
-
public final class IpSecManager {
field public static final int INVALID_SECURITY_PARAMETER_INDEX = 0; // 0x0
}
- public class LinkAddress implements android.os.Parcelable {
- ctor public LinkAddress(@NonNull java.net.InetAddress, @IntRange(from=0, to=128) int, int, int);
- ctor public LinkAddress(@NonNull java.net.InetAddress, @IntRange(from=0, to=128) int, int, int, long, long);
- ctor public LinkAddress(@NonNull java.net.InetAddress, @IntRange(from=0, to=128) int);
- ctor public LinkAddress(@NonNull String);
- ctor public LinkAddress(@NonNull String, int, int);
- method public long getDeprecationTime();
- method public long getExpirationTime();
- method public boolean isGlobalPreferred();
- method public boolean isIpv4();
- method public boolean isIpv6();
- method public boolean isSameAddressAs(@Nullable android.net.LinkAddress);
- }
-
- public final class LinkProperties implements android.os.Parcelable {
- ctor public LinkProperties(@Nullable android.net.LinkProperties);
- ctor public LinkProperties(@Nullable android.net.LinkProperties, boolean);
- method public boolean addDnsServer(@NonNull java.net.InetAddress);
- method public boolean addLinkAddress(@NonNull android.net.LinkAddress);
- method @Nullable public android.net.Uri getCaptivePortalApiUrl();
- method @Nullable public android.net.CaptivePortalData getCaptivePortalData();
- method @NonNull public java.util.List<java.net.InetAddress> getPcscfServers();
- method @Nullable public String getTcpBufferSizes();
- method @NonNull public java.util.List<java.net.InetAddress> getValidatedPrivateDnsServers();
- method public boolean hasGlobalIpv6Address();
- method public boolean hasIpv4Address();
- method public boolean hasIpv6DefaultRoute();
- method public boolean isIpv4Provisioned();
- method public boolean isIpv6Provisioned();
- method public boolean isProvisioned();
- method public boolean isReachable(@NonNull java.net.InetAddress);
- method public boolean removeDnsServer(@NonNull java.net.InetAddress);
- method public boolean removeLinkAddress(@NonNull android.net.LinkAddress);
- method public boolean removeRoute(@NonNull android.net.RouteInfo);
- method public void setCaptivePortalApiUrl(@Nullable android.net.Uri);
- method public void setCaptivePortalData(@Nullable android.net.CaptivePortalData);
- method public void setPcscfServers(@NonNull java.util.Collection<java.net.InetAddress>);
- method public void setPrivateDnsServerName(@Nullable String);
- method public void setTcpBufferSizes(@Nullable String);
- method public void setUsePrivateDns(boolean);
- method public void setValidatedPrivateDnsServers(@NonNull java.util.Collection<java.net.InetAddress>);
- }
-
- public class Network implements android.os.Parcelable {
- ctor public Network(@NonNull android.net.Network);
- method public int getNetId();
- method @NonNull public android.net.Network getPrivateDnsBypassingCopy();
- }
-
public final class NetworkCapabilities implements android.os.Parcelable {
- method @NonNull public int[] getAdministratorUids();
method public int[] getCapabilities();
- method @Nullable public String getSsid();
- method @NonNull public int[] getTransportTypes();
- method public boolean satisfiedByNetworkCapabilities(@Nullable android.net.NetworkCapabilities);
field public static final int TRANSPORT_TEST = 7; // 0x7
}
- public static final class NetworkCapabilities.Builder {
- ctor public NetworkCapabilities.Builder();
- ctor public NetworkCapabilities.Builder(@NonNull android.net.NetworkCapabilities);
- method @NonNull public android.net.NetworkCapabilities.Builder addCapability(int);
- method @NonNull public android.net.NetworkCapabilities.Builder addTransportType(int);
- method @NonNull public android.net.NetworkCapabilities build();
- method @NonNull public android.net.NetworkCapabilities.Builder removeCapability(int);
- method @NonNull public android.net.NetworkCapabilities.Builder removeTransportType(int);
- method @NonNull @RequiresPermission(android.Manifest.permission.NETWORK_FACTORY) public android.net.NetworkCapabilities.Builder setAdministratorUids(@NonNull int[]);
- method @NonNull public android.net.NetworkCapabilities.Builder setLinkDownstreamBandwidthKbps(int);
- method @NonNull public android.net.NetworkCapabilities.Builder setLinkUpstreamBandwidthKbps(int);
- method @NonNull public android.net.NetworkCapabilities.Builder setNetworkSpecifier(@Nullable android.net.NetworkSpecifier);
- method @NonNull @RequiresPermission(android.Manifest.permission.NETWORK_FACTORY) public android.net.NetworkCapabilities.Builder setOwnerUid(int);
- method @NonNull @RequiresPermission(android.Manifest.permission.NETWORK_FACTORY) public android.net.NetworkCapabilities.Builder setRequestorPackageName(@Nullable String);
- method @NonNull @RequiresPermission(android.Manifest.permission.NETWORK_FACTORY) public android.net.NetworkCapabilities.Builder setRequestorUid(int);
- method @NonNull @RequiresPermission(android.Manifest.permission.NETWORK_SIGNAL_STRENGTH_WAKEUP) public android.net.NetworkCapabilities.Builder setSignalStrength(int);
- method @NonNull @RequiresPermission(android.Manifest.permission.NETWORK_FACTORY) public android.net.NetworkCapabilities.Builder setSsid(@Nullable String);
- method @NonNull public android.net.NetworkCapabilities.Builder setTransportInfo(@Nullable android.net.TransportInfo);
- }
-
public class NetworkStack {
- method @Nullable public static android.os.IBinder getService();
method public static void setServiceForTest(@Nullable android.os.IBinder);
- field public static final String PERMISSION_MAINLINE_NETWORK_STACK = "android.permission.MAINLINE_NETWORK_STACK";
- }
-
- public final class RouteInfo implements android.os.Parcelable {
- ctor public RouteInfo(@Nullable android.net.IpPrefix, @Nullable java.net.InetAddress, @Nullable String, int);
- method public int getType();
- field public static final int RTN_THROW = 9; // 0x9
- field public static final int RTN_UNICAST = 1; // 0x1
- field public static final int RTN_UNREACHABLE = 7; // 0x7
- }
-
- public final class StaticIpConfiguration implements android.os.Parcelable {
- ctor public StaticIpConfiguration();
- ctor public StaticIpConfiguration(@Nullable android.net.StaticIpConfiguration);
- method public void addDnsServer(@NonNull java.net.InetAddress);
- method public void clear();
- method public int describeContents();
- method @NonNull public java.util.List<java.net.InetAddress> getDnsServers();
- method @Nullable public String getDomains();
- method @Nullable public java.net.InetAddress getGateway();
- method @Nullable public android.net.LinkAddress getIpAddress();
- method @NonNull public java.util.List<android.net.RouteInfo> getRoutes(@Nullable String);
- method public void writeToParcel(android.os.Parcel, int);
- field @NonNull public static final android.os.Parcelable.Creator<android.net.StaticIpConfiguration> CREATOR;
- }
-
- public static final class StaticIpConfiguration.Builder {
- ctor public StaticIpConfiguration.Builder();
- method @NonNull public android.net.StaticIpConfiguration build();
- method @NonNull public android.net.StaticIpConfiguration.Builder setDnsServers(@NonNull Iterable<java.net.InetAddress>);
- method @NonNull public android.net.StaticIpConfiguration.Builder setDomains(@Nullable String);
- method @NonNull public android.net.StaticIpConfiguration.Builder setGateway(@Nullable java.net.InetAddress);
- method @NonNull public android.net.StaticIpConfiguration.Builder setIpAddress(@Nullable android.net.LinkAddress);
}
public final class TestNetworkInterface implements android.os.Parcelable {
@@ -2434,228 +1105,8 @@ package android.net {
}
-package android.net.apf {
-
- public final class ApfCapabilities implements android.os.Parcelable {
- ctor public ApfCapabilities(int, int, int);
- method public int describeContents();
- method public static boolean getApfDrop8023Frames();
- method @NonNull public static int[] getApfEtherTypeBlackList();
- method public boolean hasDataAccess();
- method public void writeToParcel(android.os.Parcel, int);
- field public static final android.os.Parcelable.Creator<android.net.apf.ApfCapabilities> CREATOR;
- field public final int apfPacketFormat;
- field public final int apfVersionSupported;
- field public final int maximumApfProgramSize;
- }
-
-}
-
-package android.net.metrics {
-
- public final class ApfProgramEvent implements android.net.metrics.IpConnectivityLog.Event {
- }
-
- public static final class ApfProgramEvent.Builder {
- ctor public ApfProgramEvent.Builder();
- method @NonNull public android.net.metrics.ApfProgramEvent build();
- method @NonNull public android.net.metrics.ApfProgramEvent.Builder setActualLifetime(long);
- method @NonNull public android.net.metrics.ApfProgramEvent.Builder setCurrentRas(int);
- method @NonNull public android.net.metrics.ApfProgramEvent.Builder setFilteredRas(int);
- method @NonNull public android.net.metrics.ApfProgramEvent.Builder setFlags(boolean, boolean);
- method @NonNull public android.net.metrics.ApfProgramEvent.Builder setLifetime(long);
- method @NonNull public android.net.metrics.ApfProgramEvent.Builder setProgramLength(int);
- }
-
- public final class ApfStats implements android.net.metrics.IpConnectivityLog.Event {
- }
-
- public static final class ApfStats.Builder {
- ctor public ApfStats.Builder();
- method @NonNull public android.net.metrics.ApfStats build();
- method @NonNull public android.net.metrics.ApfStats.Builder setDroppedRas(int);
- method @NonNull public android.net.metrics.ApfStats.Builder setDurationMs(long);
- method @NonNull public android.net.metrics.ApfStats.Builder setMatchingRas(int);
- method @NonNull public android.net.metrics.ApfStats.Builder setMaxProgramSize(int);
- method @NonNull public android.net.metrics.ApfStats.Builder setParseErrors(int);
- method @NonNull public android.net.metrics.ApfStats.Builder setProgramUpdates(int);
- method @NonNull public android.net.metrics.ApfStats.Builder setProgramUpdatesAll(int);
- method @NonNull public android.net.metrics.ApfStats.Builder setProgramUpdatesAllowingMulticast(int);
- method @NonNull public android.net.metrics.ApfStats.Builder setReceivedRas(int);
- method @NonNull public android.net.metrics.ApfStats.Builder setZeroLifetimeRas(int);
- }
-
- public final class DhcpClientEvent implements android.net.metrics.IpConnectivityLog.Event {
- }
-
- public static final class DhcpClientEvent.Builder {
- ctor public DhcpClientEvent.Builder();
- method @NonNull public android.net.metrics.DhcpClientEvent build();
- method @NonNull public android.net.metrics.DhcpClientEvent.Builder setDurationMs(int);
- method @NonNull public android.net.metrics.DhcpClientEvent.Builder setMsg(String);
- }
-
- public final class DhcpErrorEvent implements android.net.metrics.IpConnectivityLog.Event {
- ctor public DhcpErrorEvent(int);
- method public static int errorCodeWithOption(int, int);
- field public static final int BOOTP_TOO_SHORT = 67174400; // 0x4010000
- field public static final int BUFFER_UNDERFLOW = 83951616; // 0x5010000
- field public static final int DHCP_BAD_MAGIC_COOKIE = 67239936; // 0x4020000
- field public static final int DHCP_ERROR = 4; // 0x4
- field public static final int DHCP_INVALID_OPTION_LENGTH = 67305472; // 0x4030000
- field public static final int DHCP_NO_COOKIE = 67502080; // 0x4060000
- field public static final int DHCP_NO_MSG_TYPE = 67371008; // 0x4040000
- field public static final int DHCP_UNKNOWN_MSG_TYPE = 67436544; // 0x4050000
- field public static final int L2_ERROR = 1; // 0x1
- field public static final int L2_TOO_SHORT = 16842752; // 0x1010000
- field public static final int L2_WRONG_ETH_TYPE = 16908288; // 0x1020000
- field public static final int L3_ERROR = 2; // 0x2
- field public static final int L3_INVALID_IP = 33751040; // 0x2030000
- field public static final int L3_NOT_IPV4 = 33685504; // 0x2020000
- field public static final int L3_TOO_SHORT = 33619968; // 0x2010000
- field public static final int L4_ERROR = 3; // 0x3
- field public static final int L4_NOT_UDP = 50397184; // 0x3010000
- field public static final int L4_WRONG_PORT = 50462720; // 0x3020000
- field public static final int MISC_ERROR = 5; // 0x5
- field public static final int PARSING_ERROR = 84082688; // 0x5030000
- field public static final int RECEIVE_ERROR = 84017152; // 0x5020000
- }
-
- public class IpConnectivityLog {
- ctor public IpConnectivityLog();
- method public boolean log(long, @NonNull android.net.metrics.IpConnectivityLog.Event);
- method public boolean log(@NonNull String, @NonNull android.net.metrics.IpConnectivityLog.Event);
- method public boolean log(@NonNull android.net.Network, @NonNull int[], @NonNull android.net.metrics.IpConnectivityLog.Event);
- method public boolean log(int, @NonNull int[], @NonNull android.net.metrics.IpConnectivityLog.Event);
- method public boolean log(@NonNull android.net.metrics.IpConnectivityLog.Event);
- }
-
- public static interface IpConnectivityLog.Event extends android.os.Parcelable {
- }
-
- public final class IpManagerEvent implements android.net.metrics.IpConnectivityLog.Event {
- ctor public IpManagerEvent(int, long);
- field public static final int COMPLETE_LIFECYCLE = 3; // 0x3
- field public static final int ERROR_INTERFACE_NOT_FOUND = 8; // 0x8
- field public static final int ERROR_INVALID_PROVISIONING = 7; // 0x7
- field public static final int ERROR_STARTING_IPREACHABILITYMONITOR = 6; // 0x6
- field public static final int ERROR_STARTING_IPV4 = 4; // 0x4
- field public static final int ERROR_STARTING_IPV6 = 5; // 0x5
- field public static final int PROVISIONING_FAIL = 2; // 0x2
- field public static final int PROVISIONING_OK = 1; // 0x1
- }
-
- public final class IpReachabilityEvent implements android.net.metrics.IpConnectivityLog.Event {
- ctor public IpReachabilityEvent(int);
- field public static final int NUD_FAILED = 512; // 0x200
- field public static final int NUD_FAILED_ORGANIC = 1024; // 0x400
- field public static final int PROBE = 256; // 0x100
- field public static final int PROVISIONING_LOST = 768; // 0x300
- field public static final int PROVISIONING_LOST_ORGANIC = 1280; // 0x500
- }
-
- public final class NetworkEvent implements android.net.metrics.IpConnectivityLog.Event {
- ctor public NetworkEvent(int, long);
- ctor public NetworkEvent(int);
- field public static final int NETWORK_CAPTIVE_PORTAL_FOUND = 4; // 0x4
- field public static final int NETWORK_CONNECTED = 1; // 0x1
- field public static final int NETWORK_CONSECUTIVE_DNS_TIMEOUT_FOUND = 12; // 0xc
- field public static final int NETWORK_DISCONNECTED = 7; // 0x7
- field public static final int NETWORK_FIRST_VALIDATION_PORTAL_FOUND = 10; // 0xa
- field public static final int NETWORK_FIRST_VALIDATION_SUCCESS = 8; // 0x8
- field public static final int NETWORK_LINGER = 5; // 0x5
- field public static final int NETWORK_PARTIAL_CONNECTIVITY = 13; // 0xd
- field public static final int NETWORK_REVALIDATION_PORTAL_FOUND = 11; // 0xb
- field public static final int NETWORK_REVALIDATION_SUCCESS = 9; // 0x9
- field public static final int NETWORK_UNLINGER = 6; // 0x6
- field public static final int NETWORK_VALIDATED = 2; // 0x2
- field public static final int NETWORK_VALIDATION_FAILED = 3; // 0x3
- }
-
- public final class RaEvent implements android.net.metrics.IpConnectivityLog.Event {
- }
-
- public static final class RaEvent.Builder {
- ctor public RaEvent.Builder();
- method @NonNull public android.net.metrics.RaEvent build();
- method @NonNull public android.net.metrics.RaEvent.Builder updateDnsslLifetime(long);
- method @NonNull public android.net.metrics.RaEvent.Builder updatePrefixPreferredLifetime(long);
- method @NonNull public android.net.metrics.RaEvent.Builder updatePrefixValidLifetime(long);
- method @NonNull public android.net.metrics.RaEvent.Builder updateRdnssLifetime(long);
- method @NonNull public android.net.metrics.RaEvent.Builder updateRouteInfoLifetime(long);
- method @NonNull public android.net.metrics.RaEvent.Builder updateRouterLifetime(long);
- }
-
- public final class ValidationProbeEvent implements android.net.metrics.IpConnectivityLog.Event {
- method @NonNull public static String getProbeName(int);
- field public static final int DNS_FAILURE = 0; // 0x0
- field public static final int DNS_SUCCESS = 1; // 0x1
- field public static final int PROBE_DNS = 0; // 0x0
- field public static final int PROBE_FALLBACK = 4; // 0x4
- field public static final int PROBE_HTTP = 1; // 0x1
- field public static final int PROBE_HTTPS = 2; // 0x2
- field public static final int PROBE_PAC = 3; // 0x3
- field public static final int PROBE_PRIVDNS = 5; // 0x5
- }
-
- public static final class ValidationProbeEvent.Builder {
- ctor public ValidationProbeEvent.Builder();
- method @NonNull public android.net.metrics.ValidationProbeEvent build();
- method @NonNull public android.net.metrics.ValidationProbeEvent.Builder setDurationMs(long);
- method @NonNull public android.net.metrics.ValidationProbeEvent.Builder setProbeType(int, boolean);
- method @NonNull public android.net.metrics.ValidationProbeEvent.Builder setReturnCode(int);
- }
-
-}
-
-package android.net.util {
-
- public final class SocketUtils {
- method public static void bindSocketToInterface(@NonNull java.io.FileDescriptor, @NonNull String) throws android.system.ErrnoException;
- method public static void closeSocket(@Nullable java.io.FileDescriptor) throws java.io.IOException;
- method @NonNull public static java.net.SocketAddress makeNetlinkSocketAddress(int, int);
- method @NonNull public static java.net.SocketAddress makePacketSocketAddress(int, int);
- method @Deprecated @NonNull public static java.net.SocketAddress makePacketSocketAddress(int, @NonNull byte[]);
- method @NonNull public static java.net.SocketAddress makePacketSocketAddress(int, int, @NonNull byte[]);
- }
-
-}
-
package android.os {
- public class BatteryManager {
- method @RequiresPermission(android.Manifest.permission.POWER_SAVER) public boolean setChargingStateUpdateDelayMillis(int);
- }
-
- public final class BugreportManager {
- method @RequiresPermission(android.Manifest.permission.DUMP) public void cancelBugreport();
- method @RequiresPermission(android.Manifest.permission.DUMP) public void requestBugreport(@NonNull android.os.BugreportParams, @Nullable CharSequence, @Nullable CharSequence);
- method @RequiresPermission(android.Manifest.permission.DUMP) public void startBugreport(@NonNull android.os.ParcelFileDescriptor, @Nullable android.os.ParcelFileDescriptor, @NonNull android.os.BugreportParams, @NonNull java.util.concurrent.Executor, @NonNull android.os.BugreportManager.BugreportCallback);
- }
-
- public abstract static class BugreportManager.BugreportCallback {
- ctor public BugreportManager.BugreportCallback();
- method public void onError(int);
- method public void onFinished();
- method public void onProgress(@FloatRange(from=0.0f, to=100.0f) float);
- field public static final int BUGREPORT_ERROR_ANOTHER_REPORT_IN_PROGRESS = 5; // 0x5
- field public static final int BUGREPORT_ERROR_INVALID_INPUT = 1; // 0x1
- field public static final int BUGREPORT_ERROR_RUNTIME = 2; // 0x2
- field public static final int BUGREPORT_ERROR_USER_CONSENT_TIMED_OUT = 4; // 0x4
- field public static final int BUGREPORT_ERROR_USER_DENIED_CONSENT = 3; // 0x3
- }
-
- public final class BugreportParams {
- ctor public BugreportParams(int);
- method public int getMode();
- field public static final int BUGREPORT_MODE_FULL = 0; // 0x0
- field public static final int BUGREPORT_MODE_INTERACTIVE = 1; // 0x1
- field public static final int BUGREPORT_MODE_REMOTE = 2; // 0x2
- field public static final int BUGREPORT_MODE_TELEPHONY = 4; // 0x4
- field public static final int BUGREPORT_MODE_WEAR = 3; // 0x3
- field public static final int BUGREPORT_MODE_WIFI = 5; // 0x5
- }
-
public class Build {
method public static boolean is64BitAbi(String);
field public static final boolean IS_EMULATOR;
@@ -2668,18 +1119,12 @@ package android.os {
}
public class DeviceIdleManager {
- method @RequiresPermission(android.Manifest.permission.DEVICE_POWER) public void endIdle(@NonNull String);
method @NonNull public String[] getSystemPowerWhitelist();
method @NonNull public String[] getSystemPowerWhitelistExceptIdle();
}
public class Environment {
method public static java.io.File buildPath(java.io.File, java.lang.String...);
- method @NonNull public static java.io.File getOdmDirectory();
- method @NonNull public static java.io.File getOemDirectory();
- method @NonNull public static java.io.File getProductDirectory();
- method @NonNull public static java.io.File getSystemExtDirectory();
- method @NonNull public static java.io.File getVendorDirectory();
}
public final class FileUtils {
@@ -2688,228 +1133,11 @@ package android.os {
method @NonNull public static byte[] digest(@NonNull java.io.InputStream, @NonNull String) throws java.io.IOException, java.security.NoSuchAlgorithmException;
}
- public class HidlMemory implements java.io.Closeable {
- ctor public HidlMemory(@NonNull String, @IntRange(from=0) long, @Nullable android.os.NativeHandle);
- method public void close() throws java.io.IOException;
- method @NonNull public android.os.HidlMemory dup() throws java.io.IOException;
- method protected void finalize();
- method @Nullable public android.os.NativeHandle getHandle();
- method @NonNull public String getName();
- method public long getSize();
- method @Nullable public android.os.NativeHandle releaseHandle();
- }
-
- public abstract class HwBinder implements android.os.IHwBinder {
- ctor public HwBinder();
- method public static final void configureRpcThreadpool(long, boolean);
- method public static void enableInstrumentation();
- method public static final android.os.IHwBinder getService(String, String) throws java.util.NoSuchElementException, android.os.RemoteException;
- method public static final android.os.IHwBinder getService(String, String, boolean) throws java.util.NoSuchElementException, android.os.RemoteException;
- method public static final void joinRpcThreadpool();
- method public abstract void onTransact(int, android.os.HwParcel, android.os.HwParcel, int) throws android.os.RemoteException;
- method public final void registerService(String) throws android.os.RemoteException;
- method public final void transact(int, android.os.HwParcel, android.os.HwParcel, int) throws android.os.RemoteException;
- }
-
- public class HwBlob {
- ctor public HwBlob(int);
- method public final void copyToBoolArray(long, boolean[], int);
- method public final void copyToDoubleArray(long, double[], int);
- method public final void copyToFloatArray(long, float[], int);
- method public final void copyToInt16Array(long, short[], int);
- method public final void copyToInt32Array(long, int[], int);
- method public final void copyToInt64Array(long, long[], int);
- method public final void copyToInt8Array(long, byte[], int);
- method public final boolean getBool(long);
- method public final double getDouble(long);
- method public final long getFieldHandle(long);
- method public final float getFloat(long);
- method public final short getInt16(long);
- method public final int getInt32(long);
- method public final long getInt64(long);
- method public final byte getInt8(long);
- method public final String getString(long);
- method public final long handle();
- method public final void putBlob(long, android.os.HwBlob);
- method public final void putBool(long, boolean);
- method public final void putBoolArray(long, boolean[]);
- method public final void putDouble(long, double);
- method public final void putDoubleArray(long, double[]);
- method public final void putFloat(long, float);
- method public final void putFloatArray(long, float[]);
- method public final void putHidlMemory(long, @NonNull android.os.HidlMemory);
- method public final void putInt16(long, short);
- method public final void putInt16Array(long, short[]);
- method public final void putInt32(long, int);
- method public final void putInt32Array(long, int[]);
- method public final void putInt64(long, long);
- method public final void putInt64Array(long, long[]);
- method public final void putInt8(long, byte);
- method public final void putInt8Array(long, byte[]);
- method public final void putNativeHandle(long, @Nullable android.os.NativeHandle);
- method public final void putString(long, String);
- method public static Boolean[] wrapArray(@NonNull boolean[]);
- method public static Long[] wrapArray(@NonNull long[]);
- method public static Byte[] wrapArray(@NonNull byte[]);
- method public static Short[] wrapArray(@NonNull short[]);
- method public static Integer[] wrapArray(@NonNull int[]);
- method public static Float[] wrapArray(@NonNull float[]);
- method public static Double[] wrapArray(@NonNull double[]);
- }
-
- public class HwParcel {
- ctor public HwParcel();
- method public final void enforceInterface(String);
- method public final boolean readBool();
- method public final java.util.ArrayList<java.lang.Boolean> readBoolVector();
- method public final android.os.HwBlob readBuffer(long);
- method public final double readDouble();
- method public final java.util.ArrayList<java.lang.Double> readDoubleVector();
- method public final android.os.HwBlob readEmbeddedBuffer(long, long, long, boolean);
- method @NonNull @Nullable public final android.os.HidlMemory readEmbeddedHidlMemory(long, long, long);
- method @Nullable public final android.os.NativeHandle readEmbeddedNativeHandle(long, long);
- method public final float readFloat();
- method public final java.util.ArrayList<java.lang.Float> readFloatVector();
- method @NonNull public final android.os.HidlMemory readHidlMemory();
- method public final short readInt16();
- method public final java.util.ArrayList<java.lang.Short> readInt16Vector();
- method public final int readInt32();
- method public final java.util.ArrayList<java.lang.Integer> readInt32Vector();
- method public final long readInt64();
- method public final java.util.ArrayList<java.lang.Long> readInt64Vector();
- method public final byte readInt8();
- method public final java.util.ArrayList<java.lang.Byte> readInt8Vector();
- method @Nullable public final android.os.NativeHandle readNativeHandle();
- method @NonNull public final java.util.ArrayList<android.os.NativeHandle> readNativeHandleVector();
- method public final String readString();
- method public final java.util.ArrayList<java.lang.String> readStringVector();
- method public final android.os.IHwBinder readStrongBinder();
- method public final void release();
- method public final void releaseTemporaryStorage();
- method public final void send();
- method public final void verifySuccess();
- method public final void writeBool(boolean);
- method public final void writeBoolVector(java.util.ArrayList<java.lang.Boolean>);
- method public final void writeBuffer(android.os.HwBlob);
- method public final void writeDouble(double);
- method public final void writeDoubleVector(java.util.ArrayList<java.lang.Double>);
- method public final void writeFloat(float);
- method public final void writeFloatVector(java.util.ArrayList<java.lang.Float>);
- method public final void writeHidlMemory(@NonNull android.os.HidlMemory);
- method public final void writeInt16(short);
- method public final void writeInt16Vector(java.util.ArrayList<java.lang.Short>);
- method public final void writeInt32(int);
- method public final void writeInt32Vector(java.util.ArrayList<java.lang.Integer>);
- method public final void writeInt64(long);
- method public final void writeInt64Vector(java.util.ArrayList<java.lang.Long>);
- method public final void writeInt8(byte);
- method public final void writeInt8Vector(java.util.ArrayList<java.lang.Byte>);
- method public final void writeInterfaceToken(String);
- method public final void writeNativeHandle(@Nullable android.os.NativeHandle);
- method public final void writeNativeHandleVector(@NonNull java.util.ArrayList<android.os.NativeHandle>);
- method public final void writeStatus(int);
- method public final void writeString(String);
- method public final void writeStringVector(java.util.ArrayList<java.lang.String>);
- method public final void writeStrongBinder(android.os.IHwBinder);
- field public static final int STATUS_SUCCESS = 0; // 0x0
- }
-
- public interface IHwBinder {
- method public boolean linkToDeath(android.os.IHwBinder.DeathRecipient, long);
- method public android.os.IHwInterface queryLocalInterface(String);
- method public void transact(int, android.os.HwParcel, android.os.HwParcel, int) throws android.os.RemoteException;
- method public boolean unlinkToDeath(android.os.IHwBinder.DeathRecipient);
- }
-
- public static interface IHwBinder.DeathRecipient {
- method public void serviceDied(long);
- }
-
- public interface IHwInterface {
- method public android.os.IHwBinder asBinder();
- }
-
- public class IncidentManager {
- method @RequiresPermission(android.Manifest.permission.APPROVE_INCIDENT_REPORTS) public void approveReport(android.net.Uri);
- method @RequiresPermission("android.permission.REQUEST_INCIDENT_REPORT_APPROVAL") public void cancelAuthorization(android.os.IncidentManager.AuthListener);
- method @RequiresPermission(allOf={android.Manifest.permission.DUMP, android.Manifest.permission.PACKAGE_USAGE_STATS}) public void deleteIncidentReports(android.net.Uri);
- method @RequiresPermission(android.Manifest.permission.APPROVE_INCIDENT_REPORTS) public void denyReport(android.net.Uri);
- method @Nullable @RequiresPermission(allOf={android.Manifest.permission.DUMP, android.Manifest.permission.PACKAGE_USAGE_STATS}) public android.os.IncidentManager.IncidentReport getIncidentReport(android.net.Uri);
- method @NonNull @RequiresPermission(allOf={android.Manifest.permission.DUMP, android.Manifest.permission.PACKAGE_USAGE_STATS}) public java.util.List<android.net.Uri> getIncidentReportList(String);
- method @RequiresPermission(android.Manifest.permission.APPROVE_INCIDENT_REPORTS) public java.util.List<android.os.IncidentManager.PendingReport> getPendingReports();
- method public void registerSection(int, @NonNull String, @NonNull java.util.concurrent.Executor, @NonNull android.os.IncidentManager.DumpCallback);
- method @RequiresPermission(allOf={android.Manifest.permission.DUMP, android.Manifest.permission.PACKAGE_USAGE_STATS}) public void reportIncident(android.os.IncidentReportArgs);
- method @RequiresPermission("android.permission.REQUEST_INCIDENT_REPORT_APPROVAL") public void requestAuthorization(int, String, int, android.os.IncidentManager.AuthListener);
- method public void unregisterSection(int);
- field public static final int FLAG_CONFIRMATION_DIALOG = 1; // 0x1
- field public static final int PRIVACY_POLICY_AUTO = 200; // 0xc8
- field public static final int PRIVACY_POLICY_EXPLICIT = 100; // 0x64
- field public static final int PRIVACY_POLICY_LOCAL = 0; // 0x0
- }
-
- public static class IncidentManager.AuthListener {
- ctor public IncidentManager.AuthListener();
- method public void onReportApproved();
- method public void onReportDenied();
- }
-
- public static class IncidentManager.DumpCallback {
- ctor public IncidentManager.DumpCallback();
- method public void onDumpSection(int, @NonNull java.io.OutputStream);
- }
-
- public static class IncidentManager.IncidentReport implements java.io.Closeable android.os.Parcelable {
- ctor public IncidentManager.IncidentReport(android.os.Parcel);
- method public void close();
- method public int describeContents();
- method public java.io.InputStream getInputStream() throws java.io.IOException;
- method public long getPrivacyPolicy();
- method public long getTimestamp();
- method public void writeToParcel(android.os.Parcel, int);
- field @NonNull public static final android.os.Parcelable.Creator<android.os.IncidentManager.IncidentReport> CREATOR;
- }
-
- public static class IncidentManager.PendingReport {
- ctor public IncidentManager.PendingReport(@NonNull android.net.Uri);
- method public int getFlags();
- method @NonNull public String getRequestingPackage();
- method public long getTimestamp();
- method @NonNull public android.net.Uri getUri();
- }
-
- public final class IncidentReportArgs implements android.os.Parcelable {
- ctor public IncidentReportArgs();
- ctor public IncidentReportArgs(android.os.Parcel);
- method public void addHeader(byte[]);
- method public void addSection(int);
- method public boolean containsSection(int);
- method public int describeContents();
- method public boolean isAll();
- method public void readFromParcel(android.os.Parcel);
- method public int sectionCount();
- method public void setAll(boolean);
- method public void setPrivacyPolicy(int);
- method public void writeToParcel(android.os.Parcel, int);
- field @NonNull public static final android.os.Parcelable.Creator<android.os.IncidentReportArgs> CREATOR;
- }
-
public final class MessageQueue {
method public int postSyncBarrier();
method public void removeSyncBarrier(int);
}
- public final class NativeHandle implements java.io.Closeable {
- ctor public NativeHandle();
- ctor public NativeHandle(@NonNull java.io.FileDescriptor, boolean);
- ctor public NativeHandle(@NonNull java.io.FileDescriptor[], @NonNull int[], boolean);
- method public void close() throws java.io.IOException;
- method @NonNull public android.os.NativeHandle dup() throws java.io.IOException;
- method @NonNull public java.io.FileDescriptor getFileDescriptor();
- method @NonNull public java.io.FileDescriptor[] getFileDescriptors();
- method @NonNull public int[] getInts();
- method public boolean hasSingleFileDescriptor();
- }
-
public final class Parcel {
method public boolean allowSquashing();
method public int readExceptionCode();
@@ -2921,24 +1149,7 @@ package android.os {
}
public final class PowerManager {
- method @RequiresPermission(android.Manifest.permission.POWER_SAVER) public int getPowerSaveModeTrigger();
- method @RequiresPermission(android.Manifest.permission.DEVICE_POWER) public void setBatteryDischargePrediction(@NonNull java.time.Duration, boolean);
- method @RequiresPermission(android.Manifest.permission.POWER_SAVER) public boolean setDynamicPowerSaveHint(boolean, int);
- method @RequiresPermission(anyOf={android.Manifest.permission.DEVICE_POWER, android.Manifest.permission.POWER_SAVER}) public boolean setPowerSaveModeEnabled(boolean);
field public static final String ACTION_ENHANCED_DISCHARGE_PREDICTION_CHANGED = "android.os.action.ENHANCED_DISCHARGE_PREDICTION_CHANGED";
- field public static final int POWER_SAVE_MODE_TRIGGER_DYNAMIC = 1; // 0x1
- field public static final int POWER_SAVE_MODE_TRIGGER_PERCENTAGE = 0; // 0x0
- }
-
- public class PowerWhitelistManager {
- method @RequiresPermission(android.Manifest.permission.DEVICE_POWER) public void addToWhitelist(@NonNull String);
- method @RequiresPermission(android.Manifest.permission.DEVICE_POWER) public void addToWhitelist(@NonNull java.util.List<java.lang.String>);
- method @RequiresPermission(android.Manifest.permission.DEVICE_POWER) public void removeFromWhitelist(@NonNull String);
- method @RequiresPermission(android.Manifest.permission.CHANGE_DEVICE_IDLE_TEMP_WHITELIST) public void whitelistAppTemporarily(@NonNull String, long);
- method @RequiresPermission(android.Manifest.permission.CHANGE_DEVICE_IDLE_TEMP_WHITELIST) public long whitelistAppTemporarilyForEvent(@NonNull String, int, @NonNull String);
- field public static final int EVENT_MMS = 2; // 0x2
- field public static final int EVENT_SMS = 1; // 0x1
- field public static final int EVENT_UNSPECIFIED = 0; // 0x0
}
public class Process {
@@ -2950,19 +1161,6 @@ package android.os {
field public static final int NUM_UIDS_PER_APP_ZYGOTE = 100; // 0x64
}
- public final class RemoteCallback implements android.os.Parcelable {
- ctor public RemoteCallback(android.os.RemoteCallback.OnResultListener);
- ctor public RemoteCallback(@NonNull android.os.RemoteCallback.OnResultListener, @Nullable android.os.Handler);
- method public int describeContents();
- method public void sendResult(@Nullable android.os.Bundle);
- method public void writeToParcel(android.os.Parcel, int);
- field @NonNull public static final android.os.Parcelable.Creator<android.os.RemoteCallback> CREATOR;
- }
-
- public static interface RemoteCallback.OnResultListener {
- method public void onResult(@Nullable android.os.Bundle);
- }
-
public final class StrictMode {
method public static void conditionallyCheckInstanceCounts();
method public static void setViolationLogger(android.os.StrictMode.ViolationLogger);
@@ -3000,31 +1198,11 @@ package android.os {
method @NonNull public android.os.StrictMode.VmPolicy.Builder permitIncorrectContextUse();
}
- public class SystemConfigManager {
- method @NonNull @RequiresPermission(android.Manifest.permission.READ_CARRIER_APP_INFO) public java.util.Set<java.lang.String> getDisabledUntilUsedPreinstalledCarrierApps();
- method @NonNull @RequiresPermission(android.Manifest.permission.READ_CARRIER_APP_INFO) public java.util.Map<java.lang.String,java.util.List<java.lang.String>> getDisabledUntilUsedPreinstalledCarrierAssociatedApps();
- }
-
- public class SystemProperties {
- method @NonNull public static String get(@NonNull String);
- method @NonNull public static String get(@NonNull String, @Nullable String);
- method public static boolean getBoolean(@NonNull String, boolean);
- method public static int getInt(@NonNull String, int);
- method public static long getLong(@NonNull String, long);
- }
-
public final class UserHandle implements android.os.Parcelable {
- method public static int getAppId(int);
- method public int getIdentifier();
method public static int getUid(int, int);
method public static int getUserId(int);
method public static boolean isApp(int);
- method public static int myUserId();
- method public static android.os.UserHandle of(int);
- field @NonNull public static final android.os.UserHandle ALL;
- field @NonNull public static final android.os.UserHandle CURRENT;
field public static final int MIN_SECONDARY_USER_ID = 10; // 0xa
- field @NonNull public static final android.os.UserHandle SYSTEM;
field public static final int USER_ALL = -1; // 0xffffffff
field public static final int USER_NULL = -10000; // 0xffffd8f0
field public static final int USER_SYSTEM = 0; // 0x0
@@ -3033,7 +1211,6 @@ package android.os {
public class UserManager {
method @RequiresPermission(anyOf={android.Manifest.permission.MANAGE_USERS, android.Manifest.permission.CREATE_USERS}) public boolean hasBaseUserRestriction(@NonNull String, @NonNull android.os.UserHandle);
method public static boolean isSplitSystemUser();
- field public static final String ACTION_USER_RESTRICTIONS_CHANGED = "android.os.action.USER_RESTRICTIONS_CHANGED";
}
public final class VibrationAttributes implements android.os.Parcelable {
@@ -3090,17 +1267,6 @@ package android.os {
field @NonNull public static final android.os.Parcelable.Creator<android.os.VibrationEffect.Waveform> CREATOR;
}
- public abstract class Vibrator {
- method @RequiresPermission(android.Manifest.permission.ACCESS_VIBRATOR_STATE) public void addVibratorStateListener(@NonNull android.os.Vibrator.OnVibratorStateChangedListener);
- method @RequiresPermission(android.Manifest.permission.ACCESS_VIBRATOR_STATE) public void addVibratorStateListener(@NonNull java.util.concurrent.Executor, @NonNull android.os.Vibrator.OnVibratorStateChangedListener);
- method @RequiresPermission(android.Manifest.permission.ACCESS_VIBRATOR_STATE) public boolean isVibrating();
- method @RequiresPermission(android.Manifest.permission.ACCESS_VIBRATOR_STATE) public void removeVibratorStateListener(@NonNull android.os.Vibrator.OnVibratorStateChangedListener);
- }
-
- public static interface Vibrator.OnVibratorStateChangedListener {
- method public void onVibratorStateChanged(boolean);
- }
-
public class VintfObject {
method public static String[] getHalNamesAndVersions();
method public static String getSepolicyVersion();
@@ -3120,16 +1286,10 @@ package android.os {
}
public class WorkSource implements android.os.Parcelable {
- ctor public WorkSource(int);
method public boolean add(int);
method public boolean add(int, String);
method @Deprecated public android.os.WorkSource addReturningNewbs(android.os.WorkSource);
- method @Nullable public String getPackageName(int);
- method public int getUid(int);
- method public boolean isEmpty();
method @Deprecated public android.os.WorkSource[] setReturningDiffs(android.os.WorkSource);
- method public int size();
- method @NonNull public android.os.WorkSource withoutNames();
}
}
@@ -3189,36 +1349,6 @@ package android.os.health {
}
-package android.os.image {
-
- public class DynamicSystemClient {
- ctor public DynamicSystemClient(@NonNull android.content.Context);
- method @RequiresPermission(android.Manifest.permission.INSTALL_DYNAMIC_SYSTEM) public void bind();
- method public void setOnStatusChangedListener(@NonNull java.util.concurrent.Executor, @NonNull android.os.image.DynamicSystemClient.OnStatusChangedListener);
- method public void setOnStatusChangedListener(@NonNull android.os.image.DynamicSystemClient.OnStatusChangedListener);
- method @RequiresPermission(android.Manifest.permission.INSTALL_DYNAMIC_SYSTEM) public void start(@NonNull android.net.Uri, long);
- method @RequiresPermission(android.Manifest.permission.INSTALL_DYNAMIC_SYSTEM) public void start(@NonNull android.net.Uri, long, long);
- method @RequiresPermission(android.Manifest.permission.INSTALL_DYNAMIC_SYSTEM) public void unbind();
- field public static final int CAUSE_ERROR_EXCEPTION = 6; // 0x6
- field public static final int CAUSE_ERROR_INVALID_URL = 4; // 0x4
- field public static final int CAUSE_ERROR_IO = 3; // 0x3
- field public static final int CAUSE_ERROR_IPC = 5; // 0x5
- field public static final int CAUSE_INSTALL_CANCELLED = 2; // 0x2
- field public static final int CAUSE_INSTALL_COMPLETED = 1; // 0x1
- field public static final int CAUSE_NOT_SPECIFIED = 0; // 0x0
- field public static final int STATUS_IN_PROGRESS = 2; // 0x2
- field public static final int STATUS_IN_USE = 4; // 0x4
- field public static final int STATUS_NOT_STARTED = 1; // 0x1
- field public static final int STATUS_READY = 3; // 0x3
- field public static final int STATUS_UNKNOWN = 0; // 0x0
- }
-
- public static interface DynamicSystemClient.OnStatusChangedListener {
- method public void onStatusChanged(int, int, long, @Nullable Throwable);
- }
-
-}
-
package android.os.storage {
public final class CrateInfo implements android.os.Parcelable {
@@ -3232,10 +1362,6 @@ package android.os.storage {
field @NonNull public static final android.os.Parcelable.Creator<android.os.storage.CrateInfo> CREATOR;
}
- public class StorageManager {
- method public static boolean hasIsolatedStorage();
- }
-
public final class StorageVolume implements android.os.Parcelable {
method public String getPath();
}
@@ -3252,17 +1378,9 @@ package android.os.strictmode {
package android.permission {
public final class PermissionControllerManager {
- method @RequiresPermission(anyOf={android.Manifest.permission.GRANT_RUNTIME_PERMISSIONS, android.Manifest.permission.RESTORE_RUNTIME_PERMISSIONS}) public void applyStagedRuntimePermissionBackup(@NonNull String, @NonNull android.os.UserHandle, @NonNull java.util.concurrent.Executor, @NonNull java.util.function.Consumer<java.lang.Boolean>);
method @RequiresPermission(android.Manifest.permission.GET_RUNTIME_PERMISSIONS) public void countPermissionApps(@NonNull java.util.List<java.lang.String>, int, @NonNull android.permission.PermissionControllerManager.OnCountPermissionAppsResultCallback, @Nullable android.os.Handler);
method @RequiresPermission(android.Manifest.permission.GET_RUNTIME_PERMISSIONS) public void getAppPermissions(@NonNull String, @NonNull android.permission.PermissionControllerManager.OnGetAppPermissionResultCallback, @Nullable android.os.Handler);
- method @RequiresPermission(android.Manifest.permission.GET_RUNTIME_PERMISSIONS) public void getRuntimePermissionBackup(@NonNull android.os.UserHandle, @NonNull java.util.concurrent.Executor, @NonNull java.util.function.Consumer<byte[]>);
method @RequiresPermission(android.Manifest.permission.REVOKE_RUNTIME_PERMISSIONS) public void revokeRuntimePermission(@NonNull String, @NonNull String);
- method @RequiresPermission(android.Manifest.permission.REVOKE_RUNTIME_PERMISSIONS) public void revokeRuntimePermissions(@NonNull java.util.Map<java.lang.String,java.util.List<java.lang.String>>, boolean, int, @NonNull java.util.concurrent.Executor, @NonNull android.permission.PermissionControllerManager.OnRevokeRuntimePermissionsCallback);
- method @RequiresPermission(anyOf={android.Manifest.permission.GRANT_RUNTIME_PERMISSIONS, android.Manifest.permission.RESTORE_RUNTIME_PERMISSIONS}) public void stageAndApplyRuntimePermissionsBackup(@NonNull byte[], @NonNull android.os.UserHandle);
- field public static final int COUNT_ONLY_WHEN_GRANTED = 1; // 0x1
- field public static final int COUNT_WHEN_SYSTEM = 2; // 0x2
- field public static final int REASON_INSTALLER_POLICY_VIOLATION = 2; // 0x2
- field public static final int REASON_MALWARE = 1; // 0x1
}
public static interface PermissionControllerManager.OnCountPermissionAppsResultCallback {
@@ -3273,33 +1391,6 @@ package android.permission {
method public void onGetAppPermissions(@NonNull java.util.List<android.permission.RuntimePermissionPresentationInfo>);
}
- public abstract static class PermissionControllerManager.OnRevokeRuntimePermissionsCallback {
- ctor public PermissionControllerManager.OnRevokeRuntimePermissionsCallback();
- method public abstract void onRevokeRuntimePermissions(@NonNull java.util.Map<java.lang.String,java.util.List<java.lang.String>>);
- }
-
- public final class PermissionManager {
- method @IntRange(from=0) @RequiresPermission(anyOf={android.Manifest.permission.ADJUST_RUNTIME_PERMISSIONS_POLICY, android.Manifest.permission.UPGRADE_RUNTIME_PERMISSIONS}) public int getRuntimePermissionsVersion();
- method @NonNull public java.util.List<android.permission.PermissionManager.SplitPermissionInfo> getSplitPermissions();
- method @RequiresPermission(anyOf={android.Manifest.permission.ADJUST_RUNTIME_PERMISSIONS_POLICY, android.Manifest.permission.UPGRADE_RUNTIME_PERMISSIONS}) public void setRuntimePermissionsVersion(@IntRange(from=0) int);
- }
-
- public static final class PermissionManager.SplitPermissionInfo {
- method @NonNull public java.util.List<java.lang.String> getNewPermissions();
- method @NonNull public String getSplitPermission();
- method public int getTargetSdk();
- }
-
- public final class RuntimePermissionPresentationInfo implements android.os.Parcelable {
- ctor public RuntimePermissionPresentationInfo(@NonNull CharSequence, boolean, boolean);
- method public int describeContents();
- method @NonNull public CharSequence getLabel();
- method public boolean isGranted();
- method public boolean isStandard();
- method public void writeToParcel(android.os.Parcel, int);
- field @NonNull public static final android.os.Parcelable.Creator<android.permission.RuntimePermissionPresentationInfo> CREATOR;
- }
-
}
package android.print {
@@ -3347,75 +1438,18 @@ package android.provider {
}
public final class DeviceConfig {
- method @RequiresPermission(android.Manifest.permission.READ_DEVICE_CONFIG) public static void addOnPropertiesChangedListener(@NonNull String, @NonNull java.util.concurrent.Executor, @NonNull android.provider.DeviceConfig.OnPropertiesChangedListener);
- method @RequiresPermission(android.Manifest.permission.READ_DEVICE_CONFIG) public static boolean getBoolean(@NonNull String, @NonNull String, boolean);
- method @RequiresPermission(android.Manifest.permission.READ_DEVICE_CONFIG) public static float getFloat(@NonNull String, @NonNull String, float);
- method @RequiresPermission(android.Manifest.permission.READ_DEVICE_CONFIG) public static int getInt(@NonNull String, @NonNull String, int);
- method @RequiresPermission(android.Manifest.permission.READ_DEVICE_CONFIG) public static long getLong(@NonNull String, @NonNull String, long);
- method @NonNull @RequiresPermission(android.Manifest.permission.READ_DEVICE_CONFIG) public static android.provider.DeviceConfig.Properties getProperties(@NonNull String, @NonNull java.lang.String...);
- method @RequiresPermission(android.Manifest.permission.READ_DEVICE_CONFIG) public static String getProperty(@NonNull String, @NonNull String);
- method @RequiresPermission(android.Manifest.permission.READ_DEVICE_CONFIG) public static String getString(@NonNull String, @NonNull String, @Nullable String);
- method public static void removeOnPropertiesChangedListener(@NonNull android.provider.DeviceConfig.OnPropertiesChangedListener);
- method @RequiresPermission(android.Manifest.permission.WRITE_DEVICE_CONFIG) public static void resetToDefaults(int, @Nullable String);
- method @RequiresPermission(android.Manifest.permission.WRITE_DEVICE_CONFIG) public static boolean setProperties(@NonNull android.provider.DeviceConfig.Properties) throws android.provider.DeviceConfig.BadConfigException;
- method @RequiresPermission(android.Manifest.permission.WRITE_DEVICE_CONFIG) public static boolean setProperty(@NonNull String, @NonNull String, @Nullable String, boolean);
field public static final String NAMESPACE_ALARM_MANAGER = "alarm_manager";
field public static final String NAMESPACE_ANDROID = "android";
- field public static final String NAMESPACE_AUTOFILL = "autofill";
- field public static final String NAMESPACE_BIOMETRICS = "biometrics";
- field public static final String NAMESPACE_CONTENT_CAPTURE = "content_capture";
field public static final String NAMESPACE_DEVICE_IDLE = "device_idle";
field public static final String NAMESPACE_JOB_SCHEDULER = "jobscheduler";
- field public static final String NAMESPACE_PERMISSIONS = "permissions";
- field public static final String NAMESPACE_PRIVACY = "privacy";
- field public static final String NAMESPACE_ROLLBACK = "rollback";
- field public static final String NAMESPACE_ROLLBACK_BOOT = "rollback_boot";
- }
-
- public static class DeviceConfig.BadConfigException extends java.lang.Exception {
- ctor public DeviceConfig.BadConfigException();
- }
-
- public static interface DeviceConfig.OnPropertiesChangedListener {
- method public void onPropertiesChanged(@NonNull android.provider.DeviceConfig.Properties);
- }
-
- public static class DeviceConfig.Properties {
- method public boolean getBoolean(@NonNull String, boolean);
- method public float getFloat(@NonNull String, float);
- method public int getInt(@NonNull String, int);
- method @NonNull public java.util.Set<java.lang.String> getKeyset();
- method public long getLong(@NonNull String, long);
- method @NonNull public String getNamespace();
- method @Nullable public String getString(@NonNull String, @Nullable String);
- }
-
- public static final class DeviceConfig.Properties.Builder {
- ctor public DeviceConfig.Properties.Builder(@NonNull String);
- method @NonNull public android.provider.DeviceConfig.Properties build();
- method @NonNull public android.provider.DeviceConfig.Properties.Builder setBoolean(@NonNull String, boolean);
- method @NonNull public android.provider.DeviceConfig.Properties.Builder setFloat(@NonNull String, float);
- method @NonNull public android.provider.DeviceConfig.Properties.Builder setInt(@NonNull String, int);
- method @NonNull public android.provider.DeviceConfig.Properties.Builder setLong(@NonNull String, long);
- method @NonNull public android.provider.DeviceConfig.Properties.Builder setString(@NonNull String, @Nullable String);
- }
-
- public final class DocumentsContract {
- method public static boolean isManageMode(@NonNull android.net.Uri);
- method @NonNull public static android.net.Uri setManageMode(@NonNull android.net.Uri);
}
public final class Settings {
- field public static final String ACTION_ENTERPRISE_PRIVACY_SETTINGS = "android.settings.ENTERPRISE_PRIVACY_SETTINGS";
- field public static final String ACTION_MANAGE_APP_OVERLAY_PERMISSION = "android.settings.MANAGE_APP_OVERLAY_PERMISSION";
- field public static final String ACTION_REQUEST_ENABLE_CONTENT_CAPTURE = "android.settings.REQUEST_ENABLE_CONTENT_CAPTURE";
- field public static final String ACTION_TETHER_PROVISIONING_UI = "android.settings.TETHER_PROVISIONING_UI";
field public static final int RESET_MODE_PACKAGE_DEFAULTS = 1; // 0x1
}
public static final class Settings.Global extends android.provider.Settings.NameValueTable {
field public static final String APP_OPS_CONSTANTS = "app_ops_constants";
- field public static final String AUTOFILL_COMPAT_MODE_ALLOWED_PACKAGES = "autofill_compat_mode_allowed_packages";
field public static final String AUTOMATIC_POWER_SAVE_MODE = "automatic_power_save_mode";
field public static final String BATTERY_SAVER_CONSTANTS = "battery_saver_constants";
field public static final String DYNAMIC_POWER_SAVINGS_DISABLE_THRESHOLD = "dynamic_power_savings_disable_threshold";
@@ -3430,12 +1464,10 @@ package android.provider {
field public static final String NOTIFICATION_BUBBLES = "notification_bubbles";
field public static final String OVERLAY_DISPLAY_DEVICES = "overlay_display_devices";
field public static final String SHOW_FIRST_CRASH_DIALOG = "show_first_crash_dialog";
- field public static final String TETHER_OFFLOAD_DISABLED = "tether_offload_disabled";
field public static final String USE_OPEN_WIFI_PACKAGE = "use_open_wifi_package";
}
public static final class Settings.Secure extends android.provider.Settings.NameValueTable {
- method @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS) public static void resetToDefaults(@NonNull android.content.ContentResolver, @Nullable String);
field public static final String ACCESSIBILITY_DISPLAY_MAGNIFICATION_ENABLED = "accessibility_display_magnification_enabled";
field public static final String ACCESSIBILITY_MAGNIFICATION_CAPABILITY = "accessibility_magnification_capability";
field public static final String ACCESSIBILITY_MAGNIFICATION_MODE = "accessibility_magnification_mode";
@@ -3444,23 +1476,12 @@ package android.provider {
field public static final int ACCESSIBILITY_MAGNIFICATION_MODE_WINDOW = 2; // 0x2
field public static final String ACCESSIBILITY_SHORTCUT_TARGET_SERVICE = "accessibility_shortcut_target_service";
field public static final String ANR_SHOW_BACKGROUND = "anr_show_background";
- field public static final String AUTOFILL_FEATURE_FIELD_CLASSIFICATION = "autofill_field_classification";
field public static final String AUTOFILL_SERVICE = "autofill_service";
- field public static final String AUTOFILL_USER_DATA_MAX_CATEGORY_COUNT = "autofill_user_data_max_category_count";
- field public static final String AUTOFILL_USER_DATA_MAX_FIELD_CLASSIFICATION_IDS_SIZE = "autofill_user_data_max_field_classification_size";
- field public static final String AUTOFILL_USER_DATA_MAX_USER_DATA_SIZE = "autofill_user_data_max_user_data_size";
- field public static final String AUTOFILL_USER_DATA_MAX_VALUE_LENGTH = "autofill_user_data_max_value_length";
- field public static final String AUTOFILL_USER_DATA_MIN_VALUE_LENGTH = "autofill_user_data_min_value_length";
field public static final String CONTENT_CAPTURE_ENABLED = "content_capture_enabled";
field public static final String DISABLED_PRINT_SERVICES = "disabled_print_services";
- field public static final String DOZE_ALWAYS_ON = "doze_always_on";
field @Deprecated public static final String ENABLED_NOTIFICATION_POLICY_ACCESS_PACKAGES = "enabled_notification_policy_access_packages";
field public static final String ENABLED_VR_LISTENERS = "enabled_vr_listeners";
field public static final String IMMERSIVE_MODE_CONFIRMATIONS = "immersive_mode_confirmations";
- field public static final String LOCATION_ACCESS_CHECK_DELAY_MILLIS = "location_access_check_delay_millis";
- field public static final String LOCATION_ACCESS_CHECK_INTERVAL_MILLIS = "location_access_check_interval_millis";
- field public static final String LOCK_SCREEN_ALLOW_PRIVATE_NOTIFICATIONS = "lock_screen_allow_private_notifications";
- field public static final String LOCK_SCREEN_SHOW_NOTIFICATIONS = "lock_screen_show_notifications";
field public static final String NFC_PAYMENT_DEFAULT_COMPONENT = "nfc_payment_default_component";
field public static final String NOTIFICATION_BADGING = "notification_badging";
field public static final String POWER_MENU_LOCKED_SHOW_CONTENT = "power_menu_locked_show_content";
@@ -3469,45 +1490,9 @@ package android.provider {
field public static final String SHOW_FIRST_CRASH_DIALOG_DEV_OPTION = "show_first_crash_dialog_dev_option";
field public static final String SHOW_IME_WITH_HARD_KEYBOARD = "show_ime_with_hard_keyboard";
field @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS) public static final String SYNC_PARENT_SOUNDS = "sync_parent_sounds";
- field public static final String USER_SETUP_COMPLETE = "user_setup_complete";
field public static final String VOICE_INTERACTION_SERVICE = "voice_interaction_service";
}
- public static final class Telephony.CellBroadcasts implements android.provider.BaseColumns {
- field public static final String CID = "cid";
- field public static final String CMAS_CATEGORY = "cmas_category";
- field public static final String CMAS_CERTAINTY = "cmas_certainty";
- field public static final String CMAS_MESSAGE_CLASS = "cmas_message_class";
- field public static final String CMAS_RESPONSE_TYPE = "cmas_response_type";
- field public static final String CMAS_SEVERITY = "cmas_severity";
- field public static final String CMAS_URGENCY = "cmas_urgency";
- field @NonNull public static final android.net.Uri CONTENT_URI;
- field public static final String DATA_CODING_SCHEME = "dcs";
- field public static final String DEFAULT_SORT_ORDER = "date DESC";
- field public static final String DELIVERY_TIME = "date";
- field public static final String ETWS_IS_PRIMARY = "etws_is_primary";
- field public static final String ETWS_WARNING_TYPE = "etws_warning_type";
- field public static final String GEOGRAPHICAL_SCOPE = "geo_scope";
- field public static final String GEOMETRIES = "geometries";
- field public static final String LAC = "lac";
- field public static final String LANGUAGE_CODE = "language";
- field public static final String LOCATION_CHECK_TIME = "location_check_time";
- field public static final String MAXIMUM_WAIT_TIME = "maximum_wait_time";
- field public static final String MESSAGE_BODY = "body";
- field public static final String MESSAGE_BROADCASTED = "message_broadcasted";
- field public static final String MESSAGE_DISPLAYED = "message_displayed";
- field public static final String MESSAGE_FORMAT = "format";
- field @NonNull @RequiresPermission(android.Manifest.permission.READ_CELL_BROADCASTS) public static final android.net.Uri MESSAGE_HISTORY_URI;
- field public static final String MESSAGE_PRIORITY = "priority";
- field public static final String MESSAGE_READ = "read";
- field public static final String PLMN = "plmn";
- field public static final String RECEIVED_TIME = "received_time";
- field public static final String SERIAL_NUMBER = "serial_number";
- field public static final String SERVICE_CATEGORY = "service_category";
- field public static final String SLOT_INDEX = "slot_index";
- field public static final String SUBSCRIPTION_ID = "sub_id";
- }
-
public static final class Telephony.Sms.Intents {
field public static final String SMS_CARRIER_PROVISION_ACTION = "android.provider.Telephony.SMS_CARRIER_PROVISION";
}
@@ -3529,19 +1514,6 @@ package android.security {
package android.security.keystore {
- public abstract class AttestationUtils {
- method @NonNull @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public static java.security.cert.X509Certificate[] attestDeviceIds(android.content.Context, @NonNull int[], @NonNull byte[]) throws android.security.keystore.DeviceIdAttestationException;
- field public static final int ID_TYPE_IMEI = 2; // 0x2
- field public static final int ID_TYPE_MEID = 3; // 0x3
- field public static final int ID_TYPE_SERIAL = 1; // 0x1
- field public static final int USE_INDIVIDUAL_ATTESTATION = 4; // 0x4
- }
-
- public class DeviceIdAttestationException extends java.lang.Exception {
- ctor public DeviceIdAttestationException(@Nullable String);
- ctor public DeviceIdAttestationException(@Nullable String, @Nullable Throwable);
- }
-
public static final class KeyGenParameterSpec.Builder {
method @NonNull public android.security.keystore.KeyGenParameterSpec.Builder setUniqueIdIncluded(boolean);
}
@@ -3556,37 +1528,8 @@ package android.security.keystore {
}
-package android.service.appprediction {
-
- public abstract class AppPredictionService extends android.app.Service {
- ctor public AppPredictionService();
- method @MainThread public abstract void onAppTargetEvent(@NonNull android.app.prediction.AppPredictionSessionId, @NonNull android.app.prediction.AppTargetEvent);
- method @NonNull public final android.os.IBinder onBind(@NonNull android.content.Intent);
- method public void onCreatePredictionSession(@NonNull android.app.prediction.AppPredictionContext, @NonNull android.app.prediction.AppPredictionSessionId);
- method @MainThread public void onDestroyPredictionSession(@NonNull android.app.prediction.AppPredictionSessionId);
- method @MainThread public abstract void onLaunchLocationShown(@NonNull android.app.prediction.AppPredictionSessionId, @NonNull String, @NonNull java.util.List<android.app.prediction.AppTargetId>);
- method @MainThread public abstract void onRequestPredictionUpdate(@NonNull android.app.prediction.AppPredictionSessionId);
- method @MainThread public abstract void onSortAppTargets(@NonNull android.app.prediction.AppPredictionSessionId, @NonNull java.util.List<android.app.prediction.AppTarget>, @NonNull android.os.CancellationSignal, @NonNull java.util.function.Consumer<java.util.List<android.app.prediction.AppTarget>>);
- method @MainThread public void onStartPredictionUpdates();
- method @MainThread public void onStopPredictionUpdates();
- method public final void updatePredictions(@NonNull android.app.prediction.AppPredictionSessionId, @NonNull java.util.List<android.app.prediction.AppTarget>);
- }
-
-}
-
package android.service.autofill {
- public abstract class AutofillFieldClassificationService extends android.app.Service {
- ctor public AutofillFieldClassificationService();
- method public android.os.IBinder onBind(android.content.Intent);
- field public static final String REQUIRED_ALGORITHM_CREDIT_CARD = "CREDIT_CARD";
- field public static final String REQUIRED_ALGORITHM_EDIT_DISTANCE = "EDIT_DISTANCE";
- field public static final String REQUIRED_ALGORITHM_EXACT_MATCH = "EXACT_MATCH";
- field public static final String SERVICE_INTERFACE = "android.service.autofill.AutofillFieldClassificationService";
- field public static final String SERVICE_META_DATA_KEY_AVAILABLE_ALGORITHMS = "android.autofill.field_classification.available_algorithms";
- field public static final String SERVICE_META_DATA_KEY_DEFAULT_ALGORITHM = "android.autofill.field_classification.default_algorithm";
- }
-
public final class CharSequenceTransformation extends android.service.autofill.InternalTransformation implements android.os.Parcelable android.service.autofill.Transformation {
method public void apply(@NonNull android.service.autofill.ValueFinder, @NonNull android.widget.RemoteViews, int) throws java.lang.Exception;
}
@@ -3609,11 +1552,6 @@ package android.service.autofill {
method @Nullable public android.util.SparseArray<android.service.autofill.InternalOnClickAction> getActions();
}
- public static final class Dataset.Builder {
- ctor public Dataset.Builder(@NonNull android.service.autofill.InlinePresentation);
- method @NonNull public android.service.autofill.Dataset.Builder setFieldInlinePresentation(@NonNull android.view.autofill.AutofillId, @Nullable android.view.autofill.AutofillValue, @Nullable java.util.regex.Pattern, @NonNull android.service.autofill.InlinePresentation);
- }
-
public final class DateTransformation extends android.service.autofill.InternalTransformation implements android.os.Parcelable android.service.autofill.Transformation {
method public void apply(@NonNull android.service.autofill.ValueFinder, @NonNull android.widget.RemoteViews, int) throws java.lang.Exception;
}
@@ -3630,15 +1568,6 @@ package android.service.autofill {
method public void apply(@NonNull android.service.autofill.ValueFinder, @NonNull android.widget.RemoteViews, int) throws java.lang.Exception;
}
- public abstract class InlineSuggestionRenderService extends android.app.Service {
- ctor public InlineSuggestionRenderService();
- method @Nullable public final android.os.IBinder onBind(@NonNull android.content.Intent);
- method @NonNull public android.os.Bundle onGetInlineSuggestionsRendererInfo();
- method @Nullable public android.view.View onRenderSuggestion(@NonNull android.service.autofill.InlinePresentation, int, int);
- method public final void startIntentSender(@NonNull android.content.IntentSender);
- field public static final String SERVICE_INTERFACE = "android.service.autofill.InlineSuggestionRenderService";
- }
-
public abstract class InternalOnClickAction implements android.service.autofill.OnClickAction android.os.Parcelable {
ctor public InternalOnClickAction();
method public abstract void onClick(@NonNull android.view.ViewGroup);
@@ -3688,26 +1617,6 @@ package android.service.autofill {
package android.service.autofill.augmented {
- public abstract class AugmentedAutofillService extends android.app.Service {
- ctor public AugmentedAutofillService();
- method protected final void dump(java.io.FileDescriptor, java.io.PrintWriter, String[]);
- method protected void dump(@NonNull java.io.PrintWriter, @NonNull String[]);
- method @Nullable public final android.service.autofill.FillEventHistory getFillEventHistory();
- method public void onConnected();
- method public void onDisconnected();
- method public void onFillRequest(@NonNull android.service.autofill.augmented.FillRequest, @NonNull android.os.CancellationSignal, @NonNull android.service.autofill.augmented.FillController, @NonNull android.service.autofill.augmented.FillCallback);
- method public final boolean requestAutofill(@NonNull android.content.ComponentName, @NonNull android.view.autofill.AutofillId);
- field public static final String SERVICE_INTERFACE = "android.service.autofill.augmented.AugmentedAutofillService";
- }
-
- public final class FillCallback {
- method public void onSuccess(@Nullable android.service.autofill.augmented.FillResponse);
- }
-
- public final class FillController {
- method public void autofill(@NonNull java.util.List<android.util.Pair<android.view.autofill.AutofillId,android.view.autofill.AutofillValue>>);
- }
-
public final class FillRequest {
method @NonNull public android.content.ComponentName getActivityComponent();
method @NonNull public android.view.autofill.AutofillId getFocusedId();
@@ -3717,181 +1626,14 @@ package android.service.autofill.augmented {
method public int getTaskId();
}
- public final class FillResponse {
- }
-
- public static final class FillResponse.Builder {
- ctor public FillResponse.Builder();
- method @NonNull public android.service.autofill.augmented.FillResponse build();
- method @NonNull public android.service.autofill.augmented.FillResponse.Builder setClientState(@NonNull android.os.Bundle);
- method @NonNull public android.service.autofill.augmented.FillResponse.Builder setFillWindow(@NonNull android.service.autofill.augmented.FillWindow);
- method @NonNull public android.service.autofill.augmented.FillResponse.Builder setInlineSuggestions(@NonNull java.util.List<android.service.autofill.Dataset>);
- }
-
- public final class FillWindow implements java.lang.AutoCloseable {
- ctor public FillWindow();
- method public void destroy();
- method public boolean update(@NonNull android.service.autofill.augmented.PresentationParams.Area, @NonNull android.view.View, long);
- }
-
- public abstract class PresentationParams {
- method @Nullable public android.service.autofill.augmented.PresentationParams.Area getSuggestionArea();
- }
-
- public abstract static class PresentationParams.Area {
- method @NonNull public android.graphics.Rect getBounds();
- }
-
-}
-
-package android.service.contentcapture {
-
- public final class ActivityEvent implements android.os.Parcelable {
- method public int describeContents();
- method @NonNull public android.content.ComponentName getComponentName();
- method public int getEventType();
- method public void writeToParcel(@NonNull android.os.Parcel, int);
- field @NonNull public static final android.os.Parcelable.Creator<android.service.contentcapture.ActivityEvent> CREATOR;
- field public static final int TYPE_ACTIVITY_DESTROYED = 24; // 0x18
- field public static final int TYPE_ACTIVITY_PAUSED = 2; // 0x2
- field public static final int TYPE_ACTIVITY_RESUMED = 1; // 0x1
- field public static final int TYPE_ACTIVITY_STOPPED = 23; // 0x17
- }
-
- public abstract class ContentCaptureService extends android.app.Service {
- ctor public ContentCaptureService();
- method public final void disableSelf();
- method public void onActivityEvent(@NonNull android.service.contentcapture.ActivityEvent);
- method public void onActivitySnapshot(@NonNull android.view.contentcapture.ContentCaptureSessionId, @NonNull android.service.contentcapture.SnapshotData);
- method public void onConnected();
- method public void onContentCaptureEvent(@NonNull android.view.contentcapture.ContentCaptureSessionId, @NonNull android.view.contentcapture.ContentCaptureEvent);
- method public void onCreateContentCaptureSession(@NonNull android.view.contentcapture.ContentCaptureContext, @NonNull android.view.contentcapture.ContentCaptureSessionId);
- method public void onDataRemovalRequest(@NonNull android.view.contentcapture.DataRemovalRequest);
- method public void onDataShareRequest(@NonNull android.view.contentcapture.DataShareRequest, @NonNull android.service.contentcapture.DataShareCallback);
- method public void onDestroyContentCaptureSession(@NonNull android.view.contentcapture.ContentCaptureSessionId);
- method public void onDisconnected();
- method public final void setContentCaptureConditions(@NonNull String, @Nullable java.util.Set<android.view.contentcapture.ContentCaptureCondition>);
- method public final void setContentCaptureWhitelist(@Nullable java.util.Set<java.lang.String>, @Nullable java.util.Set<android.content.ComponentName>);
- field public static final String SERVICE_INTERFACE = "android.service.contentcapture.ContentCaptureService";
- field public static final String SERVICE_META_DATA = "android.content_capture";
- }
-
- public interface DataShareCallback {
- method public void onAccept(@NonNull java.util.concurrent.Executor, @NonNull android.service.contentcapture.DataShareReadAdapter);
- method public void onReject();
- }
-
- public interface DataShareReadAdapter {
- method public void onError(int);
- method public void onStart(@NonNull android.os.ParcelFileDescriptor);
- }
-
- public final class SnapshotData implements android.os.Parcelable {
- method public int describeContents();
- method @Nullable public android.app.assist.AssistContent getAssistContent();
- method @NonNull public android.os.Bundle getAssistData();
- method @NonNull public android.app.assist.AssistStructure getAssistStructure();
- method public void writeToParcel(@NonNull android.os.Parcel, int);
- field @NonNull public static final android.os.Parcelable.Creator<android.service.contentcapture.SnapshotData> CREATOR;
- }
-
}
package android.service.notification {
- public final class Adjustment implements android.os.Parcelable {
- ctor public Adjustment(String, String, android.os.Bundle, CharSequence, int);
- ctor public Adjustment(@NonNull String, @NonNull String, @NonNull android.os.Bundle, @NonNull CharSequence, @NonNull android.os.UserHandle);
- method public int describeContents();
- method @NonNull public CharSequence getExplanation();
- method @NonNull public String getKey();
- method @NonNull public String getPackage();
- method @NonNull public android.os.Bundle getSignals();
- method public int getUser();
- method @NonNull public android.os.UserHandle getUserHandle();
- method public void writeToParcel(android.os.Parcel, int);
- field @NonNull public static final android.os.Parcelable.Creator<android.service.notification.Adjustment> CREATOR;
- field public static final String KEY_CONTEXTUAL_ACTIONS = "key_contextual_actions";
- field public static final String KEY_IMPORTANCE = "key_importance";
- field public static final String KEY_RANKING_SCORE = "key_ranking_score";
- field public static final String KEY_SNOOZE_CRITERIA = "key_snooze_criteria";
- field public static final String KEY_TEXT_REPLIES = "key_text_replies";
- field public static final String KEY_USER_SENTIMENT = "key_user_sentiment";
- }
-
@Deprecated public abstract class ConditionProviderService extends android.app.Service {
method @Deprecated public boolean isBound();
}
- public abstract class NotificationAssistantService extends android.service.notification.NotificationListenerService {
- ctor public NotificationAssistantService();
- method public final void adjustNotification(@NonNull android.service.notification.Adjustment);
- method public final void adjustNotifications(@NonNull java.util.List<android.service.notification.Adjustment>);
- method public void onActionInvoked(@NonNull String, @NonNull android.app.Notification.Action, int);
- method public void onAllowedAdjustmentsChanged();
- method @NonNull public final android.os.IBinder onBind(@Nullable android.content.Intent);
- method public void onNotificationDirectReplied(@NonNull String);
- method @Nullable public abstract android.service.notification.Adjustment onNotificationEnqueued(@NonNull android.service.notification.StatusBarNotification);
- method @Nullable public android.service.notification.Adjustment onNotificationEnqueued(@NonNull android.service.notification.StatusBarNotification, @NonNull android.app.NotificationChannel);
- method public void onNotificationExpansionChanged(@NonNull String, boolean, boolean);
- method public abstract void onNotificationSnoozedUntilContext(@NonNull android.service.notification.StatusBarNotification, @NonNull String);
- method public void onNotificationVisibilityChanged(@NonNull String, boolean);
- method public void onNotificationsSeen(@NonNull java.util.List<java.lang.String>);
- method public void onPanelHidden();
- method public void onPanelRevealed(int);
- method public void onSuggestedReplySent(@NonNull String, @NonNull CharSequence, int);
- method public final void unsnoozeNotification(@NonNull String);
- field public static final String SERVICE_INTERFACE = "android.service.notification.NotificationAssistantService";
- field public static final int SOURCE_FROM_APP = 0; // 0x0
- field public static final int SOURCE_FROM_ASSISTANT = 1; // 0x1
- }
-
- public abstract class NotificationListenerService extends android.app.Service {
- method public void onNotificationRemoved(@NonNull android.service.notification.StatusBarNotification, @NonNull android.service.notification.NotificationListenerService.RankingMap, @NonNull android.service.notification.NotificationStats, int);
- }
-
- public final class NotificationStats implements android.os.Parcelable {
- ctor public NotificationStats();
- method public int describeContents();
- method public int getDismissalSentiment();
- method public int getDismissalSurface();
- method public boolean hasDirectReplied();
- method public boolean hasExpanded();
- method public boolean hasInteracted();
- method public boolean hasSeen();
- method public boolean hasSnoozed();
- method public boolean hasViewedSettings();
- method public void setDirectReplied();
- method public void setDismissalSentiment(int);
- method public void setDismissalSurface(int);
- method public void setExpanded();
- method public void setSeen();
- method public void setSnoozed();
- method public void setViewedSettings();
- method public void writeToParcel(android.os.Parcel, int);
- field @NonNull public static final android.os.Parcelable.Creator<android.service.notification.NotificationStats> CREATOR;
- field public static final int DISMISSAL_AOD = 2; // 0x2
- field public static final int DISMISSAL_NOT_DISMISSED = -1; // 0xffffffff
- field public static final int DISMISSAL_OTHER = 0; // 0x0
- field public static final int DISMISSAL_PEEK = 1; // 0x1
- field public static final int DISMISSAL_SHADE = 3; // 0x3
- field public static final int DISMISS_SENTIMENT_NEGATIVE = 0; // 0x0
- field public static final int DISMISS_SENTIMENT_NEUTRAL = 1; // 0x1
- field public static final int DISMISS_SENTIMENT_POSITIVE = 2; // 0x2
- field public static final int DISMISS_SENTIMENT_UNKNOWN = -1000; // 0xfffffc18
- }
-
- public final class SnoozeCriterion implements android.os.Parcelable {
- ctor public SnoozeCriterion(String, CharSequence, CharSequence);
- ctor protected SnoozeCriterion(android.os.Parcel);
- method public int describeContents();
- method public CharSequence getConfirmation();
- method public CharSequence getExplanation();
- method public String getId();
- method public void writeToParcel(android.os.Parcel, int);
- field @NonNull public static final android.os.Parcelable.Creator<android.service.notification.SnoozeCriterion> CREATOR;
- }
-
}
package android.service.quickaccesswallet {
@@ -3932,67 +1674,16 @@ package android.service.quicksettings {
}
-package android.service.textclassifier {
-
- public abstract class TextClassifierService extends android.app.Service {
- ctor public TextClassifierService();
- method @NonNull public static android.view.textclassifier.TextClassifier getDefaultTextClassifierImplementation(@NonNull android.content.Context);
- method @Deprecated public final android.view.textclassifier.TextClassifier getLocalTextClassifier();
- method @Nullable public final android.os.IBinder onBind(@NonNull android.content.Intent);
- method @MainThread public abstract void onClassifyText(@Nullable android.view.textclassifier.TextClassificationSessionId, @NonNull android.view.textclassifier.TextClassification.Request, @NonNull android.os.CancellationSignal, @NonNull android.service.textclassifier.TextClassifierService.Callback<android.view.textclassifier.TextClassification>);
- method public void onConnected();
- method @MainThread public void onCreateTextClassificationSession(@NonNull android.view.textclassifier.TextClassificationContext, @NonNull android.view.textclassifier.TextClassificationSessionId);
- method @MainThread public void onDestroyTextClassificationSession(@NonNull android.view.textclassifier.TextClassificationSessionId);
- method @MainThread public void onDetectLanguage(@Nullable android.view.textclassifier.TextClassificationSessionId, @NonNull android.view.textclassifier.TextLanguage.Request, @NonNull android.os.CancellationSignal, @NonNull android.service.textclassifier.TextClassifierService.Callback<android.view.textclassifier.TextLanguage>);
- method public void onDisconnected();
- method @MainThread public abstract void onGenerateLinks(@Nullable android.view.textclassifier.TextClassificationSessionId, @NonNull android.view.textclassifier.TextLinks.Request, @NonNull android.os.CancellationSignal, @NonNull android.service.textclassifier.TextClassifierService.Callback<android.view.textclassifier.TextLinks>);
- method @Deprecated @MainThread public void onSelectionEvent(@Nullable android.view.textclassifier.TextClassificationSessionId, @NonNull android.view.textclassifier.SelectionEvent);
- method @MainThread public void onSuggestConversationActions(@Nullable android.view.textclassifier.TextClassificationSessionId, @NonNull android.view.textclassifier.ConversationActions.Request, @NonNull android.os.CancellationSignal, @NonNull android.service.textclassifier.TextClassifierService.Callback<android.view.textclassifier.ConversationActions>);
- method @MainThread public abstract void onSuggestSelection(@Nullable android.view.textclassifier.TextClassificationSessionId, @NonNull android.view.textclassifier.TextSelection.Request, @NonNull android.os.CancellationSignal, @NonNull android.service.textclassifier.TextClassifierService.Callback<android.view.textclassifier.TextSelection>);
- method @MainThread public void onTextClassifierEvent(@Nullable android.view.textclassifier.TextClassificationSessionId, @NonNull android.view.textclassifier.TextClassifierEvent);
- field public static final String SERVICE_INTERFACE = "android.service.textclassifier.TextClassifierService";
- }
-
- public static interface TextClassifierService.Callback<T> {
- method public void onFailure(@NonNull CharSequence);
- method public void onSuccess(T);
- }
-
-}
-
package android.service.watchdog {
public abstract class ExplicitHealthCheckService extends android.app.Service {
- ctor public ExplicitHealthCheckService();
- method public final void notifyHealthCheckPassed(@NonNull String);
- method @NonNull public final android.os.IBinder onBind(@NonNull android.content.Intent);
- method public abstract void onCancelHealthCheck(@NonNull String);
- method @NonNull public abstract java.util.List<java.lang.String> onGetRequestedPackages();
- method @NonNull public abstract java.util.List<android.service.watchdog.ExplicitHealthCheckService.PackageConfig> onGetSupportedPackages();
- method public abstract void onRequestHealthCheck(@NonNull String);
method public void setCallback(@Nullable android.os.RemoteCallback);
- field public static final String BIND_PERMISSION = "android.permission.BIND_EXPLICIT_HEALTH_CHECK_SERVICE";
- field public static final String SERVICE_INTERFACE = "android.service.watchdog.ExplicitHealthCheckService";
- }
-
- public static final class ExplicitHealthCheckService.PackageConfig implements android.os.Parcelable {
- ctor public ExplicitHealthCheckService.PackageConfig(@NonNull String, long);
- method public int describeContents();
- method public long getHealthCheckTimeoutMillis();
- method @NonNull public String getPackageName();
- method public void writeToParcel(android.os.Parcel, int);
- field @NonNull public static final android.os.Parcelable.Creator<android.service.watchdog.ExplicitHealthCheckService.PackageConfig> CREATOR;
}
}
package android.telecom {
- public final class Call {
- method public void enterBackgroundAudioProcessing();
- method public void exitBackgroundAudioProcessing(boolean);
- }
-
public static class Call.Details {
method public String getTelecomCallId();
}
@@ -4001,42 +1692,6 @@ package android.telecom {
ctor public CallAudioState(boolean, int, int, @Nullable android.bluetooth.BluetoothDevice, @NonNull java.util.Collection<android.bluetooth.BluetoothDevice>);
}
- public static class CallScreeningService.CallResponse.Builder {
- method @NonNull @RequiresPermission(android.Manifest.permission.CAPTURE_AUDIO_OUTPUT) public android.telecom.CallScreeningService.CallResponse.Builder setShouldScreenCallViaAudioProcessing(boolean);
- }
-
- public abstract class Conference extends android.telecom.Conferenceable {
- method public android.telecom.Connection getPrimaryConnection();
- method @NonNull public final String getTelecomCallId();
- method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public final void setAddress(@NonNull android.net.Uri, int);
- method public final void setCallerDisplayName(@NonNull String, int);
- method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setConferenceState(boolean);
- }
-
- public abstract class Connection extends android.telecom.Conferenceable {
- method @IntRange(from=0) public final long getConnectTimeMillis();
- method public final long getConnectionStartElapsedRealtimeMillis();
- method @Nullable public android.telecom.PhoneAccountHandle getPhoneAccountHandle();
- method @Nullable public final String getTelecomCallId();
- method public final void resetConnectionTime();
- method public void setCallDirection(int);
- method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public final void setConnectTimeMillis(@IntRange(from=0) long);
- method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public final void setConnectionStartElapsedRealtimeMillis(long);
- method public void setPhoneAccountHandle(@NonNull android.telecom.PhoneAccountHandle);
- method public void setTelecomCallId(@NonNull String);
- field public static final int CAPABILITY_CONFERENCE_HAS_NO_CHILDREN = 2097152; // 0x200000
- field public static final int CAPABILITY_SPEED_UP_MT_AUDIO = 262144; // 0x40000
- field public static final String EXTRA_DISABLE_ADD_CALL = "android.telecom.extra.DISABLE_ADD_CALL";
- field public static final int PROPERTY_EMERGENCY_CALLBACK_MODE = 1; // 0x1
- field public static final int PROPERTY_GENERIC_CONFERENCE = 2; // 0x2
- field public static final int PROPERTY_IS_DOWNGRADED_CONFERENCE = 64; // 0x40
- field public static final int PROPERTY_REMOTELY_HOSTED = 2048; // 0x800
- }
-
- public final class ConnectionRequest implements android.os.Parcelable {
- method @Nullable public String getTelecomCallId();
- }
-
public static final class ConnectionRequest.Builder {
ctor public ConnectionRequest.Builder();
method @NonNull public android.telecom.ConnectionRequest build();
@@ -4052,53 +1707,11 @@ package android.telecom {
method @NonNull public android.telecom.ConnectionRequest.Builder setVideoState(int);
}
- public static class PhoneAccount.Builder {
- method @NonNull @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public android.telecom.PhoneAccount.Builder setGroupId(@NonNull String);
- }
-
- public class PhoneAccountSuggestionService extends android.app.Service {
- ctor public PhoneAccountSuggestionService();
- method public void onAccountSuggestionRequest(@NonNull String);
- method public android.os.IBinder onBind(android.content.Intent);
- method public final void suggestPhoneAccounts(@NonNull String, @NonNull java.util.List<android.telecom.PhoneAccountSuggestion>);
- field public static final String SERVICE_INTERFACE = "android.telecom.PhoneAccountSuggestionService";
- }
-
- public class TelecomManager {
- method @NonNull public android.content.Intent createLaunchEmergencyDialerIntent(@Nullable String);
- method @NonNull @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public java.util.List<android.telecom.PhoneAccountHandle> getCallCapablePhoneAccounts(boolean);
- method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public int getCurrentTtyMode();
- method @Nullable @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public String getDefaultDialerPackage(@NonNull android.os.UserHandle);
- method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public boolean isInEmergencyCall();
- method @RequiresPermission(anyOf={android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE, android.Manifest.permission.READ_PHONE_STATE}) public boolean isRinging();
- method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setUserSelectedOutgoingPhoneAccount(@Nullable android.telecom.PhoneAccountHandle);
- field public static final String ACTION_CURRENT_TTY_MODE_CHANGED = "android.telecom.action.CURRENT_TTY_MODE_CHANGED";
- field public static final String ACTION_TTY_PREFERRED_MODE_CHANGED = "android.telecom.action.TTY_PREFERRED_MODE_CHANGED";
- field public static final String EXTRA_CURRENT_TTY_MODE = "android.telecom.extra.CURRENT_TTY_MODE";
- field public static final String EXTRA_TTY_PREFERRED_MODE = "android.telecom.extra.TTY_PREFERRED_MODE";
- field public static final int TTY_MODE_FULL = 1; // 0x1
- field public static final int TTY_MODE_HCO = 2; // 0x2
- field public static final int TTY_MODE_OFF = 0; // 0x0
- field public static final int TTY_MODE_VCO = 3; // 0x3
- }
-
}
package android.telephony {
- public final class AccessNetworkConstants {
- field public static final int TRANSPORT_TYPE_INVALID = -1; // 0xffffffff
- }
-
- public static final class AccessNetworkConstants.NgranBands {
- method public static int getFrequencyRangeGroup(int);
- field public static final int FREQUENCY_RANGE_GROUP_1 = 1; // 0x1
- field public static final int FREQUENCY_RANGE_GROUP_2 = 2; // 0x2
- field public static final int FREQUENCY_RANGE_GROUP_UNKNOWN = 0; // 0x0
- }
-
public final class BarringInfo implements android.os.Parcelable {
- ctor public BarringInfo();
ctor public BarringInfo(@Nullable android.telephony.CellIdentity, @NonNull android.util.SparseArray<android.telephony.BarringInfo.BarringServiceInfo>);
}
@@ -4106,57 +1719,6 @@ package android.telephony {
ctor public BarringInfo.BarringServiceInfo(int, boolean, int, int);
}
- public final class CallQuality implements android.os.Parcelable {
- ctor public CallQuality(int, int, int, int, int, int, int, int, int, int, int);
- ctor public CallQuality(int, int, int, int, int, int, int, int, int, int, int, boolean, boolean, boolean);
- method public int describeContents();
- method public int getAverageRelativeJitter();
- method public int getAverageRoundTripTime();
- method public int getCallDuration();
- method public int getCodecType();
- method public int getDownlinkCallQualityLevel();
- method public int getMaxRelativeJitter();
- method public int getNumRtpPacketsNotReceived();
- method public int getNumRtpPacketsReceived();
- method public int getNumRtpPacketsTransmitted();
- method public int getNumRtpPacketsTransmittedLost();
- method public int getUplinkCallQualityLevel();
- method public boolean isIncomingSilenceDetectedAtCallSetup();
- method public boolean isOutgoingSilenceDetectedAtCallSetup();
- method public boolean isRtpInactivityDetected();
- method public void writeToParcel(android.os.Parcel, int);
- field public static final int CALL_QUALITY_BAD = 4; // 0x4
- field public static final int CALL_QUALITY_EXCELLENT = 0; // 0x0
- field public static final int CALL_QUALITY_FAIR = 2; // 0x2
- field public static final int CALL_QUALITY_GOOD = 1; // 0x1
- field public static final int CALL_QUALITY_NOT_AVAILABLE = 5; // 0x5
- field public static final int CALL_QUALITY_POOR = 3; // 0x3
- field @NonNull public static final android.os.Parcelable.Creator<android.telephony.CallQuality> CREATOR;
- }
-
- public class CarrierConfigManager {
- method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void overrideConfig(int, @Nullable android.os.PersistableBundle);
- }
-
- public final class DataSpecificRegistrationInfo implements android.os.Parcelable {
- method public int describeContents();
- method @NonNull public android.telephony.LteVopsSupportInfo getLteVopsSupportInfo();
- method public void writeToParcel(android.os.Parcel, int);
- field @NonNull public static final android.os.Parcelable.Creator<android.telephony.DataSpecificRegistrationInfo> CREATOR;
- }
-
- public final class LteVopsSupportInfo implements android.os.Parcelable {
- ctor public LteVopsSupportInfo(int, int);
- method public int describeContents();
- method public int getEmcBearerSupport();
- method public int getVopsSupport();
- method public void writeToParcel(android.os.Parcel, int);
- field @NonNull public static final android.os.Parcelable.Creator<android.telephony.LteVopsSupportInfo> CREATOR;
- field public static final int LTE_STATUS_NOT_AVAILABLE = 1; // 0x1
- field public static final int LTE_STATUS_NOT_SUPPORTED = 3; // 0x3
- field public static final int LTE_STATUS_SUPPORTED = 2; // 0x2
- }
-
public class MbmsDownloadSession implements java.lang.AutoCloseable {
field public static final String MBMS_DOWNLOAD_SERVICE_OVERRIDE_METADATA = "mbms-download-service-override";
}
@@ -4171,71 +1733,14 @@ package android.telephony {
public final class ModemActivityInfo implements android.os.Parcelable {
ctor public ModemActivityInfo(long, int, int, @NonNull int[], int);
- method public int describeContents();
- method @NonNull public android.telephony.ModemActivityInfo getDelta(@NonNull android.telephony.ModemActivityInfo);
- method public long getIdleTimeMillis();
- method public static int getNumTxPowerLevels();
- method public long getReceiveTimeMillis();
- method public long getSleepTimeMillis();
- method public long getTimestampMillis();
- method public long getTransmitDurationMillisAtPowerLevel(int);
- method @NonNull public android.util.Range<java.lang.Integer> getTransmitPowerRange(int);
method public boolean isValid();
- method public void writeToParcel(@NonNull android.os.Parcel, int);
- field @NonNull public static final android.os.Parcelable.Creator<android.telephony.ModemActivityInfo> CREATOR;
- field public static final int TX_POWER_LEVEL_0 = 0; // 0x0
- field public static final int TX_POWER_LEVEL_1 = 1; // 0x1
- field public static final int TX_POWER_LEVEL_2 = 2; // 0x2
- field public static final int TX_POWER_LEVEL_3 = 3; // 0x3
- field public static final int TX_POWER_LEVEL_4 = 4; // 0x4
- }
-
- public final class NetworkRegistrationInfo implements android.os.Parcelable {
- method @Nullable public android.telephony.DataSpecificRegistrationInfo getDataSpecificInfo();
- method public int getRegistrationState();
- method public int getRejectCause();
- method public int getRoamingType();
- method public boolean isEmergencyEnabled();
- method public void writeToParcel(android.os.Parcel, int);
- field public static final int REGISTRATION_STATE_DENIED = 3; // 0x3
- field public static final int REGISTRATION_STATE_HOME = 1; // 0x1
- field public static final int REGISTRATION_STATE_NOT_REGISTERED_OR_SEARCHING = 0; // 0x0
- field public static final int REGISTRATION_STATE_NOT_REGISTERED_SEARCHING = 2; // 0x2
- field public static final int REGISTRATION_STATE_ROAMING = 5; // 0x5
- field public static final int REGISTRATION_STATE_UNKNOWN = 4; // 0x4
- }
-
- public static final class NetworkRegistrationInfo.Builder {
- ctor public NetworkRegistrationInfo.Builder();
- method @NonNull public android.telephony.NetworkRegistrationInfo build();
- method @NonNull public android.telephony.NetworkRegistrationInfo.Builder setAccessNetworkTechnology(int);
- method @NonNull public android.telephony.NetworkRegistrationInfo.Builder setAvailableServices(@NonNull java.util.List<java.lang.Integer>);
- method @NonNull public android.telephony.NetworkRegistrationInfo.Builder setCellIdentity(@Nullable android.telephony.CellIdentity);
- method @NonNull public android.telephony.NetworkRegistrationInfo.Builder setDomain(int);
- method @NonNull public android.telephony.NetworkRegistrationInfo.Builder setEmergencyOnly(boolean);
- method @NonNull public android.telephony.NetworkRegistrationInfo.Builder setRegisteredPlmn(@Nullable String);
- method @NonNull public android.telephony.NetworkRegistrationInfo.Builder setRegistrationState(int);
- method @NonNull public android.telephony.NetworkRegistrationInfo.Builder setRejectCause(int);
- method @NonNull public android.telephony.NetworkRegistrationInfo.Builder setTransportType(int);
}
public class PhoneNumberUtils {
method public static int getMinMatchForTest();
- method @NonNull public static String getUsernameFromUriNumber(@NonNull String);
- method public static boolean isUriNumber(@Nullable String);
- method public static boolean isVoiceMailNumber(@NonNull android.content.Context, int, @Nullable String);
method public static void setMinMatchForTest(int);
}
- public class PhoneStateListener {
- method @Deprecated public void onOutgoingEmergencyCall(@NonNull android.telephony.emergency.EmergencyNumber);
- method public void onOutgoingEmergencyCall(@NonNull android.telephony.emergency.EmergencyNumber, int);
- method @Deprecated public void onOutgoingEmergencySms(@NonNull android.telephony.emergency.EmergencyNumber);
- method public void onOutgoingEmergencySms(@NonNull android.telephony.emergency.EmergencyNumber, int);
- field @RequiresPermission(android.Manifest.permission.READ_ACTIVE_EMERGENCY_SESSION) public static final int LISTEN_OUTGOING_EMERGENCY_CALL = 268435456; // 0x10000000
- field @RequiresPermission(android.Manifest.permission.READ_ACTIVE_EMERGENCY_SESSION) public static final int LISTEN_OUTGOING_EMERGENCY_SMS = 536870912; // 0x20000000
- }
-
public final class PreciseDataConnectionState implements android.os.Parcelable {
ctor @Deprecated public PreciseDataConnectionState(int, int, int, @NonNull String, @Nullable android.net.LinkProperties, int);
}
@@ -4261,44 +1766,16 @@ package android.telephony {
field public static final int SMS_CATEGORY_STANDARD_SHORT_CODE = 2; // 0x2
}
- public class SubscriptionManager {
- method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setDefaultVoiceSubscriptionId(int);
- field @NonNull public static final android.net.Uri ADVANCED_CALLING_ENABLED_CONTENT_URI;
- field @NonNull public static final android.net.Uri VT_ENABLED_CONTENT_URI;
- field @NonNull public static final android.net.Uri WFC_ENABLED_CONTENT_URI;
- field @NonNull public static final android.net.Uri WFC_MODE_CONTENT_URI;
- field @NonNull public static final android.net.Uri WFC_ROAMING_ENABLED_CONTENT_URI;
- field @NonNull public static final android.net.Uri WFC_ROAMING_MODE_CONTENT_URI;
- }
-
public class TelephonyManager {
method public int addDevicePolicyOverrideApn(@NonNull android.content.Context, @NonNull android.telephony.data.ApnSetting);
- method public int checkCarrierPrivilegesForPackage(String);
- method @Nullable @RequiresPermission(android.Manifest.permission.INTERACT_ACROSS_USERS) public android.content.ComponentName getAndUpdateDefaultRespondViaMessageApplication();
method public int getCarrierIdListVersion();
- method public java.util.List<java.lang.String> getCarrierPackageNamesForIntent(android.content.Intent);
- method @Nullable @RequiresPermission(android.Manifest.permission.INTERACT_ACROSS_USERS) public android.content.ComponentName getDefaultRespondViaMessageApplication();
method @NonNull public java.util.List<android.telephony.data.ApnSetting> getDevicePolicyOverrideApns(@NonNull android.content.Context);
- method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public int getEmergencyNumberDbVersion();
method @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE) public String getLine1AlphaTag();
method public android.util.Pair<java.lang.Integer,java.lang.Integer> getRadioHalVersion();
- method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public boolean isMobileDataPolicyEnabled(int);
method public boolean modifyDevicePolicyOverrideApn(@NonNull android.content.Context, int, @NonNull android.telephony.data.ApnSetting);
method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void refreshUiccProfile();
- method @RequiresPermission(android.Manifest.permission.READ_ACTIVE_EMERGENCY_SESSION) public void resetOtaEmergencyNumberDbFilePath();
method @Deprecated public void setCarrierTestOverride(String, String, String, String, String, String, String);
method public void setCarrierTestOverride(String, String, String, String, String, String, String, String, String);
- method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setMobileDataPolicyEnabledStatus(int, boolean);
- method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setSystemSelectionChannels(@NonNull java.util.List<android.telephony.RadioAccessSpecifier>, @NonNull java.util.concurrent.Executor, @NonNull java.util.function.Consumer<java.lang.Boolean>);
- method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setSystemSelectionChannels(@NonNull java.util.List<android.telephony.RadioAccessSpecifier>);
- method @RequiresPermission(android.Manifest.permission.READ_ACTIVE_EMERGENCY_SESSION) public void updateOtaEmergencyNumberDbFilePath(@NonNull android.os.ParcelFileDescriptor);
- field public static final int CARRIER_PRIVILEGE_STATUS_ERROR_LOADING_RULES = -2; // 0xfffffffe
- field public static final int CARRIER_PRIVILEGE_STATUS_HAS_ACCESS = 1; // 0x1
- field public static final int CARRIER_PRIVILEGE_STATUS_NO_ACCESS = 0; // 0x0
- field public static final int CARRIER_PRIVILEGE_STATUS_RULES_NOT_LOADED = -1; // 0xffffffff
- field public static final int INVALID_EMERGENCY_NUMBER_DB_VERSION = -1; // 0xffffffff
- field public static final int MOBILE_DATA_POLICY_DATA_ON_NON_DEFAULT_DURING_VOICE_CALL = 1; // 0x1
- field public static final int MOBILE_DATA_POLICY_MMS_ALWAYS_ALLOWED = 2; // 0x2
field public static final int UNKNOWN_CARRIER_ID_LIST_VERSION = -1; // 0xffffffff
}
@@ -4314,835 +1791,18 @@ package android.telephony.emergency {
package android.telephony.ims {
- public final class ImsCallForwardInfo implements android.os.Parcelable {
- ctor public ImsCallForwardInfo(int, int, int, int, @NonNull String, int);
- method public int describeContents();
- method public int getCondition();
- method public String getNumber();
- method public int getServiceClass();
- method public int getStatus();
- method public int getTimeSeconds();
- method public int getToA();
- method public void writeToParcel(android.os.Parcel, int);
- field public static final int CDIV_CF_REASON_ALL = 4; // 0x4
- field public static final int CDIV_CF_REASON_ALL_CONDITIONAL = 5; // 0x5
- field public static final int CDIV_CF_REASON_BUSY = 1; // 0x1
- field public static final int CDIV_CF_REASON_NOT_LOGGED_IN = 6; // 0x6
- field public static final int CDIV_CF_REASON_NOT_REACHABLE = 3; // 0x3
- field public static final int CDIV_CF_REASON_NO_REPLY = 2; // 0x2
- field public static final int CDIV_CF_REASON_UNCONDITIONAL = 0; // 0x0
- field @NonNull public static final android.os.Parcelable.Creator<android.telephony.ims.ImsCallForwardInfo> CREATOR;
- field public static final int STATUS_ACTIVE = 1; // 0x1
- field public static final int STATUS_NOT_ACTIVE = 0; // 0x0
- field public static final int TYPE_OF_ADDRESS_INTERNATIONAL = 145; // 0x91
- field public static final int TYPE_OF_ADDRESS_UNKNOWN = 129; // 0x81
- }
-
public final class ImsCallProfile implements android.os.Parcelable {
- ctor public ImsCallProfile();
- ctor public ImsCallProfile(int, int);
- ctor public ImsCallProfile(int, int, android.os.Bundle, android.telephony.ims.ImsStreamMediaProfile);
- method public int describeContents();
- method public String getCallExtra(String);
- method public String getCallExtra(String, String);
- method public boolean getCallExtraBoolean(String);
- method public boolean getCallExtraBoolean(String, boolean);
- method public int getCallExtraInt(String);
- method public int getCallExtraInt(String, int);
- method public android.os.Bundle getCallExtras();
- method public int getCallType();
- method public static int getCallTypeFromVideoState(int);
- method public int getCallerNumberVerificationStatus();
- method public int getEmergencyCallRouting();
- method public int getEmergencyServiceCategories();
- method @NonNull public java.util.List<java.lang.String> getEmergencyUrns();
- method public android.telephony.ims.ImsStreamMediaProfile getMediaProfile();
- method @NonNull public android.os.Bundle getProprietaryCallExtras();
- method public int getRestrictCause();
- method public int getServiceType();
- method public static int getVideoStateFromCallType(int);
- method public static int getVideoStateFromImsCallProfile(android.telephony.ims.ImsCallProfile);
- method public boolean hasKnownUserIntentEmergency();
- method public boolean isEmergencyCallTesting();
- method public boolean isVideoCall();
- method public boolean isVideoPaused();
- method public static int presentationToOir(int);
- method public void setCallExtra(String, String);
- method public void setCallExtraBoolean(String, boolean);
- method public void setCallExtraInt(String, int);
- method public void setCallRestrictCause(int);
- method public void setCallerNumberVerificationStatus(int);
- method public void setEmergencyCallRouting(int);
- method public void setEmergencyCallTesting(boolean);
- method public void setEmergencyServiceCategories(int);
- method public void setEmergencyUrns(@NonNull java.util.List<java.lang.String>);
- method public void setHasKnownUserIntentEmergency(boolean);
- method public void updateCallExtras(android.telephony.ims.ImsCallProfile);
- method public void updateCallType(android.telephony.ims.ImsCallProfile);
- method public void updateMediaProfile(android.telephony.ims.ImsCallProfile);
- method public void writeToParcel(android.os.Parcel, int);
- field public static final int CALL_RESTRICT_CAUSE_DISABLED = 2; // 0x2
- field public static final int CALL_RESTRICT_CAUSE_HD = 3; // 0x3
- field public static final int CALL_RESTRICT_CAUSE_NONE = 0; // 0x0
- field public static final int CALL_RESTRICT_CAUSE_RAT = 1; // 0x1
- field public static final int CALL_TYPE_VIDEO_N_VOICE = 3; // 0x3
- field public static final int CALL_TYPE_VOICE = 2; // 0x2
- field public static final int CALL_TYPE_VOICE_N_VIDEO = 1; // 0x1
- field public static final int CALL_TYPE_VS = 8; // 0x8
- field public static final int CALL_TYPE_VS_RX = 10; // 0xa
- field public static final int CALL_TYPE_VS_TX = 9; // 0x9
- field public static final int CALL_TYPE_VT = 4; // 0x4
- field public static final int CALL_TYPE_VT_NODIR = 7; // 0x7
- field public static final int CALL_TYPE_VT_RX = 6; // 0x6
- field public static final int CALL_TYPE_VT_TX = 5; // 0x5
- field @NonNull public static final android.os.Parcelable.Creator<android.telephony.ims.ImsCallProfile> CREATOR;
- field public static final int DIALSTRING_NORMAL = 0; // 0x0
- field public static final int DIALSTRING_SS_CONF = 1; // 0x1
- field public static final int DIALSTRING_USSD = 2; // 0x2
- field public static final String EXTRA_ADDITIONAL_CALL_INFO = "AdditionalCallInfo";
- field public static final String EXTRA_ADDITIONAL_SIP_INVITE_FIELDS = "android.telephony.ims.extra.ADDITIONAL_SIP_INVITE_FIELDS";
- field public static final String EXTRA_CALL_DISCONNECT_CAUSE = "android.telephony.ims.extra.CALL_DISCONNECT_CAUSE";
- field public static final String EXTRA_CALL_NETWORK_TYPE = "android.telephony.ims.extra.CALL_NETWORK_TYPE";
- field @Deprecated public static final String EXTRA_CALL_RAT_TYPE = "CallRadioTech";
- field public static final String EXTRA_CHILD_NUMBER = "ChildNum";
- field public static final String EXTRA_CNA = "cna";
- field public static final String EXTRA_CNAP = "cnap";
- field public static final String EXTRA_CODEC = "Codec";
- field public static final String EXTRA_DIALSTRING = "dialstring";
- field public static final String EXTRA_DISPLAY_TEXT = "DisplayText";
- field public static final String EXTRA_EMERGENCY_CALL = "e_call";
- field public static final String EXTRA_FORWARDED_NUMBER = "android.telephony.ims.extra.FORWARDED_NUMBER";
- field public static final String EXTRA_IS_CALL_PULL = "CallPull";
field public static final String EXTRA_OEM_EXTRAS = "android.telephony.ims.extra.OEM_EXTRAS";
- field public static final String EXTRA_OI = "oi";
- field public static final String EXTRA_OIR = "oir";
- field public static final String EXTRA_REMOTE_URI = "remote_uri";
- field public static final String EXTRA_USSD = "ussd";
- field public static final int OIR_DEFAULT = 0; // 0x0
- field public static final int OIR_PRESENTATION_NOT_RESTRICTED = 2; // 0x2
- field public static final int OIR_PRESENTATION_PAYPHONE = 4; // 0x4
- field public static final int OIR_PRESENTATION_RESTRICTED = 1; // 0x1
- field public static final int OIR_PRESENTATION_UNKNOWN = 3; // 0x3
- field public static final int SERVICE_TYPE_EMERGENCY = 2; // 0x2
- field public static final int SERVICE_TYPE_NONE = 0; // 0x0
- field public static final int SERVICE_TYPE_NORMAL = 1; // 0x1
- field public static final int VERIFICATION_STATUS_FAILED = 2; // 0x2
- field public static final int VERIFICATION_STATUS_NOT_VERIFIED = 0; // 0x0
- field public static final int VERIFICATION_STATUS_PASSED = 1; // 0x1
- }
-
- public class ImsCallSessionListener {
- method public void callQualityChanged(@NonNull android.telephony.CallQuality);
- method public void callSessionConferenceExtendFailed(android.telephony.ims.ImsReasonInfo);
- method public void callSessionConferenceExtendReceived(android.telephony.ims.stub.ImsCallSessionImplBase, android.telephony.ims.ImsCallProfile);
- method public void callSessionConferenceExtended(android.telephony.ims.stub.ImsCallSessionImplBase, android.telephony.ims.ImsCallProfile);
- method public void callSessionConferenceStateUpdated(android.telephony.ims.ImsConferenceState);
- method @Deprecated public void callSessionHandover(int, int, android.telephony.ims.ImsReasonInfo);
- method @Deprecated public void callSessionHandoverFailed(int, int, android.telephony.ims.ImsReasonInfo);
- method public void callSessionHeld(android.telephony.ims.ImsCallProfile);
- method public void callSessionHoldFailed(android.telephony.ims.ImsReasonInfo);
- method public void callSessionHoldReceived(android.telephony.ims.ImsCallProfile);
- method public void callSessionInitiated(android.telephony.ims.ImsCallProfile);
- method public void callSessionInitiatedFailed(android.telephony.ims.ImsReasonInfo);
- method public void callSessionInviteParticipantsRequestDelivered();
- method public void callSessionInviteParticipantsRequestFailed(android.telephony.ims.ImsReasonInfo);
- method @Deprecated public void callSessionMayHandover(int, int);
- method public void callSessionMergeComplete(android.telephony.ims.stub.ImsCallSessionImplBase);
- method public void callSessionMergeFailed(android.telephony.ims.ImsReasonInfo);
- method public void callSessionMergeStarted(android.telephony.ims.stub.ImsCallSessionImplBase, android.telephony.ims.ImsCallProfile);
- method public void callSessionMultipartyStateChanged(boolean);
- method public void callSessionProgressing(android.telephony.ims.ImsStreamMediaProfile);
- method public void callSessionRemoveParticipantsRequestDelivered();
- method public void callSessionRemoveParticipantsRequestFailed(android.telephony.ims.ImsReasonInfo);
- method public void callSessionResumeFailed(android.telephony.ims.ImsReasonInfo);
- method public void callSessionResumeReceived(android.telephony.ims.ImsCallProfile);
- method public void callSessionResumed(android.telephony.ims.ImsCallProfile);
- method public void callSessionRttAudioIndicatorChanged(@NonNull android.telephony.ims.ImsStreamMediaProfile);
- method public void callSessionRttMessageReceived(String);
- method public void callSessionRttModifyRequestReceived(android.telephony.ims.ImsCallProfile);
- method public void callSessionRttModifyResponseReceived(int);
- method public void callSessionSuppServiceReceived(android.telephony.ims.ImsSuppServiceNotification);
- method public void callSessionTerminated(android.telephony.ims.ImsReasonInfo);
- method public void callSessionTtyModeReceived(int);
- method public void callSessionUpdateFailed(android.telephony.ims.ImsReasonInfo);
- method public void callSessionUpdateReceived(android.telephony.ims.ImsCallProfile);
- method public void callSessionUpdated(android.telephony.ims.ImsCallProfile);
- method public void callSessionUssdMessageReceived(int, String);
- method public void onHandover(int, int, @Nullable android.telephony.ims.ImsReasonInfo);
- method public void onHandoverFailed(int, int, @NonNull android.telephony.ims.ImsReasonInfo);
- method public void onMayHandover(int, int);
- }
-
- public final class ImsConferenceState implements android.os.Parcelable {
- method public int describeContents();
- method public static int getConnectionStateForStatus(String);
- method public void writeToParcel(android.os.Parcel, int);
- field @NonNull public static final android.os.Parcelable.Creator<android.telephony.ims.ImsConferenceState> CREATOR;
- field public static final String DISPLAY_TEXT = "display-text";
- field public static final String ENDPOINT = "endpoint";
- field public static final String SIP_STATUS_CODE = "sipstatuscode";
- field public static final String STATUS = "status";
- field public static final String STATUS_ALERTING = "alerting";
- field public static final String STATUS_CONNECTED = "connected";
- field public static final String STATUS_CONNECT_FAIL = "connect-fail";
- field public static final String STATUS_DIALING_IN = "dialing-in";
- field public static final String STATUS_DIALING_OUT = "dialing-out";
- field public static final String STATUS_DISCONNECTED = "disconnected";
- field public static final String STATUS_DISCONNECTING = "disconnecting";
- field public static final String STATUS_MUTED_VIA_FOCUS = "muted-via-focus";
- field public static final String STATUS_ON_HOLD = "on-hold";
- field public static final String STATUS_PENDING = "pending";
- field public static final String STATUS_SEND_ONLY = "sendonly";
- field public static final String STATUS_SEND_RECV = "sendrecv";
- field public static final String USER = "user";
- field public final java.util.HashMap<java.lang.String,android.os.Bundle> mParticipants;
- }
-
- public final class ImsException extends java.lang.Exception {
- ctor public ImsException(@Nullable String);
- ctor public ImsException(@Nullable String, int);
- ctor public ImsException(@Nullable String, int, @Nullable Throwable);
- }
-
- public final class ImsExternalCallState implements android.os.Parcelable {
- ctor public ImsExternalCallState(@NonNull String, @NonNull android.net.Uri, @Nullable android.net.Uri, boolean, int, int, boolean);
- method public int describeContents();
- method @NonNull public android.net.Uri getAddress();
- method public int getCallId();
- method public int getCallState();
- method public int getCallType();
- method @Nullable public android.net.Uri getLocalAddress();
- method public boolean isCallHeld();
- method public boolean isCallPullable();
- method public void writeToParcel(android.os.Parcel, int);
- field public static final int CALL_STATE_CONFIRMED = 1; // 0x1
- field public static final int CALL_STATE_TERMINATED = 2; // 0x2
- field @NonNull public static final android.os.Parcelable.Creator<android.telephony.ims.ImsExternalCallState> CREATOR;
- }
-
- public class ImsMmTelManager implements android.telephony.ims.RegistrationManager {
- method @Deprecated @NonNull @RequiresPermission(anyOf={android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE, android.Manifest.permission.READ_PRECISE_PHONE_STATE}) public static android.telephony.ims.ImsMmTelManager createForSubscriptionId(int);
- method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public void getFeatureState(@NonNull java.util.concurrent.Executor, @NonNull java.util.function.Consumer<java.lang.Integer>) throws android.telephony.ims.ImsException;
- method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public void getRegistrationState(@NonNull java.util.concurrent.Executor, @NonNull java.util.function.Consumer<java.lang.Integer>);
- method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public int getVoWiFiRoamingModeSetting();
- method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public boolean isAvailable(int, int);
- method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public boolean isCapable(int, int);
- method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public void isSupported(int, int, @NonNull java.util.concurrent.Executor, @NonNull java.util.function.Consumer<java.lang.Boolean>) throws android.telephony.ims.ImsException;
- method @Deprecated @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public void registerImsRegistrationCallback(@NonNull java.util.concurrent.Executor, @NonNull android.telephony.ims.ImsMmTelManager.RegistrationCallback) throws android.telephony.ims.ImsException;
- method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setAdvancedCallingSettingEnabled(boolean);
- method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setRttCapabilitySetting(boolean);
- method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setVoWiFiModeSetting(int);
- method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setVoWiFiNonPersistent(boolean, int);
- method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setVoWiFiRoamingModeSetting(int);
- method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setVoWiFiRoamingSettingEnabled(boolean);
- method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setVoWiFiSettingEnabled(boolean);
- method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setVtSettingEnabled(boolean);
- method @Deprecated @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public void unregisterImsRegistrationCallback(@NonNull android.telephony.ims.ImsMmTelManager.RegistrationCallback);
- }
-
- @Deprecated public static class ImsMmTelManager.RegistrationCallback extends android.telephony.ims.RegistrationManager.RegistrationCallback {
- ctor @Deprecated public ImsMmTelManager.RegistrationCallback();
- }
-
- public class ImsService extends android.app.Service {
- ctor public ImsService();
- method public android.telephony.ims.feature.MmTelFeature createMmTelFeature(int);
- method public android.telephony.ims.feature.RcsFeature createRcsFeature(int);
- method public void disableIms(int);
- method public void enableIms(int);
- method public android.telephony.ims.stub.ImsConfigImplBase getConfig(int);
- method public android.telephony.ims.stub.ImsRegistrationImplBase getRegistration(int);
- method public final void onUpdateSupportedImsFeatures(android.telephony.ims.stub.ImsFeatureConfiguration) throws android.os.RemoteException;
- method public android.telephony.ims.stub.ImsFeatureConfiguration querySupportedImsFeatures();
- method public void readyForFeatureCreation();
- }
-
- public final class ImsSsData implements android.os.Parcelable {
- ctor public ImsSsData(int, int, int, int, int);
- method public int describeContents();
- method @Nullable public java.util.List<android.telephony.ims.ImsCallForwardInfo> getCallForwardInfo();
- method public int getRequestType();
- method public int getResult();
- method public int getServiceClass();
- method public int getServiceType();
- method @NonNull public java.util.List<android.telephony.ims.ImsSsInfo> getSuppServiceInfo();
- method public int getTeleserviceType();
- method public boolean isTypeBarring();
- method public boolean isTypeCf();
- method public boolean isTypeClip();
- method public boolean isTypeClir();
- method public boolean isTypeColp();
- method public boolean isTypeColr();
- method public boolean isTypeCw();
- method public boolean isTypeIcb();
- method public boolean isTypeInterrogation();
- method public boolean isTypeUnConditional();
- method public void writeToParcel(android.os.Parcel, int);
- field @NonNull public static final android.os.Parcelable.Creator<android.telephony.ims.ImsSsData> CREATOR;
- field public static final int RESULT_SUCCESS = 0; // 0x0
- field public static final int SERVICE_CLASS_DATA = 2; // 0x2
- field public static final int SERVICE_CLASS_DATA_CIRCUIT_ASYNC = 32; // 0x20
- field public static final int SERVICE_CLASS_DATA_CIRCUIT_SYNC = 16; // 0x10
- field public static final int SERVICE_CLASS_DATA_PACKET_ACCESS = 64; // 0x40
- field public static final int SERVICE_CLASS_DATA_PAD = 128; // 0x80
- field public static final int SERVICE_CLASS_FAX = 4; // 0x4
- field public static final int SERVICE_CLASS_NONE = 0; // 0x0
- field public static final int SERVICE_CLASS_SMS = 8; // 0x8
- field public static final int SERVICE_CLASS_VOICE = 1; // 0x1
- field public static final int SS_ACTIVATION = 0; // 0x0
- field public static final int SS_ALL_BARRING = 18; // 0x12
- field public static final int SS_ALL_DATA_TELESERVICES = 3; // 0x3
- field public static final int SS_ALL_TELESERVICES_EXCEPT_SMS = 5; // 0x5
- field public static final int SS_ALL_TELESEVICES = 1; // 0x1
- field public static final int SS_ALL_TELE_AND_BEARER_SERVICES = 0; // 0x0
- field public static final int SS_BAIC = 16; // 0x10
- field public static final int SS_BAIC_ROAMING = 17; // 0x11
- field public static final int SS_BAOC = 13; // 0xd
- field public static final int SS_BAOIC = 14; // 0xe
- field public static final int SS_BAOIC_EXC_HOME = 15; // 0xf
- field public static final int SS_CFU = 0; // 0x0
- field public static final int SS_CFUT = 6; // 0x6
- field public static final int SS_CF_ALL = 4; // 0x4
- field public static final int SS_CF_ALL_CONDITIONAL = 5; // 0x5
- field public static final int SS_CF_BUSY = 1; // 0x1
- field public static final int SS_CF_NOT_REACHABLE = 3; // 0x3
- field public static final int SS_CF_NO_REPLY = 2; // 0x2
- field public static final int SS_CLIP = 7; // 0x7
- field public static final int SS_CLIR = 8; // 0x8
- field public static final int SS_CNAP = 11; // 0xb
- field public static final int SS_COLP = 9; // 0x9
- field public static final int SS_COLR = 10; // 0xa
- field public static final int SS_DEACTIVATION = 1; // 0x1
- field public static final int SS_ERASURE = 4; // 0x4
- field public static final int SS_INCOMING_BARRING = 20; // 0x14
- field public static final int SS_INCOMING_BARRING_ANONYMOUS = 22; // 0x16
- field public static final int SS_INCOMING_BARRING_DN = 21; // 0x15
- field public static final int SS_INTERROGATION = 2; // 0x2
- field public static final int SS_OUTGOING_BARRING = 19; // 0x13
- field public static final int SS_REGISTRATION = 3; // 0x3
- field public static final int SS_SMS_SERVICES = 4; // 0x4
- field public static final int SS_TELEPHONY = 2; // 0x2
- field public static final int SS_WAIT = 12; // 0xc
- }
-
- public static final class ImsSsData.Builder {
- ctor public ImsSsData.Builder(int, int, int, int, int);
- method @NonNull public android.telephony.ims.ImsSsData build();
- method @NonNull public android.telephony.ims.ImsSsData.Builder setCallForwardingInfo(@NonNull java.util.List<android.telephony.ims.ImsCallForwardInfo>);
- method @NonNull public android.telephony.ims.ImsSsData.Builder setSuppServiceInfo(@NonNull java.util.List<android.telephony.ims.ImsSsInfo>);
- }
-
- public final class ImsSsInfo implements android.os.Parcelable {
- ctor @Deprecated public ImsSsInfo(int, @Nullable String);
- method public int describeContents();
- method public int getClirInterrogationStatus();
- method public int getClirOutgoingState();
- method @Deprecated public String getIcbNum();
- method @Nullable public String getIncomingCommunicationBarringNumber();
- method public int getProvisionStatus();
- method public int getStatus();
- method public void writeToParcel(android.os.Parcel, int);
- field public static final int CLIR_OUTGOING_DEFAULT = 0; // 0x0
- field public static final int CLIR_OUTGOING_INVOCATION = 1; // 0x1
- field public static final int CLIR_OUTGOING_SUPPRESSION = 2; // 0x2
- field public static final int CLIR_STATUS_NOT_PROVISIONED = 0; // 0x0
- field public static final int CLIR_STATUS_PROVISIONED_PERMANENT = 1; // 0x1
- field public static final int CLIR_STATUS_TEMPORARILY_ALLOWED = 4; // 0x4
- field public static final int CLIR_STATUS_TEMPORARILY_RESTRICTED = 3; // 0x3
- field public static final int CLIR_STATUS_UNKNOWN = 2; // 0x2
- field @NonNull public static final android.os.Parcelable.Creator<android.telephony.ims.ImsSsInfo> CREATOR;
- field public static final int DISABLED = 0; // 0x0
- field public static final int ENABLED = 1; // 0x1
- field public static final int NOT_REGISTERED = -1; // 0xffffffff
- field public static final int SERVICE_NOT_PROVISIONED = 0; // 0x0
- field public static final int SERVICE_PROVISIONED = 1; // 0x1
- field public static final int SERVICE_PROVISIONING_UNKNOWN = -1; // 0xffffffff
- }
-
- public static final class ImsSsInfo.Builder {
- ctor public ImsSsInfo.Builder(int);
- method @NonNull public android.telephony.ims.ImsSsInfo build();
- method @NonNull public android.telephony.ims.ImsSsInfo.Builder setClirInterrogationStatus(int);
- method @NonNull public android.telephony.ims.ImsSsInfo.Builder setClirOutgoingState(int);
- method @NonNull public android.telephony.ims.ImsSsInfo.Builder setIncomingCommunicationBarringNumber(@NonNull String);
- method @NonNull public android.telephony.ims.ImsSsInfo.Builder setProvisionStatus(int);
- }
-
- public final class ImsStreamMediaProfile implements android.os.Parcelable {
- ctor public ImsStreamMediaProfile(int, int, int, int, int);
- method public void copyFrom(android.telephony.ims.ImsStreamMediaProfile);
- method public int describeContents();
- method public int getAudioDirection();
- method public int getAudioQuality();
- method public int getRttMode();
- method public int getVideoDirection();
- method public int getVideoQuality();
- method public boolean isReceivingRttAudio();
- method public boolean isRttCall();
- method public void setReceivingRttAudio(boolean);
- method public void setRttMode(int);
- method public void writeToParcel(android.os.Parcel, int);
- field public static final int AUDIO_QUALITY_AMR = 1; // 0x1
- field public static final int AUDIO_QUALITY_AMR_WB = 2; // 0x2
- field public static final int AUDIO_QUALITY_EVRC = 4; // 0x4
- field public static final int AUDIO_QUALITY_EVRC_B = 5; // 0x5
- field public static final int AUDIO_QUALITY_EVRC_NW = 7; // 0x7
- field public static final int AUDIO_QUALITY_EVRC_WB = 6; // 0x6
- field public static final int AUDIO_QUALITY_EVS_FB = 20; // 0x14
- field public static final int AUDIO_QUALITY_EVS_NB = 17; // 0x11
- field public static final int AUDIO_QUALITY_EVS_SWB = 19; // 0x13
- field public static final int AUDIO_QUALITY_EVS_WB = 18; // 0x12
- field public static final int AUDIO_QUALITY_G711A = 13; // 0xd
- field public static final int AUDIO_QUALITY_G711AB = 15; // 0xf
- field public static final int AUDIO_QUALITY_G711U = 11; // 0xb
- field public static final int AUDIO_QUALITY_G722 = 14; // 0xe
- field public static final int AUDIO_QUALITY_G723 = 12; // 0xc
- field public static final int AUDIO_QUALITY_G729 = 16; // 0x10
- field public static final int AUDIO_QUALITY_GSM_EFR = 8; // 0x8
- field public static final int AUDIO_QUALITY_GSM_FR = 9; // 0x9
- field public static final int AUDIO_QUALITY_GSM_HR = 10; // 0xa
- field public static final int AUDIO_QUALITY_NONE = 0; // 0x0
- field public static final int AUDIO_QUALITY_QCELP13K = 3; // 0x3
- field @NonNull public static final android.os.Parcelable.Creator<android.telephony.ims.ImsStreamMediaProfile> CREATOR;
- field public static final int DIRECTION_INACTIVE = 0; // 0x0
- field public static final int DIRECTION_INVALID = -1; // 0xffffffff
- field public static final int DIRECTION_RECEIVE = 1; // 0x1
- field public static final int DIRECTION_SEND = 2; // 0x2
- field public static final int DIRECTION_SEND_RECEIVE = 3; // 0x3
- field public static final int RTT_MODE_DISABLED = 0; // 0x0
- field public static final int RTT_MODE_FULL = 1; // 0x1
- field public static final int VIDEO_QUALITY_NONE = 0; // 0x0
- field public static final int VIDEO_QUALITY_QCIF = 1; // 0x1
- field public static final int VIDEO_QUALITY_QVGA_LANDSCAPE = 2; // 0x2
- field public static final int VIDEO_QUALITY_QVGA_PORTRAIT = 4; // 0x4
- field public static final int VIDEO_QUALITY_VGA_LANDSCAPE = 8; // 0x8
- field public static final int VIDEO_QUALITY_VGA_PORTRAIT = 16; // 0x10
- }
-
- public final class ImsSuppServiceNotification implements android.os.Parcelable {
- ctor public ImsSuppServiceNotification(int, int, int, int, String, String[]);
- method public int describeContents();
- method public void writeToParcel(android.os.Parcel, int);
- field @NonNull public static final android.os.Parcelable.Creator<android.telephony.ims.ImsSuppServiceNotification> CREATOR;
- field public final int code;
- field public final String[] history;
- field public final int index;
- field public final int notificationType;
- field public final String number;
- field public final int type;
- }
-
- public class ImsUtListener {
- method public void onLineIdentificationSupplementaryServiceResponse(int, @NonNull android.telephony.ims.ImsSsInfo);
- method public void onSupplementaryServiceIndication(android.telephony.ims.ImsSsData);
- method public void onUtConfigurationCallBarringQueried(int, android.telephony.ims.ImsSsInfo[]);
- method public void onUtConfigurationCallForwardQueried(int, android.telephony.ims.ImsCallForwardInfo[]);
- method public void onUtConfigurationCallWaitingQueried(int, android.telephony.ims.ImsSsInfo[]);
- method @Deprecated public void onUtConfigurationQueried(int, android.os.Bundle);
- method public void onUtConfigurationQueryFailed(int, android.telephony.ims.ImsReasonInfo);
- method public void onUtConfigurationUpdateFailed(int, android.telephony.ims.ImsReasonInfo);
- method public void onUtConfigurationUpdated(int);
- field @Deprecated public static final String BUNDLE_KEY_CLIR = "queryClir";
- field @Deprecated public static final String BUNDLE_KEY_SSINFO = "imsSsInfo";
- }
-
- public abstract class ImsVideoCallProvider {
- ctor public ImsVideoCallProvider();
- method public void changeCallDataUsage(long);
- method public void changeCameraCapabilities(android.telecom.VideoProfile.CameraCapabilities);
- method public void changePeerDimensions(int, int);
- method public void changeVideoQuality(int);
- method public void handleCallSessionEvent(int);
- method public abstract void onRequestCallDataUsage();
- method public abstract void onRequestCameraCapabilities();
- method public abstract void onSendSessionModifyRequest(android.telecom.VideoProfile, android.telecom.VideoProfile);
- method public abstract void onSendSessionModifyResponse(android.telecom.VideoProfile);
- method public abstract void onSetCamera(String);
- method public void onSetCamera(String, int);
- method public abstract void onSetDeviceOrientation(int);
- method public abstract void onSetDisplaySurface(android.view.Surface);
- method public abstract void onSetPauseImage(android.net.Uri);
- method public abstract void onSetPreviewSurface(android.view.Surface);
- method public abstract void onSetZoom(float);
- method public void receiveSessionModifyRequest(android.telecom.VideoProfile);
- method public void receiveSessionModifyResponse(int, android.telecom.VideoProfile, android.telecom.VideoProfile);
- }
-
- public class ProvisioningManager {
- method @NonNull public static android.telephony.ims.ProvisioningManager createForSubscriptionId(int);
- method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) @WorkerThread public int getProvisioningIntValue(int);
- method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) @WorkerThread public boolean getProvisioningStatusForCapability(int, int);
- method @Nullable @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) @WorkerThread public String getProvisioningStringValue(int);
- method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) @WorkerThread public boolean getRcsProvisioningStatusForCapability(int);
- method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void notifyRcsAutoConfigurationReceived(@NonNull byte[], boolean);
- method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public void registerProvisioningChangedCallback(@NonNull java.util.concurrent.Executor, @NonNull android.telephony.ims.ProvisioningManager.Callback) throws android.telephony.ims.ImsException;
- method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) @WorkerThread public int setProvisioningIntValue(int, int);
- method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) @WorkerThread public void setProvisioningStatusForCapability(int, int, boolean);
- method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) @WorkerThread public int setProvisioningStringValue(int, @NonNull String);
- method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) @WorkerThread public void setRcsProvisioningStatusForCapability(int, boolean);
- method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public void unregisterProvisioningChangedCallback(@NonNull android.telephony.ims.ProvisioningManager.Callback);
- field public static final int KEY_VOICE_OVER_WIFI_ENTITLEMENT_ID = 67; // 0x43
- field public static final int KEY_VOICE_OVER_WIFI_MODE_OVERRIDE = 27; // 0x1b
- field public static final int KEY_VOICE_OVER_WIFI_ROAMING_ENABLED_OVERRIDE = 26; // 0x1a
- field public static final int PROVISIONING_VALUE_DISABLED = 0; // 0x0
- field public static final int PROVISIONING_VALUE_ENABLED = 1; // 0x1
- field public static final String STRING_QUERY_RESULT_ERROR_GENERIC = "STRING_QUERY_RESULT_ERROR_GENERIC";
- field public static final String STRING_QUERY_RESULT_ERROR_NOT_READY = "STRING_QUERY_RESULT_ERROR_NOT_READY";
- }
-
- public static class ProvisioningManager.Callback {
- ctor public ProvisioningManager.Callback();
- method public void onProvisioningIntChanged(int, int);
- method public void onProvisioningStringChanged(int, @NonNull String);
- }
-
- public class RcsUceAdapter {
- method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setUceSettingEnabled(boolean) throws android.telephony.ims.ImsException;
}
}
package android.telephony.ims.feature {
- public final class CapabilityChangeRequest implements android.os.Parcelable {
- method public void addCapabilitiesToDisableForTech(int, int);
- method public void addCapabilitiesToEnableForTech(int, int);
- method public int describeContents();
- method public java.util.List<android.telephony.ims.feature.CapabilityChangeRequest.CapabilityPair> getCapabilitiesToDisable();
- method public java.util.List<android.telephony.ims.feature.CapabilityChangeRequest.CapabilityPair> getCapabilitiesToEnable();
- method public void writeToParcel(android.os.Parcel, int);
- field @NonNull public static final android.os.Parcelable.Creator<android.telephony.ims.feature.CapabilityChangeRequest> CREATOR;
- }
-
- public static class CapabilityChangeRequest.CapabilityPair {
- ctor public CapabilityChangeRequest.CapabilityPair(int, int);
- method public int getCapability();
- method public int getRadioTech();
- }
-
- public abstract class ImsFeature {
- ctor public ImsFeature();
- method public abstract void changeEnabledCapabilities(android.telephony.ims.feature.CapabilityChangeRequest, android.telephony.ims.feature.ImsFeature.CapabilityCallbackProxy);
- method public int getFeatureState();
- method public final int getSlotIndex();
- method public abstract void onFeatureReady();
- method public abstract void onFeatureRemoved();
- method public final void setFeatureState(int);
- field public static final int CAPABILITY_ERROR_GENERIC = -1; // 0xffffffff
- field public static final int CAPABILITY_SUCCESS = 0; // 0x0
- field public static final int FEATURE_EMERGENCY_MMTEL = 0; // 0x0
- field public static final int FEATURE_MMTEL = 1; // 0x1
- field public static final int FEATURE_RCS = 2; // 0x2
- field public static final int STATE_INITIALIZING = 1; // 0x1
- field public static final int STATE_READY = 2; // 0x2
- field public static final int STATE_UNAVAILABLE = 0; // 0x0
- }
-
@Deprecated public static class ImsFeature.Capabilities {
field @Deprecated protected int mCapabilities;
}
- protected static class ImsFeature.CapabilityCallbackProxy {
- method public void onChangeCapabilityConfigurationError(int, int, int);
- }
-
- public class MmTelFeature extends android.telephony.ims.feature.ImsFeature {
- ctor public MmTelFeature();
- method public void changeEnabledCapabilities(@NonNull android.telephony.ims.feature.CapabilityChangeRequest, @NonNull android.telephony.ims.feature.ImsFeature.CapabilityCallbackProxy);
- method @Nullable public android.telephony.ims.ImsCallProfile createCallProfile(int, int);
- method @Nullable public android.telephony.ims.stub.ImsCallSessionImplBase createCallSession(@NonNull android.telephony.ims.ImsCallProfile);
- method @NonNull public android.telephony.ims.stub.ImsEcbmImplBase getEcbm();
- method @NonNull public android.telephony.ims.stub.ImsMultiEndpointImplBase getMultiEndpoint();
- method @NonNull public android.telephony.ims.stub.ImsSmsImplBase getSmsImplementation();
- method @NonNull public android.telephony.ims.stub.ImsUtImplBase getUt();
- method public final void notifyCapabilitiesStatusChanged(@NonNull android.telephony.ims.feature.MmTelFeature.MmTelCapabilities);
- method public final void notifyIncomingCall(@NonNull android.telephony.ims.stub.ImsCallSessionImplBase, @NonNull android.os.Bundle);
- method public final void notifyRejectedCall(@NonNull android.telephony.ims.ImsCallProfile, @NonNull android.telephony.ims.ImsReasonInfo);
- method public final void notifyVoiceMessageCountUpdate(int);
- method public void onFeatureReady();
- method public void onFeatureRemoved();
- method public boolean queryCapabilityConfiguration(int, int);
- method @NonNull public final android.telephony.ims.feature.MmTelFeature.MmTelCapabilities queryCapabilityStatus();
- method public void setUiTtyMode(int, @Nullable android.os.Message);
- method public int shouldProcessCall(@NonNull String[]);
- field public static final String EXTRA_IS_UNKNOWN_CALL = "android.telephony.ims.feature.extra.IS_UNKNOWN_CALL";
- field public static final String EXTRA_IS_USSD = "android.telephony.ims.feature.extra.IS_USSD";
- field public static final int PROCESS_CALL_CSFB = 1; // 0x1
- field public static final int PROCESS_CALL_IMS = 0; // 0x0
- }
-
- public static class MmTelFeature.MmTelCapabilities extends android.telephony.ims.feature.ImsFeature.Capabilities {
- ctor public MmTelFeature.MmTelCapabilities();
- ctor @Deprecated public MmTelFeature.MmTelCapabilities(android.telephony.ims.feature.ImsFeature.Capabilities);
- ctor public MmTelFeature.MmTelCapabilities(int);
- method public final void addCapabilities(int);
- method public final void removeCapabilities(int);
- }
-
- public class RcsFeature extends android.telephony.ims.feature.ImsFeature {
- ctor public RcsFeature();
- method public void changeEnabledCapabilities(@NonNull android.telephony.ims.feature.CapabilityChangeRequest, @NonNull android.telephony.ims.feature.ImsFeature.CapabilityCallbackProxy);
- method public void onFeatureReady();
- method public void onFeatureRemoved();
- }
-
-}
-
-package android.telephony.ims.stub {
-
- public class ImsCallSessionImplBase implements java.lang.AutoCloseable {
- ctor public ImsCallSessionImplBase();
- method public void accept(int, android.telephony.ims.ImsStreamMediaProfile);
- method public void close();
- method public void deflect(String);
- method public void extendToConference(String[]);
- method public String getCallId();
- method public android.telephony.ims.ImsCallProfile getCallProfile();
- method public android.telephony.ims.ImsVideoCallProvider getImsVideoCallProvider();
- method public android.telephony.ims.ImsCallProfile getLocalCallProfile();
- method public String getProperty(String);
- method public android.telephony.ims.ImsCallProfile getRemoteCallProfile();
- method public int getState();
- method public void hold(android.telephony.ims.ImsStreamMediaProfile);
- method public void inviteParticipants(String[]);
- method public boolean isInCall();
- method public boolean isMultiparty();
- method public void merge();
- method public void reject(int);
- method public void removeParticipants(String[]);
- method public void resume(android.telephony.ims.ImsStreamMediaProfile);
- method public void sendDtmf(char, android.os.Message);
- method public void sendRttMessage(String);
- method public void sendRttModifyRequest(android.telephony.ims.ImsCallProfile);
- method public void sendRttModifyResponse(boolean);
- method public void sendUssd(String);
- method public void setListener(android.telephony.ims.ImsCallSessionListener);
- method public void setMute(boolean);
- method public void start(String, android.telephony.ims.ImsCallProfile);
- method public void startConference(String[], android.telephony.ims.ImsCallProfile);
- method public void startDtmf(char);
- method public void stopDtmf();
- method public void terminate(int);
- method public void update(int, android.telephony.ims.ImsStreamMediaProfile);
- field public static final int USSD_MODE_NOTIFY = 0; // 0x0
- field public static final int USSD_MODE_REQUEST = 1; // 0x1
- }
-
- public static class ImsCallSessionImplBase.State {
- method public static String toString(int);
- field public static final int ESTABLISHED = 4; // 0x4
- field public static final int ESTABLISHING = 3; // 0x3
- field public static final int IDLE = 0; // 0x0
- field public static final int INITIATED = 1; // 0x1
- field public static final int INVALID = -1; // 0xffffffff
- field public static final int NEGOTIATING = 2; // 0x2
- field public static final int REESTABLISHING = 6; // 0x6
- field public static final int RENEGOTIATING = 5; // 0x5
- field public static final int TERMINATED = 8; // 0x8
- field public static final int TERMINATING = 7; // 0x7
- }
-
- public class ImsConfigImplBase {
- ctor public ImsConfigImplBase();
- method public int getConfigInt(int);
- method public String getConfigString(int);
- method public final void notifyProvisionedValueChanged(int, int);
- method public final void notifyProvisionedValueChanged(int, String);
- method public void notifyRcsAutoConfigurationReceived(@NonNull byte[], boolean);
- method public int setConfig(int, int);
- method public int setConfig(int, String);
- field public static final int CONFIG_RESULT_FAILED = 1; // 0x1
- field public static final int CONFIG_RESULT_SUCCESS = 0; // 0x0
- field public static final int CONFIG_RESULT_UNKNOWN = -1; // 0xffffffff
- }
-
- public class ImsEcbmImplBase {
- ctor public ImsEcbmImplBase();
- method public final void enteredEcbm();
- method public void exitEmergencyCallbackMode();
- method public final void exitedEcbm();
- }
-
- public final class ImsFeatureConfiguration implements android.os.Parcelable {
- method public int describeContents();
- method public java.util.Set<android.telephony.ims.stub.ImsFeatureConfiguration.FeatureSlotPair> getServiceFeatures();
- method public void writeToParcel(android.os.Parcel, int);
- field @NonNull public static final android.os.Parcelable.Creator<android.telephony.ims.stub.ImsFeatureConfiguration> CREATOR;
- }
-
- public static class ImsFeatureConfiguration.Builder {
- ctor public ImsFeatureConfiguration.Builder();
- method public android.telephony.ims.stub.ImsFeatureConfiguration.Builder addFeature(int, int);
- method public android.telephony.ims.stub.ImsFeatureConfiguration build();
- }
-
- public static final class ImsFeatureConfiguration.FeatureSlotPair {
- ctor public ImsFeatureConfiguration.FeatureSlotPair(int, int);
- field public final int featureType;
- field public final int slotId;
- }
-
- public class ImsMultiEndpointImplBase {
- ctor public ImsMultiEndpointImplBase();
- method public final void onImsExternalCallStateUpdate(java.util.List<android.telephony.ims.ImsExternalCallState>);
- method public void requestImsExternalCallStateInfo();
- }
-
- public class ImsRegistrationImplBase {
- ctor public ImsRegistrationImplBase();
- method public final void onDeregistered(android.telephony.ims.ImsReasonInfo);
- method public final void onRegistered(int);
- method public final void onRegistering(int);
- method public final void onSubscriberAssociatedUriChanged(android.net.Uri[]);
- method public final void onTechnologyChangeFailed(int, android.telephony.ims.ImsReasonInfo);
- field public static final int REGISTRATION_TECH_IWLAN = 1; // 0x1
- field public static final int REGISTRATION_TECH_LTE = 0; // 0x0
- field public static final int REGISTRATION_TECH_NONE = -1; // 0xffffffff
- }
-
- public class ImsSmsImplBase {
- ctor public ImsSmsImplBase();
- method public void acknowledgeSms(int, @IntRange(from=0, to=65535) int, int);
- method public void acknowledgeSmsReport(int, @IntRange(from=0, to=65535) int, int);
- method public String getSmsFormat();
- method public void onReady();
- method @Deprecated public final void onSendSmsResult(int, @IntRange(from=0, to=65535) int, int, int) throws java.lang.RuntimeException;
- method public final void onSendSmsResultError(int, @IntRange(from=0, to=65535) int, int, int, int) throws java.lang.RuntimeException;
- method public final void onSendSmsResultSuccess(int, @IntRange(from=0, to=65535) int) throws java.lang.RuntimeException;
- method public final void onSmsReceived(int, String, byte[]) throws java.lang.RuntimeException;
- method @Deprecated public final void onSmsStatusReportReceived(int, @IntRange(from=0, to=65535) int, String, byte[]) throws java.lang.RuntimeException;
- method public final void onSmsStatusReportReceived(int, String, byte[]) throws java.lang.RuntimeException;
- method public void sendSms(int, @IntRange(from=0, to=65535) int, String, String, boolean, byte[]);
- field public static final int DELIVER_STATUS_ERROR_GENERIC = 2; // 0x2
- field public static final int DELIVER_STATUS_ERROR_NO_MEMORY = 3; // 0x3
- field public static final int DELIVER_STATUS_ERROR_REQUEST_NOT_SUPPORTED = 4; // 0x4
- field public static final int DELIVER_STATUS_OK = 1; // 0x1
- field public static final int RESULT_NO_NETWORK_ERROR = -1; // 0xffffffff
- field public static final int SEND_STATUS_ERROR = 2; // 0x2
- field public static final int SEND_STATUS_ERROR_FALLBACK = 4; // 0x4
- field public static final int SEND_STATUS_ERROR_RETRY = 3; // 0x3
- field public static final int SEND_STATUS_OK = 1; // 0x1
- field public static final int STATUS_REPORT_STATUS_ERROR = 2; // 0x2
- field public static final int STATUS_REPORT_STATUS_OK = 1; // 0x1
- }
-
- public class ImsUtImplBase {
- ctor public ImsUtImplBase();
- method public void close();
- method public int queryCallBarring(int);
- method public int queryCallBarringForServiceClass(int, int);
- method public int queryCallForward(int, String);
- method public int queryCallWaiting();
- method public int queryClip();
- method public int queryClir();
- method public int queryColp();
- method public int queryColr();
- method public void setListener(android.telephony.ims.ImsUtListener);
- method public int transact(android.os.Bundle);
- method public int updateCallBarring(int, int, String[]);
- method public int updateCallBarringForServiceClass(int, int, String[], int);
- method public int updateCallForward(int, int, String, int, int);
- method public int updateCallWaiting(boolean, int);
- method public int updateClip(boolean);
- method public int updateClir(int);
- method public int updateColp(boolean);
- method public int updateColr(int);
- }
-
-}
-
-package android.telephony.mbms {
-
- public static class DownloadRequest.Builder {
- method public android.telephony.mbms.DownloadRequest.Builder setServiceId(String);
- }
-
- public final class FileInfo implements android.os.Parcelable {
- ctor public FileInfo(android.net.Uri, String);
- }
-
- public final class FileServiceInfo extends android.telephony.mbms.ServiceInfo implements android.os.Parcelable {
- ctor public FileServiceInfo(java.util.Map<java.util.Locale,java.lang.String>, String, java.util.List<java.util.Locale>, String, java.util.Date, java.util.Date, java.util.List<android.telephony.mbms.FileInfo>);
- }
-
- public final class StreamingServiceInfo extends android.telephony.mbms.ServiceInfo implements android.os.Parcelable {
- ctor public StreamingServiceInfo(java.util.Map<java.util.Locale,java.lang.String>, String, java.util.List<java.util.Locale>, String, java.util.Date, java.util.Date);
- }
-
- public final class UriPathPair implements android.os.Parcelable {
- method public int describeContents();
- method public android.net.Uri getContentUri();
- method public android.net.Uri getFilePathUri();
- method public void writeToParcel(android.os.Parcel, int);
- field @NonNull public static final android.os.Parcelable.Creator<android.telephony.mbms.UriPathPair> CREATOR;
- }
-
-}
-
-package android.telephony.mbms.vendor {
-
- public class MbmsDownloadServiceBase extends android.os.Binder implements android.os.IInterface {
- ctor public MbmsDownloadServiceBase();
- method public int addProgressListener(android.telephony.mbms.DownloadRequest, android.telephony.mbms.DownloadProgressListener) throws android.os.RemoteException;
- method public int addServiceAnnouncement(int, @NonNull byte[]);
- method public int addStatusListener(android.telephony.mbms.DownloadRequest, android.telephony.mbms.DownloadStatusListener) throws android.os.RemoteException;
- method public android.os.IBinder asBinder();
- method public int cancelDownload(android.telephony.mbms.DownloadRequest) throws android.os.RemoteException;
- method public void dispose(int) throws android.os.RemoteException;
- method public int download(android.telephony.mbms.DownloadRequest) throws android.os.RemoteException;
- method public int initialize(int, android.telephony.mbms.MbmsDownloadSessionCallback) throws android.os.RemoteException;
- method @NonNull public java.util.List<android.telephony.mbms.DownloadRequest> listPendingDownloads(int) throws android.os.RemoteException;
- method public void onAppCallbackDied(int, int);
- method public boolean onTransact(int, android.os.Parcel, android.os.Parcel, int) throws android.os.RemoteException;
- method public int removeProgressListener(android.telephony.mbms.DownloadRequest, android.telephony.mbms.DownloadProgressListener) throws android.os.RemoteException;
- method public int removeStatusListener(android.telephony.mbms.DownloadRequest, android.telephony.mbms.DownloadStatusListener) throws android.os.RemoteException;
- method public int requestDownloadState(android.telephony.mbms.DownloadRequest, android.telephony.mbms.FileInfo) throws android.os.RemoteException;
- method public int requestUpdateFileServices(int, java.util.List<java.lang.String>) throws android.os.RemoteException;
- method public int resetDownloadKnowledge(android.telephony.mbms.DownloadRequest) throws android.os.RemoteException;
- method public int setTempFileRootDirectory(int, String) throws android.os.RemoteException;
- }
-
- public class MbmsGroupCallServiceBase extends android.app.Service {
- ctor public MbmsGroupCallServiceBase();
- method public void dispose(int) throws android.os.RemoteException;
- method public int initialize(@NonNull android.telephony.mbms.MbmsGroupCallSessionCallback, int) throws android.os.RemoteException;
- method public void onAppCallbackDied(int, int);
- method public android.os.IBinder onBind(android.content.Intent);
- method public int startGroupCall(int, long, @NonNull java.util.List<java.lang.Integer>, @NonNull java.util.List<java.lang.Integer>, @NonNull android.telephony.mbms.GroupCallCallback);
- method public void stopGroupCall(int, long);
- method public void updateGroupCall(int, long, @NonNull java.util.List<java.lang.Integer>, @NonNull java.util.List<java.lang.Integer>);
- }
-
- public class MbmsStreamingServiceBase extends android.os.Binder implements android.os.IInterface {
- ctor public MbmsStreamingServiceBase();
- method public android.os.IBinder asBinder();
- method public void dispose(int) throws android.os.RemoteException;
- method @Nullable public android.net.Uri getPlaybackUri(int, String) throws android.os.RemoteException;
- method public int initialize(android.telephony.mbms.MbmsStreamingSessionCallback, int) throws android.os.RemoteException;
- method public void onAppCallbackDied(int, int);
- method public boolean onTransact(int, android.os.Parcel, android.os.Parcel, int) throws android.os.RemoteException;
- method public int requestUpdateStreamingServices(int, java.util.List<java.lang.String>) throws android.os.RemoteException;
- method public int startStreaming(int, String, android.telephony.mbms.StreamingServiceCallback) throws android.os.RemoteException;
- method public void stopStreaming(int, String) throws android.os.RemoteException;
- }
-
- public class VendorUtils {
- ctor public VendorUtils();
- method public static android.content.ComponentName getAppReceiverFromPackageName(android.content.Context, String);
- field public static final String ACTION_CLEANUP = "android.telephony.mbms.action.CLEANUP";
- field public static final String ACTION_DOWNLOAD_RESULT_INTERNAL = "android.telephony.mbms.action.DOWNLOAD_RESULT_INTERNAL";
- field public static final String ACTION_FILE_DESCRIPTOR_REQUEST = "android.telephony.mbms.action.FILE_DESCRIPTOR_REQUEST";
- field public static final String EXTRA_FD_COUNT = "android.telephony.mbms.extra.FD_COUNT";
- field public static final String EXTRA_FINAL_URI = "android.telephony.mbms.extra.FINAL_URI";
- field public static final String EXTRA_FREE_URI_LIST = "android.telephony.mbms.extra.FREE_URI_LIST";
- field public static final String EXTRA_PAUSED_LIST = "android.telephony.mbms.extra.PAUSED_LIST";
- field public static final String EXTRA_PAUSED_URI_LIST = "android.telephony.mbms.extra.PAUSED_URI_LIST";
- field public static final String EXTRA_SERVICE_ID = "android.telephony.mbms.extra.SERVICE_ID";
- field public static final String EXTRA_TEMP_FILES_IN_USE = "android.telephony.mbms.extra.TEMP_FILES_IN_USE";
- field public static final String EXTRA_TEMP_FILE_ROOT = "android.telephony.mbms.extra.TEMP_FILE_ROOT";
- field public static final String EXTRA_TEMP_LIST = "android.telephony.mbms.extra.TEMP_LIST";
- }
-
}
package android.text {
@@ -5181,7 +1841,6 @@ package android.util {
field public static final String HEARING_AID_SETTINGS = "settings_bluetooth_hearing_aid";
field public static final String PERSIST_PREFIX = "persist.sys.fflag.override.";
field public static final String SCREENRECORD_LONG_PRESS = "settings_screenrecord_long_press";
- field public static final String SEAMLESS_TRANSFER = "settings_seamless_transfer";
field public static final String SETTINGS_WIFITRACKER2 = "settings_wifitracker2";
}
@@ -5396,10 +2055,7 @@ package android.view.accessibility {
public final class AccessibilityManager {
method public void addAccessibilityServicesStateChangeListener(@NonNull android.view.accessibility.AccessibilityManager.AccessibilityServicesStateChangeListener, @Nullable android.os.Handler);
method @NonNull @RequiresPermission(android.Manifest.permission.MANAGE_ACCESSIBILITY) public java.util.List<java.lang.String> getAccessibilityShortcutTargets(int);
- method @RequiresPermission(android.Manifest.permission.MANAGE_ACCESSIBILITY) public void performAccessibilityShortcut();
- method @RequiresPermission(android.Manifest.permission.MANAGE_ACCESSIBILITY) public void registerSystemAction(@NonNull android.app.RemoteAction, int);
method public void removeAccessibilityServicesStateChangeListener(@NonNull android.view.accessibility.AccessibilityManager.AccessibilityServicesStateChangeListener);
- method @RequiresPermission(android.Manifest.permission.MANAGE_ACCESSIBILITY) public void unregisterSystemAction(int);
}
public static interface AccessibilityManager.AccessibilityServicesStateChangeListener {
@@ -5445,7 +2101,6 @@ package android.view.autofill {
}
public final class AutofillManager {
- method public void setAugmentedAutofillWhitelist(@Nullable java.util.Set<java.lang.String>, @Nullable java.util.Set<android.content.ComponentName>);
field public static final String DEVICE_CONFIG_AUTOFILL_SMART_SUGGESTION_SUPPORTED_MODES = "smart_suggestion_supported_modes";
field public static final int FLAG_SMART_SUGGESTION_OFF = 0; // 0x0
field public static final int FLAG_SMART_SUGGESTION_SYSTEM = 1; // 0x1
@@ -5456,42 +2111,7 @@ package android.view.autofill {
package android.view.contentcapture {
- public final class ContentCaptureContext implements android.os.Parcelable {
- method @Nullable public android.content.ComponentName getActivityComponent();
- method public int getDisplayId();
- method public int getFlags();
- method @Nullable public android.view.contentcapture.ContentCaptureSessionId getParentSessionId();
- method public int getTaskId();
- field public static final int FLAG_DISABLED_BY_APP = 1; // 0x1
- field public static final int FLAG_DISABLED_BY_FLAG_SECURE = 2; // 0x2
- field public static final int FLAG_RECONNECTED = 4; // 0x4
- }
-
- public final class ContentCaptureEvent implements android.os.Parcelable {
- method public int describeContents();
- method @Nullable public android.view.contentcapture.ContentCaptureContext getContentCaptureContext();
- method public long getEventTime();
- method @Nullable public android.view.autofill.AutofillId getId();
- method @Nullable public java.util.List<android.view.autofill.AutofillId> getIds();
- method @Nullable public android.graphics.Insets getInsets();
- method @Nullable public CharSequence getText();
- method public int getType();
- method @Nullable public android.view.contentcapture.ViewNode getViewNode();
- method public void writeToParcel(android.os.Parcel, int);
- field @NonNull public static final android.os.Parcelable.Creator<android.view.contentcapture.ContentCaptureEvent> CREATOR;
- field public static final int TYPE_CONTEXT_UPDATED = 6; // 0x6
- field public static final int TYPE_SESSION_PAUSED = 8; // 0x8
- field public static final int TYPE_SESSION_RESUMED = 7; // 0x7
- field public static final int TYPE_VIEW_APPEARED = 1; // 0x1
- field public static final int TYPE_VIEW_DISAPPEARED = 2; // 0x2
- field public static final int TYPE_VIEW_INSETS_CHANGED = 9; // 0x9
- field public static final int TYPE_VIEW_TEXT_CHANGED = 3; // 0x3
- field public static final int TYPE_VIEW_TREE_APPEARED = 5; // 0x5
- field public static final int TYPE_VIEW_TREE_APPEARING = 4; // 0x4
- }
-
public final class ContentCaptureManager {
- method public boolean isContentCaptureFeatureEnabled();
field public static final String DEVICE_CONFIG_PROPERTY_IDLE_FLUSH_FREQUENCY = "idle_flush_frequency";
field public static final String DEVICE_CONFIG_PROPERTY_LOGGING_LEVEL = "logging_level";
field public static final String DEVICE_CONFIG_PROPERTY_LOG_HISTORY_SIZE = "log_history_size";
@@ -5504,7 +2124,6 @@ package android.view.contentcapture {
}
public final class ViewNode extends android.app.assist.AssistStructure.ViewNode {
- method @Nullable public android.view.autofill.AutofillId getParentAutofillId();
method @Nullable public static android.view.contentcapture.ViewNode readFromParcel(@NonNull android.os.Parcel);
method public static void writeToParcel(@NonNull android.os.Parcel, @Nullable android.view.contentcapture.ViewNode, int);
}
@@ -5753,7 +2372,7 @@ package android.window {
public class TaskOrganizer extends android.window.WindowOrganizer {
ctor public TaskOrganizer();
- method @Nullable @RequiresPermission(android.Manifest.permission.MANAGE_ACTIVITY_STACKS) public android.app.ActivityManager.RunningTaskInfo createRootTask(int, int);
+ method @Nullable @RequiresPermission(android.Manifest.permission.MANAGE_ACTIVITY_STACKS) public android.window.TaskAppearedInfo createRootTask(int, int);
method @RequiresPermission(android.Manifest.permission.MANAGE_ACTIVITY_STACKS) public boolean deleteRootTask(@NonNull android.window.WindowContainerToken);
method @Nullable @RequiresPermission(android.Manifest.permission.MANAGE_ACTIVITY_STACKS) public java.util.List<android.app.ActivityManager.RunningTaskInfo> getChildTasks(@NonNull android.window.WindowContainerToken, @NonNull int[]);
method @Nullable @RequiresPermission(android.Manifest.permission.MANAGE_ACTIVITY_STACKS) public android.window.WindowContainerToken getImeTarget(int);
diff --git a/api/test-removed.txt b/api/test-removed.txt
index e47f6edfbff1..d802177e249b 100644
--- a/api/test-removed.txt
+++ b/api/test-removed.txt
@@ -1,10 +1 @@
// Signature format: 2.0
-package android.app.prediction {
-
- public static final class AppTarget.Builder {
- method @Deprecated @NonNull public android.app.prediction.AppTarget.Builder setTarget(@NonNull String, @NonNull android.os.UserHandle);
- method @Deprecated @NonNull public android.app.prediction.AppTarget.Builder setTarget(@NonNull android.content.pm.ShortcutInfo);
- }
-
-}
-
diff --git a/cmds/idmap2/idmap2d/Idmap2Service.h b/cmds/idmap2/idmap2d/Idmap2Service.h
index 1a445192aff8..1d2090c431ae 100644
--- a/cmds/idmap2/idmap2d/Idmap2Service.h
+++ b/cmds/idmap2/idmap2d/Idmap2Service.h
@@ -22,6 +22,8 @@
#include <android-base/unique_fd.h>
#include <binder/BinderService.h>
+#include <string>
+
#include "android/os/BnIdmap2.h"
namespace android::os {
diff --git a/cmds/idmap2/include/idmap2/BinaryStreamVisitor.h b/cmds/idmap2/include/idmap2/BinaryStreamVisitor.h
index ff45b1407dea..bf31cbf8d4f7 100644
--- a/cmds/idmap2/include/idmap2/BinaryStreamVisitor.h
+++ b/cmds/idmap2/include/idmap2/BinaryStreamVisitor.h
@@ -36,12 +36,11 @@ class BinaryStreamVisitor : public Visitor {
void visit(const IdmapData::Header& header) override;
private:
- void Write(const void* value, size_t length);
void Write8(uint8_t value);
void Write16(uint16_t value);
void Write32(uint32_t value);
void WriteString256(const StringPiece& value);
- void WriteString(const std::string& value);
+ void WriteString(const StringPiece& value);
std::ostream& stream_;
};
diff --git a/cmds/idmap2/include/idmap2/Idmap.h b/cmds/idmap2/include/idmap2/Idmap.h
index 0f05592b70f3..a35fad9d686c 100644
--- a/cmds/idmap2/include/idmap2/Idmap.h
+++ b/cmds/idmap2/include/idmap2/Idmap.h
@@ -17,48 +17,45 @@
/*
* # idmap file format (current version)
*
- * idmap := header data*
- * header := magic version target_crc overlay_crc target_path overlay_path debug_info
- * data := data_header data_block*
- * data_header := target_package_id types_count
- * data_block := target_type overlay_type entry_count entry_offset entry*
- * overlay_path := string256
- * target_path := string256
- * debug_info := string
- * string := <uint32_t> <uint8_t>+ '\0'+
- * entry := <uint32_t>
- * entry_count := <uint16_t>
- * entry_offset := <uint16_t>
- * magic := <uint32_t>
- * overlay_crc := <uint32_t>
- * overlay_type := <uint16_t>
- * string256 := <uint8_t>[256]
- * target_crc := <uint32_t>
- * target_package_id := <uint16_t>
- * target_type := <uint16_t>
- * types_count := <uint16_t>
- * version := <uint32_t>
+ * idmap := header data*
+ * header := magic version target_crc overlay_crc fulfilled_policies
+ * enforce_overlayable target_path overlay_path debug_info
+ * data := data_header target_entry* target_inline_entry* overlay_entry*
+ * string_pool
+ * data_header := target_package_id overlay_package_id padding(2) target_entry_count
+ * target_inline_entry_count overlay_entry_count string_pool_index
+ * target_entry := target_id overlay_id
+ * target_inline_entry := target_id Res_value::size padding(1) Res_value::type
+ * Res_value::value
+ * overlay_entry := overlay_id target_id
*
- *
- * # idmap file format changelog
- * ## v1
- * - Identical to idmap v1.
- *
- * ## v2
- * - Entries are no longer separated by type into type specific data blocks.
- * - Added overlay-indexed target resource id lookup capabilities.
- * - Target and overlay entries are stored as a sparse array in the data block. The target entries
- * array maps from target resource id to overlay data type and value and the array is sorted by
- * target resource id. The overlay entries array maps from overlay resource id to target resource
- * id and the array is sorted by overlay resource id. It is important for both arrays to be sorted
- * to allow for O(log(number_of_overlaid_resources)) performance when looking up resource
- * mappings at runtime.
- * - Idmap can now encode a type and value to override a resource without needing a table entry.
- * - A string pool block is included to retrieve the value of strings that do not have a resource
- * table entry.
- *
- * ## v3
- * - Add 'debug' block to IdmapHeader.
+ * debug_info := string
+ * enforce_overlayable := <uint32_t>
+ * fulfilled_policies := <uint32_t>
+ * magic := <uint32_t>
+ * overlay_crc := <uint32_t>
+ * overlay_entry_count := <uint32_t>
+ * overlay_id := <uint32_t>
+ * overlay_package_id := <uint8_t>
+ * overlay_path := string256
+ * padding(n) := <uint8_t>[n]
+ * Res_value::size := <uint16_t>
+ * Res_value::type := <uint8_t>
+ * Res_value::value := <uint32_t>
+ * string := <uint32_t> <uint8_t>+ padding(n)
+ * string256 := <uint8_t>[256]
+ * string_pool := string
+ * string_pool_index := <uint32_t>
+ * string_pool_length := <uint32_t>
+ * target_crc := <uint32_t>
+ * target_entry_count := <uint32_t>
+ * target_inline_entry_count := <uint32_t>
+ * target_id := <uint32_t>
+ * target_package_id := <uint8_t>
+ * target_path := string256
+ * value_type := <uint8_t>
+ * value_data := <uint32_t>
+ * version := <uint32_t>
*/
#ifndef IDMAP2_INCLUDE_IDMAP2_IDMAP_H_
@@ -183,6 +180,10 @@ class IdmapData {
return target_entry_count;
}
+ inline uint32_t GetTargetInlineEntryCount() const {
+ return target_entry_inline_count;
+ }
+
inline uint32_t GetOverlayEntryCount() const {
return overlay_entry_count;
}
@@ -191,19 +192,15 @@ class IdmapData {
return string_pool_index_offset;
}
- inline uint32_t GetStringPoolLength() const {
- return string_pool_len;
- }
-
void accept(Visitor* v) const;
private:
PackageId target_package_id_;
PackageId overlay_package_id_;
uint32_t target_entry_count;
+ uint32_t target_entry_inline_count;
uint32_t overlay_entry_count;
uint32_t string_pool_index_offset;
- uint32_t string_pool_len;
Header() = default;
friend Idmap;
@@ -213,8 +210,12 @@ class IdmapData {
struct TargetEntry {
ResourceId target_id;
- TargetValue::DataType data_type;
- TargetValue::DataValue data_value;
+ ResourceId overlay_id;
+ };
+
+ struct TargetInlineEntry {
+ ResourceId target_id;
+ TargetValue value;
};
struct OverlayEntry {
@@ -227,20 +228,24 @@ class IdmapData {
static Result<std::unique_ptr<const IdmapData>> FromResourceMapping(
const ResourceMapping& resource_mapping);
- inline const std::unique_ptr<const Header>& GetHeader() const {
+ const std::unique_ptr<const Header>& GetHeader() const {
return header_;
}
- inline const std::vector<TargetEntry>& GetTargetEntries() const {
+ const std::vector<TargetEntry>& GetTargetEntries() const {
return target_entries_;
}
- inline const std::vector<OverlayEntry>& GetOverlayEntries() const {
+ const std::vector<TargetInlineEntry>& GetTargetInlineEntries() const {
+ return target_inline_entries_;
+ }
+
+ const std::vector<OverlayEntry>& GetOverlayEntries() const {
return overlay_entries_;
}
- inline const void* GetStringPoolData() const {
- return string_pool_.get();
+ const std::string& GetStringPoolData() const {
+ return string_pool_data_;
}
void accept(Visitor* v) const;
@@ -251,8 +256,9 @@ class IdmapData {
std::unique_ptr<const Header> header_;
std::vector<TargetEntry> target_entries_;
+ std::vector<TargetInlineEntry> target_inline_entries_;
std::vector<OverlayEntry> overlay_entries_;
- std::unique_ptr<uint8_t[]> string_pool_;
+ std::string string_pool_data_;
friend Idmap;
DISALLOW_COPY_AND_ASSIGN(IdmapData);
@@ -304,6 +310,10 @@ class Visitor {
virtual void visit(const IdmapData::Header& header) = 0;
};
+inline size_t CalculatePadding(size_t data_length) {
+ return (4 - (data_length % 4)) % 4;
+}
+
} // namespace android::idmap2
#endif // IDMAP2_INCLUDE_IDMAP2_IDMAP_H_
diff --git a/cmds/idmap2/include/idmap2/PrettyPrintVisitor.h b/cmds/idmap2/include/idmap2/PrettyPrintVisitor.h
index 5dcf217e2aa3..2b4c76124175 100644
--- a/cmds/idmap2/include/idmap2/PrettyPrintVisitor.h
+++ b/cmds/idmap2/include/idmap2/PrettyPrintVisitor.h
@@ -41,8 +41,9 @@ class PrettyPrintVisitor : public Visitor {
private:
std::ostream& stream_;
- std::unique_ptr<const ApkAssets> target_apk_;
AssetManager2 target_am_;
+ AssetManager2 overlay_am_;
+ std::vector<std::unique_ptr<const ApkAssets>> apk_assets_;
};
} // namespace idmap2
diff --git a/cmds/idmap2/include/idmap2/RawPrintVisitor.h b/cmds/idmap2/include/idmap2/RawPrintVisitor.h
index 92c186453611..58edc99715fd 100644
--- a/cmds/idmap2/include/idmap2/RawPrintVisitor.h
+++ b/cmds/idmap2/include/idmap2/RawPrintVisitor.h
@@ -45,11 +45,9 @@ class RawPrintVisitor : public Visitor {
void print(uint16_t value, const char* fmt, ...);
void print(uint32_t value, const char* fmt, ...);
void print(const std::string& value, size_t encoded_size, const char* fmt, ...);
- void print_raw(uint32_t length, const char* fmt, ...);
std::ostream& stream_;
- std::unique_ptr<const ApkAssets> target_apk_;
- std::unique_ptr<const ApkAssets> overlay_apk_;
+ std::vector<std::unique_ptr<const ApkAssets>> apk_assets_;
AssetManager2 target_am_;
AssetManager2 overlay_am_;
size_t offset_;
diff --git a/cmds/idmap2/include/idmap2/ResourceMapping.h b/cmds/idmap2/include/idmap2/ResourceMapping.h
index 5869409e7db9..0a58ec43d8ff 100644
--- a/cmds/idmap2/include/idmap2/ResourceMapping.h
+++ b/cmds/idmap2/include/idmap2/ResourceMapping.h
@@ -41,7 +41,7 @@ struct TargetValue {
DataValue data_value;
};
-using TargetResourceMap = std::map<ResourceId, TargetValue>;
+using TargetResourceMap = std::map<ResourceId, std::variant<ResourceId, TargetValue>>;
using OverlayResourceMap = std::map<ResourceId, ResourceId>;
class ResourceMapping {
@@ -56,7 +56,7 @@ class ResourceMapping {
bool enforce_overlayable, LogInfo& log_info);
// Retrieves the mapping of target resource id to overlay value.
- inline TargetResourceMap GetTargetToOverlayMap() const {
+ inline const TargetResourceMap& GetTargetToOverlayMap() const {
return target_map_;
}
@@ -81,19 +81,24 @@ class ResourceMapping {
}
// Retrieves the raw string pool data from the xml referenced in android:resourcesMap.
- inline const std::pair<const uint8_t*, uint32_t> GetStringPoolData() const {
- return std::make_pair(string_pool_data_.get(), string_pool_data_length_);
+ inline const StringPiece GetStringPoolData() const {
+ return StringPiece(reinterpret_cast<const char*>(string_pool_data_.get()),
+ string_pool_data_length_);
}
private:
ResourceMapping() = default;
- // Apps a mapping of target resource id to the type and value of the data that overlays the
- // target resource. The data_type is the runtime format of the data value (see
- // Res_value::dataType). If rewrite_overlay_reference is `true` then references to an overlay
+ // Maps a target resource id to an overlay resource id.
+ // If rewrite_overlay_reference is `true` then references to the overlay
// resource should appear as a reference to its corresponding target resource at runtime.
+ Result<Unit> AddMapping(ResourceId target_resource, ResourceId overlay_resource,
+ bool rewrite_overlay_reference);
+
+ // Maps a target resource id to a data type and value combination.
+ // The `data_type` is the runtime format of the data value (see Res_value::dataType).
Result<Unit> AddMapping(ResourceId target_resource, TargetValue::DataType data_type,
- TargetValue::DataValue data_value, bool rewrite_overlay_reference);
+ TargetValue::DataValue data_value);
// Removes the overlay value mapping for the target resource.
void RemoveMapping(ResourceId target_resource);
diff --git a/cmds/idmap2/libidmap2/BinaryStreamVisitor.cpp b/cmds/idmap2/libidmap2/BinaryStreamVisitor.cpp
index 255212ad4c66..726f6c5c2c99 100644
--- a/cmds/idmap2/libidmap2/BinaryStreamVisitor.cpp
+++ b/cmds/idmap2/libidmap2/BinaryStreamVisitor.cpp
@@ -24,10 +24,6 @@
namespace android::idmap2 {
-void BinaryStreamVisitor::Write(const void* value, size_t length) {
- stream_.write(reinterpret_cast<const char*>(value), length);
-}
-
void BinaryStreamVisitor::Write8(uint8_t value) {
stream_.write(reinterpret_cast<char*>(&value), sizeof(uint8_t));
}
@@ -49,11 +45,11 @@ void BinaryStreamVisitor::WriteString256(const StringPiece& value) {
stream_.write(buf, sizeof(buf));
}
-void BinaryStreamVisitor::WriteString(const std::string& value) {
- // pad with null to nearest word boundary; include at least one terminating null
- size_t padding_size = 4 - (value.size() % 4);
- Write32(value.size() + padding_size);
- stream_.write(value.c_str(), value.size());
+void BinaryStreamVisitor::WriteString(const StringPiece& value) {
+ // pad with null to nearest word boundary;
+ size_t padding_size = CalculatePadding(value.size());
+ Write32(value.size());
+ stream_.write(value.data(), value.size());
stream_.write("\0\0\0\0", padding_size);
}
@@ -67,7 +63,7 @@ void BinaryStreamVisitor::visit(const IdmapHeader& header) {
Write32(header.GetTargetCrc());
Write32(header.GetOverlayCrc());
Write32(header.GetFulfilledPolicies());
- Write8(static_cast<uint8_t>(header.GetEnforceOverlayable()));
+ Write32(static_cast<uint8_t>(header.GetEnforceOverlayable()));
WriteString256(header.GetTargetPath());
WriteString256(header.GetOverlayPath());
WriteString(header.GetDebugInfo());
@@ -76,8 +72,16 @@ void BinaryStreamVisitor::visit(const IdmapHeader& header) {
void BinaryStreamVisitor::visit(const IdmapData& data) {
for (const auto& target_entry : data.GetTargetEntries()) {
Write32(target_entry.target_id);
- Write8(target_entry.data_type);
- Write32(target_entry.data_value);
+ Write32(target_entry.overlay_id);
+ }
+
+ static constexpr uint16_t kValueSize = 8U;
+ for (const auto& target_entry : data.GetTargetInlineEntries()) {
+ Write32(target_entry.target_id);
+ Write16(kValueSize);
+ Write8(0U); // padding
+ Write8(target_entry.value.data_type);
+ Write32(target_entry.value.data_value);
}
for (const auto& overlay_entry : data.GetOverlayEntries()) {
@@ -85,16 +89,18 @@ void BinaryStreamVisitor::visit(const IdmapData& data) {
Write32(overlay_entry.target_id);
}
- Write(data.GetStringPoolData(), data.GetHeader()->GetStringPoolLength());
+ WriteString(data.GetStringPoolData());
}
void BinaryStreamVisitor::visit(const IdmapData::Header& header) {
Write8(header.GetTargetPackageId());
Write8(header.GetOverlayPackageId());
+ Write8(0U); // padding
+ Write8(0U); // padding
Write32(header.GetTargetEntryCount());
+ Write32(header.GetTargetInlineEntryCount());
Write32(header.GetOverlayEntryCount());
Write32(header.GetStringPoolIndexOffset());
- Write32(header.GetStringPoolLength());
}
} // namespace android::idmap2
diff --git a/cmds/idmap2/libidmap2/Idmap.cpp b/cmds/idmap2/libidmap2/Idmap.cpp
index 23c25a7089de..1129413584b2 100644
--- a/cmds/idmap2/libidmap2/Idmap.cpp
+++ b/cmds/idmap2/libidmap2/Idmap.cpp
@@ -51,19 +51,19 @@ bool WARN_UNUSED Read8(std::istream& stream, uint8_t* out) {
return false;
}
-bool WARN_UNUSED Read32(std::istream& stream, uint32_t* out) {
- uint32_t value;
- if (stream.read(reinterpret_cast<char*>(&value), sizeof(uint32_t))) {
- *out = dtohl(value);
+bool WARN_UNUSED Read16(std::istream& stream, uint16_t* out) {
+ uint16_t value;
+ if (stream.read(reinterpret_cast<char*>(&value), sizeof(uint16_t))) {
+ *out = dtohs(value);
return true;
}
return false;
}
-bool WARN_UNUSED ReadBuffer(std::istream& stream, std::unique_ptr<uint8_t[]>* out, size_t length) {
- auto buffer = std::unique_ptr<uint8_t[]>(new uint8_t[length]);
- if (stream.read(reinterpret_cast<char*>(buffer.get()), length)) {
- *out = std::move(buffer);
+bool WARN_UNUSED Read32(std::istream& stream, uint32_t* out) {
+ uint32_t value;
+ if (stream.read(reinterpret_cast<char*>(&value), sizeof(uint32_t))) {
+ *out = dtohl(value);
return true;
}
return false;
@@ -95,8 +95,11 @@ Result<std::string> ReadString(std::istream& stream) {
if (!stream.read(buf.data(), size)) {
return Error("failed to read string of size %u", size);
}
- // buf is guaranteed to be null terminated (with enough nulls to end on a word boundary)
- buf.resize(strlen(buf.c_str()));
+ uint32_t padding_size = CalculatePadding(size);
+ std::string padding(padding_size, '\0');
+ if (!stream.read(padding.data(), padding_size)) {
+ return Error("failed to read string padding of size %u", padding_size);
+ }
return buf;
}
@@ -112,16 +115,16 @@ Result<uint32_t> GetPackageCrc(const ZipFile& zip) {
std::unique_ptr<const IdmapHeader> IdmapHeader::FromBinaryStream(std::istream& stream) {
std::unique_ptr<IdmapHeader> idmap_header(new IdmapHeader());
- uint8_t enforce_overlayable;
+ uint32_t enforce_overlayable;
if (!Read32(stream, &idmap_header->magic_) || !Read32(stream, &idmap_header->version_) ||
!Read32(stream, &idmap_header->target_crc_) || !Read32(stream, &idmap_header->overlay_crc_) ||
- !Read32(stream, &idmap_header->fulfilled_policies_) || !Read8(stream, &enforce_overlayable) ||
- !ReadString256(stream, idmap_header->target_path_) ||
+ !Read32(stream, &idmap_header->fulfilled_policies_) ||
+ !Read32(stream, &enforce_overlayable) || !ReadString256(stream, idmap_header->target_path_) ||
!ReadString256(stream, idmap_header->overlay_path_)) {
return nullptr;
}
- idmap_header->enforce_overlayable_ = static_cast<bool>(enforce_overlayable);
+ idmap_header->enforce_overlayable_ = enforce_overlayable != 0U;
auto debug_str = ReadString(stream);
if (!debug_str) {
@@ -207,12 +210,13 @@ Result<Unit> IdmapHeader::IsUpToDate(const char* target_path, const char* overla
std::unique_ptr<const IdmapData::Header> IdmapData::Header::FromBinaryStream(std::istream& stream) {
std::unique_ptr<IdmapData::Header> idmap_data_header(new IdmapData::Header());
+ uint8_t padding;
if (!Read8(stream, &idmap_data_header->target_package_id_) ||
- !Read8(stream, &idmap_data_header->overlay_package_id_) ||
- !Read32(stream, &idmap_data_header->target_entry_count) ||
+ !Read8(stream, &idmap_data_header->overlay_package_id_) || !Read8(stream, &padding) ||
+ !Read8(stream, &padding) || !Read32(stream, &idmap_data_header->target_entry_count) ||
+ !Read32(stream, &idmap_data_header->target_entry_inline_count) ||
!Read32(stream, &idmap_data_header->overlay_entry_count) ||
- !Read32(stream, &idmap_data_header->string_pool_index_offset) ||
- !Read32(stream, &idmap_data_header->string_pool_len)) {
+ !Read32(stream, &idmap_data_header->string_pool_index_offset)) {
return nullptr;
}
@@ -225,14 +229,27 @@ std::unique_ptr<const IdmapData> IdmapData::FromBinaryStream(std::istream& strea
if (!data->header_) {
return nullptr;
}
+
// Read the mapping of target resource id to overlay resource value.
for (size_t i = 0; i < data->header_->GetTargetEntryCount(); i++) {
TargetEntry target_entry{};
- if (!Read32(stream, &target_entry.target_id) || !Read8(stream, &target_entry.data_type) ||
- !Read32(stream, &target_entry.data_value)) {
+ if (!Read32(stream, &target_entry.target_id) || !Read32(stream, &target_entry.overlay_id)) {
+ return nullptr;
+ }
+ data->target_entries_.push_back(target_entry);
+ }
+
+ // Read the mapping of target resource id to inline overlay values.
+ uint8_t unused1;
+ uint16_t unused2;
+ for (size_t i = 0; i < data->header_->GetTargetInlineEntryCount(); i++) {
+ TargetInlineEntry target_entry{};
+ if (!Read32(stream, &target_entry.target_id) || !Read16(stream, &unused2) ||
+ !Read8(stream, &unused1) || !Read8(stream, &target_entry.value.data_type) ||
+ !Read32(stream, &target_entry.value.data_value)) {
return nullptr;
}
- data->target_entries_.emplace_back(target_entry);
+ data->target_inline_entries_.push_back(target_entry);
}
// Read the mapping of overlay resource id to target resource id.
@@ -245,9 +262,11 @@ std::unique_ptr<const IdmapData> IdmapData::FromBinaryStream(std::istream& strea
}
// Read raw string pool bytes.
- if (!ReadBuffer(stream, &data->string_pool_, data->header_->string_pool_len)) {
+ auto string_pool_data = ReadString(stream);
+ if (!string_pool_data) {
return nullptr;
}
+ data->string_pool_data_ = std::move(*string_pool_data);
return std::move(data);
}
@@ -290,27 +309,28 @@ Result<std::unique_ptr<const IdmapData>> IdmapData::FromResourceMapping(
}
std::unique_ptr<IdmapData> data(new IdmapData());
- for (const auto& mappings : resource_mapping.GetTargetToOverlayMap()) {
- data->target_entries_.emplace_back(IdmapData::TargetEntry{
- mappings.first, mappings.second.data_type, mappings.second.data_value});
+ data->string_pool_data_ = resource_mapping.GetStringPoolData().to_string();
+ for (const auto& mapping : resource_mapping.GetTargetToOverlayMap()) {
+ if (auto overlay_resource = std::get_if<ResourceId>(&mapping.second)) {
+ data->target_entries_.push_back({mapping.first, *overlay_resource});
+ } else {
+ data->target_inline_entries_.push_back(
+ {mapping.first, std::get<TargetValue>(mapping.second)});
+ }
}
- for (const auto& mappings : resource_mapping.GetOverlayToTargetMap()) {
- data->overlay_entries_.emplace_back(IdmapData::OverlayEntry{mappings.first, mappings.second});
+ for (const auto& mapping : resource_mapping.GetOverlayToTargetMap()) {
+ data->overlay_entries_.emplace_back(IdmapData::OverlayEntry{mapping.first, mapping.second});
}
std::unique_ptr<IdmapData::Header> data_header(new IdmapData::Header());
data_header->target_package_id_ = resource_mapping.GetTargetPackageId();
data_header->overlay_package_id_ = resource_mapping.GetOverlayPackageId();
data_header->target_entry_count = static_cast<uint32_t>(data->target_entries_.size());
+ data_header->target_entry_inline_count =
+ static_cast<uint32_t>(data->target_inline_entries_.size());
data_header->overlay_entry_count = static_cast<uint32_t>(data->overlay_entries_.size());
data_header->string_pool_index_offset = resource_mapping.GetStringPoolOffset();
-
- const auto string_pool_data = resource_mapping.GetStringPoolData();
- data_header->string_pool_len = string_pool_data.second;
- data->string_pool_ = std::unique_ptr<uint8_t[]>(new uint8_t[data_header->string_pool_len]);
- memcpy(data->string_pool_.get(), string_pool_data.first, data_header->string_pool_len);
-
data->header_ = std::move(data_header);
return {std::move(data)};
}
diff --git a/cmds/idmap2/libidmap2/PrettyPrintVisitor.cpp b/cmds/idmap2/libidmap2/PrettyPrintVisitor.cpp
index 63ee8a648352..a93202a64d31 100644
--- a/cmds/idmap2/libidmap2/PrettyPrintVisitor.cpp
+++ b/cmds/idmap2/libidmap2/PrettyPrintVisitor.cpp
@@ -38,6 +38,7 @@ void PrettyPrintVisitor::visit(const IdmapHeader& header) {
stream_ << "Paths:" << std::endl
<< TAB "target apk path : " << header.GetTargetPath() << std::endl
<< TAB "overlay apk path : " << header.GetOverlayPath() << std::endl;
+
const std::string& debug = header.GetDebugInfo();
if (!debug.empty()) {
std::istringstream debug_stream(debug);
@@ -48,10 +49,16 @@ void PrettyPrintVisitor::visit(const IdmapHeader& header) {
}
}
- target_apk_ = ApkAssets::Load(header.GetTargetPath().to_string());
- if (target_apk_) {
+ if (auto target_apk_ = ApkAssets::Load(header.GetTargetPath().to_string())) {
target_am_.SetApkAssets({target_apk_.get()});
+ apk_assets_.push_back(std::move(target_apk_));
+ }
+
+ if (auto overlay_apk = ApkAssets::Load(header.GetOverlayPath().to_string())) {
+ overlay_am_.SetApkAssets({overlay_apk.get()});
+ apk_assets_.push_back(std::move(overlay_apk));
}
+
stream_ << "Mapping:" << std::endl;
}
@@ -59,34 +66,56 @@ void PrettyPrintVisitor::visit(const IdmapData::Header& header ATTRIBUTE_UNUSED)
}
void PrettyPrintVisitor::visit(const IdmapData& data) {
+ static constexpr const char* kUnknownResourceName = "???";
+
const bool target_package_loaded = !target_am_.GetApkAssets().empty();
- const ResStringPool string_pool(data.GetStringPoolData(),
- data.GetHeader()->GetStringPoolLength());
+ const bool overlay_package_loaded = !overlay_am_.GetApkAssets().empty();
+
+ const ResStringPool string_pool(data.GetStringPoolData().data(), data.GetStringPoolData().size());
const size_t string_pool_offset = data.GetHeader()->GetStringPoolIndexOffset();
- for (auto& target_entry : data.GetTargetEntries()) {
- stream_ << TAB << base::StringPrintf("0x%08x ->", target_entry.target_id);
+ for (const auto& target_entry : data.GetTargetEntries()) {
+ std::string target_name = kUnknownResourceName;
+ if (target_package_loaded) {
+ if (auto name = utils::ResToTypeEntryName(target_am_, target_entry.target_id)) {
+ target_name = *name;
+ }
+ }
- if (target_entry.data_type != Res_value::TYPE_REFERENCE &&
- target_entry.data_type != Res_value::TYPE_DYNAMIC_REFERENCE) {
- stream_ << " " << utils::DataTypeToString(target_entry.data_type);
+ std::string overlay_name = kUnknownResourceName;
+ if (overlay_package_loaded) {
+ if (auto name = utils::ResToTypeEntryName(overlay_am_, target_entry.overlay_id)) {
+ overlay_name = *name;
+ }
}
- if (target_entry.data_type == Res_value::TYPE_STRING) {
- stream_ << " \""
- << string_pool.string8ObjectAt(target_entry.data_value - string_pool_offset).c_str()
- << "\"";
+ stream_ << TAB
+ << base::StringPrintf("0x%08x -> 0x%08x (%s -> %s)", target_entry.target_id,
+ target_entry.overlay_id, target_name.c_str(),
+ overlay_name.c_str())
+ << std::endl;
+ }
+
+ for (auto& target_entry : data.GetTargetInlineEntries()) {
+ stream_ << TAB << base::StringPrintf("0x%08x -> ", target_entry.target_id)
+ << utils::DataTypeToString(target_entry.value.data_type);
+
+ size_t unused;
+ if (target_entry.value.data_type == Res_value::TYPE_STRING) {
+ auto str = string_pool.stringAt(target_entry.value.data_value - string_pool_offset, &unused);
+ stream_ << " \"" << StringPiece16(str) << "\"";
} else {
- stream_ << " " << base::StringPrintf("0x%08x", target_entry.data_value);
+ stream_ << " " << base::StringPrintf("0x%08x", target_entry.value.data_value);
}
+ std::string target_name = kUnknownResourceName;
if (target_package_loaded) {
- Result<std::string> name = utils::ResToTypeEntryName(target_am_, target_entry.target_id);
- if (name) {
- stream_ << " " << *name;
+ if (auto name = utils::ResToTypeEntryName(target_am_, target_entry.target_id)) {
+ target_name = *name;
}
}
- stream_ << std::endl;
+
+ stream_ << " (" << target_name << ")" << std::endl;
}
}
diff --git a/cmds/idmap2/libidmap2/RawPrintVisitor.cpp b/cmds/idmap2/libidmap2/RawPrintVisitor.cpp
index 3f62a2ae2029..82f5d26cbbb3 100644
--- a/cmds/idmap2/libidmap2/RawPrintVisitor.cpp
+++ b/cmds/idmap2/libidmap2/RawPrintVisitor.cpp
@@ -30,15 +30,6 @@
using android::ApkAssets;
using android::idmap2::policy::PoliciesToDebugString;
-namespace {
-
-size_t StringSizeWhenEncoded(const std::string& s) {
- size_t null_bytes = 4 - (s.size() % 4);
- return sizeof(uint32_t) + s.size() + null_bytes;
-}
-
-} // namespace
-
namespace android::idmap2 {
void RawPrintVisitor::visit(const Idmap& idmap ATTRIBUTE_UNUSED) {
@@ -51,19 +42,24 @@ void RawPrintVisitor::visit(const IdmapHeader& header) {
print(header.GetOverlayCrc(), "overlay crc");
print(header.GetFulfilledPolicies(), "fulfilled policies: %s",
PoliciesToDebugString(header.GetFulfilledPolicies()).c_str());
- print(static_cast<uint8_t>(header.GetEnforceOverlayable()), "enforce overlayable");
+ print(static_cast<uint32_t>(header.GetEnforceOverlayable()), "enforce overlayable");
print(header.GetTargetPath().to_string(), kIdmapStringLength, "target path");
print(header.GetOverlayPath().to_string(), kIdmapStringLength, "overlay path");
- print("...", StringSizeWhenEncoded(header.GetDebugInfo()), "debug info");
- target_apk_ = ApkAssets::Load(header.GetTargetPath().to_string());
+ uint32_t debug_info_size = header.GetDebugInfo().size();
+ print(debug_info_size, "debug info size");
+ print("...", debug_info_size + CalculatePadding(debug_info_size), "debug info");
+
+ auto target_apk_ = ApkAssets::Load(header.GetTargetPath().to_string());
if (target_apk_) {
target_am_.SetApkAssets({target_apk_.get()});
+ apk_assets_.push_back(std::move(target_apk_));
}
- overlay_apk_ = ApkAssets::Load(header.GetOverlayPath().to_string());
+ auto overlay_apk_ = ApkAssets::Load(header.GetOverlayPath().to_string());
if (overlay_apk_) {
overlay_am_.SetApkAssets({overlay_apk_.get()});
+ apk_assets_.push_back(std::move(overlay_apk_));
}
}
@@ -82,18 +78,44 @@ void RawPrintVisitor::visit(const IdmapData& data ATTRIBUTE_UNUSED) {
print(target_entry.target_id, "target id");
}
- print(target_entry.data_type, "type: %s",
- utils::DataTypeToString(target_entry.data_type).data());
+ Result<std::string> overlay_name(Error(""));
+ if (overlay_package_loaded) {
+ overlay_name = utils::ResToTypeEntryName(overlay_am_, target_entry.overlay_id);
+ }
+ if (overlay_name) {
+ print(target_entry.overlay_id, "overlay id: %s", overlay_name->c_str());
+ } else {
+ print(target_entry.overlay_id, "overlay id");
+ }
+ }
+
+ for (auto& target_entry : data.GetTargetInlineEntries()) {
+ Result<std::string> target_name(Error(""));
+ if (target_package_loaded) {
+ target_name = utils::ResToTypeEntryName(target_am_, target_entry.target_id);
+ }
+ if (target_name) {
+ print(target_entry.target_id, "target id: %s", target_name->c_str());
+ } else {
+ print(target_entry.target_id, "target id");
+ }
+
+ print("...", sizeof(Res_value::size) + sizeof(Res_value::res0), "padding");
+
+ print(target_entry.value.data_type, "type: %s",
+ utils::DataTypeToString(target_entry.value.data_type).data());
Result<std::string> overlay_name(Error(""));
- if (overlay_package_loaded && (target_entry.data_type == Res_value::TYPE_REFERENCE ||
- target_entry.data_type == Res_value::TYPE_DYNAMIC_REFERENCE)) {
- overlay_name = utils::ResToTypeEntryName(overlay_am_, target_entry.data_value);
+ if (overlay_package_loaded &&
+ (target_entry.value.data_value == Res_value::TYPE_REFERENCE ||
+ target_entry.value.data_value == Res_value::TYPE_DYNAMIC_REFERENCE)) {
+ overlay_name = utils::ResToTypeEntryName(overlay_am_, target_entry.value.data_value);
}
+
if (overlay_name) {
- print(target_entry.data_value, "value: %s", overlay_name->c_str());
+ print(target_entry.value.data_value, "data: %s", overlay_name->c_str());
} else {
- print(target_entry.data_value, "value");
+ print(target_entry.value.data_value, "data");
}
}
@@ -121,19 +143,19 @@ void RawPrintVisitor::visit(const IdmapData& data ATTRIBUTE_UNUSED) {
}
}
- const size_t string_pool_length = data.GetHeader()->GetStringPoolLength();
- if (string_pool_length > 0) {
- print_raw(string_pool_length, "%zu raw string pool bytes", string_pool_length);
- }
+ uint32_t string_pool_size = data.GetStringPoolData().size();
+ print(string_pool_size, "string pool size");
+ print("...", string_pool_size + CalculatePadding(string_pool_size), "string pool");
}
void RawPrintVisitor::visit(const IdmapData::Header& header) {
print(header.GetTargetPackageId(), "target package id");
print(header.GetOverlayPackageId(), "overlay package id");
+ print("...", sizeof(Idmap_data_header::p0), "padding");
print(header.GetTargetEntryCount(), "target entry count");
+ print(header.GetTargetInlineEntryCount(), "target inline entry count");
print(header.GetOverlayEntryCount(), "overlay entry count");
print(header.GetStringPoolIndexOffset(), "string pool index offset");
- print(header.GetStringPoolLength(), "string pool byte length");
}
// NOLINTNEXTLINE(cert-dcl50-cpp)
@@ -190,17 +212,4 @@ void RawPrintVisitor::print(const std::string& value, size_t encoded_size, const
offset_ += encoded_size;
}
-// NOLINTNEXTLINE(cert-dcl50-cpp)
-void RawPrintVisitor::print_raw(uint32_t length, const char* fmt, ...) {
- va_list ap;
- va_start(ap, fmt);
- std::string comment;
- base::StringAppendV(&comment, fmt, ap);
- va_end(ap);
-
- stream_ << base::StringPrintf("%08zx: ", offset_) << "........ " << comment << std::endl;
-
- offset_ += length;
-}
-
} // namespace android::idmap2
diff --git a/cmds/idmap2/libidmap2/ResourceMapping.cpp b/cmds/idmap2/libidmap2/ResourceMapping.cpp
index fd8b4eb86b4a..31f1c16ba5a6 100644
--- a/cmds/idmap2/libidmap2/ResourceMapping.cpp
+++ b/cmds/idmap2/libidmap2/ResourceMapping.cpp
@@ -71,9 +71,9 @@ Result<Unit> CheckOverlayable(const LoadedPackage& target_package,
if (!target_package.DefinesOverlayable()) {
return (sDefaultPolicies & fulfilled_policies) != 0
? Result<Unit>({})
- : Error(
- "overlay must be preinstalled or signed with the same signature as the "
- "target");
+ : Error("overlay must be preinstalled, signed with the same signature as the target,"
+ " or signed with the same signature as the package referenced through"
+ " <overlay-config-signature>.");
}
const OverlayableInfo* overlayable_info = target_package.GetOverlayableInfo(target_resource);
@@ -205,19 +205,14 @@ Result<ResourceMapping> ResourceMapping::CreateResourceMapping(const AssetManage
overlay_resource->data += string_pool_offset;
}
- // Only rewrite resources defined within the overlay package to their corresponding target
- // resource ids at runtime.
- bool rewrite_overlay_reference =
- IsReference(overlay_resource->dataType)
- ? overlay_package_id == EXTRACT_PACKAGE(overlay_resource->data)
- : false;
-
- if (rewrite_overlay_reference) {
- overlay_resource->dataType = Res_value::TYPE_DYNAMIC_REFERENCE;
+ if (IsReference(overlay_resource->dataType)) {
+ // Only rewrite resources defined within the overlay package to their corresponding target
+ // resource ids at runtime.
+ bool rewrite_reference = overlay_package_id == EXTRACT_PACKAGE(overlay_resource->data);
+ resource_mapping.AddMapping(target_id, overlay_resource->data, rewrite_reference);
+ } else {
+ resource_mapping.AddMapping(target_id, overlay_resource->dataType, overlay_resource->data);
}
-
- resource_mapping.AddMapping(target_id, overlay_resource->dataType, overlay_resource->data,
- rewrite_overlay_reference);
}
return resource_mapping;
@@ -246,9 +241,8 @@ Result<ResourceMapping> ResourceMapping::CreateResourceMappingLegacy(
// Retrieve the compile-time resource id of the target resource.
target_resource = REWRITE_PACKAGE(target_resource, target_package_id);
-
- resource_mapping.AddMapping(target_resource, Res_value::TYPE_REFERENCE, overlay_resid,
- /* rewrite_overlay_reference */ false);
+ resource_mapping.AddMapping(target_resource, overlay_resid,
+ false /* rewrite_overlay_reference */);
}
return resource_mapping;
@@ -396,9 +390,7 @@ OverlayResourceMap ResourceMapping::GetOverlayToTargetMap() const {
return map;
}
-Result<Unit> ResourceMapping::AddMapping(ResourceId target_resource,
- TargetValue::DataType data_type,
- TargetValue::DataValue data_value,
+Result<Unit> ResourceMapping::AddMapping(ResourceId target_resource, ResourceId overlay_resource,
bool rewrite_overlay_reference) {
if (target_map_.find(target_resource) != target_map_.end()) {
return Error(R"(target resource id "0x%08x" mapped to multiple values)", target_resource);
@@ -407,13 +399,26 @@ Result<Unit> ResourceMapping::AddMapping(ResourceId target_resource,
// TODO(141485591): Ensure that the overlay type is compatible with the target type. If the
// runtime types are not compatible, it could cause runtime crashes when the resource is resolved.
- target_map_.insert(std::make_pair(target_resource, TargetValue{data_type, data_value}));
+ target_map_.insert(std::make_pair(target_resource, overlay_resource));
- if (rewrite_overlay_reference && IsReference(data_type)) {
- overlay_map_.insert(std::make_pair(data_value, target_resource));
+ if (rewrite_overlay_reference) {
+ overlay_map_.insert(std::make_pair(overlay_resource, target_resource));
}
+ return Unit{};
+}
- return Result<Unit>({});
+Result<Unit> ResourceMapping::AddMapping(ResourceId target_resource,
+ TargetValue::DataType data_type,
+ TargetValue::DataValue data_value) {
+ if (target_map_.find(target_resource) != target_map_.end()) {
+ return Error(R"(target resource id "0x%08x" mapped to multiple values)", target_resource);
+ }
+
+ // TODO(141485591): Ensure that the overlay type is compatible with the target type. If the
+ // runtime types are not compatible, it could cause runtime crashes when the resource is resolved.
+
+ target_map_.insert(std::make_pair(target_resource, TargetValue{data_type, data_value}));
+ return Unit{};
}
void ResourceMapping::RemoveMapping(ResourceId target_resource) {
@@ -422,14 +427,15 @@ void ResourceMapping::RemoveMapping(ResourceId target_resource) {
return;
}
- const TargetValue value = target_iter->second;
+ const auto value = target_iter->second;
target_map_.erase(target_iter);
- if (!IsReference(value.data_type)) {
+ const ResourceId* overlay_resource = std::get_if<ResourceId>(&value);
+ if (overlay_resource == nullptr) {
return;
}
- auto overlay_iter = overlay_map_.equal_range(value.data_value);
+ auto overlay_iter = overlay_map_.equal_range(*overlay_resource);
for (auto i = overlay_iter.first; i != overlay_iter.second; ++i) {
if (i->second == target_resource) {
overlay_map_.erase(i);
diff --git a/cmds/idmap2/tests/BinaryStreamVisitorTests.cpp b/cmds/idmap2/tests/BinaryStreamVisitorTests.cpp
index 5fea7bcdaac5..c3a3e0ba9047 100644
--- a/cmds/idmap2/tests/BinaryStreamVisitorTests.cpp
+++ b/cmds/idmap2/tests/BinaryStreamVisitorTests.cpp
@@ -72,13 +72,20 @@ TEST(BinaryStreamVisitorTests, CreateBinaryStreamViaBinaryStreamVisitor) {
const auto& target_entries2 = data2->GetTargetEntries();
ASSERT_EQ(target_entries1.size(), target_entries2.size());
ASSERT_EQ(target_entries1[0].target_id, target_entries2[0].target_id);
- ASSERT_EQ(target_entries1[0].data_value, target_entries2[0].data_value);
+ ASSERT_EQ(target_entries1[0].overlay_id, target_entries2[0].overlay_id);
ASSERT_EQ(target_entries1[1].target_id, target_entries2[1].target_id);
- ASSERT_EQ(target_entries1[1].data_value, target_entries2[1].data_value);
+ ASSERT_EQ(target_entries1[1].overlay_id, target_entries2[1].overlay_id);
ASSERT_EQ(target_entries1[2].target_id, target_entries2[2].target_id);
- ASSERT_EQ(target_entries1[2].data_value, target_entries2[2].data_value);
+ ASSERT_EQ(target_entries1[2].overlay_id, target_entries2[2].overlay_id);
+
+ const auto& target_inline_entries1 = data1->GetTargetInlineEntries();
+ const auto& target_inline_entries2 = data2->GetTargetInlineEntries();
+ ASSERT_EQ(target_inline_entries1.size(), target_inline_entries2.size());
+ ASSERT_EQ(target_inline_entries1[0].target_id, target_inline_entries2[0].target_id);
+ ASSERT_EQ(target_inline_entries1[0].value.data_type, target_inline_entries2[0].value.data_type);
+ ASSERT_EQ(target_inline_entries1[0].value.data_value, target_inline_entries2[0].value.data_value);
const auto& overlay_entries1 = data1->GetOverlayEntries();
const auto& overlay_entries2 = data2->GetOverlayEntries();
diff --git a/cmds/idmap2/tests/Idmap2BinaryTests.cpp b/cmds/idmap2/tests/Idmap2BinaryTests.cpp
index 61751b33dcba..e7e9e4cf5091 100644
--- a/cmds/idmap2/tests/Idmap2BinaryTests.cpp
+++ b/cmds/idmap2/tests/Idmap2BinaryTests.cpp
@@ -128,13 +128,13 @@ TEST_F(Idmap2BinaryTests, Dump) {
// clang-format on
ASSERT_THAT(result, NotNull());
ASSERT_EQ(result->status, EXIT_SUCCESS) << result->stderr;
- ASSERT_NE(result->stdout.find(R::target::integer::literal::int1 + " -> 0x7f010000 integer/int1"),
+ ASSERT_NE(result->stdout.find(R::target::integer::literal::int1 + " -> 0x7f010000"),
std::string::npos);
- ASSERT_NE(result->stdout.find(R::target::string::literal::str1 + " -> 0x7f020000 string/str1"),
+ ASSERT_NE(result->stdout.find(R::target::string::literal::str1 + " -> 0x7f020000"),
std::string::npos);
- ASSERT_NE(result->stdout.find(R::target::string::literal::str3 + " -> 0x7f020001 string/str3"),
+ ASSERT_NE(result->stdout.find(R::target::string::literal::str3 + " -> 0x7f020001"),
std::string::npos);
- ASSERT_NE(result->stdout.find(R::target::string::literal::str4 + " -> 0x7f020002 string/str4"),
+ ASSERT_NE(result->stdout.find(R::target::string::literal::str4 + " -> 0x7f020002"),
std::string::npos);
// clang-format off
diff --git a/cmds/idmap2/tests/IdmapTests.cpp b/cmds/idmap2/tests/IdmapTests.cpp
index 6fab5e0f8ae1..9b42a2781b58 100644
--- a/cmds/idmap2/tests/IdmapTests.cpp
+++ b/cmds/idmap2/tests/IdmapTests.cpp
@@ -42,14 +42,18 @@ using PolicyFlags = android::ResTable_overlayable_policy_header::PolicyFlags;
namespace android::idmap2 {
-#define ASSERT_TARGET_ENTRY(entry, target_resid, type, value) \
- ASSERT_EQ(entry.target_id, target_resid); \
- ASSERT_EQ(entry.data_type, type); \
- ASSERT_EQ(entry.data_value, value)
+#define ASSERT_TARGET_ENTRY(entry, target_resid, overlay_resid) \
+ ASSERT_EQ((entry).target_id, (target_resid)); \
+ ASSERT_EQ((entry).overlay_id, (overlay_resid))
+
+#define ASSERT_TARGET_INLINE_ENTRY(entry, target_resid, expected_type, expected_value) \
+ ASSERT_EQ((entry).target_id, target_resid); \
+ ASSERT_EQ((entry).value.data_type, (expected_type)); \
+ ASSERT_EQ((entry).value.data_value, (expected_value))
#define ASSERT_OVERLAY_ENTRY(entry, overlay_resid, target_resid) \
- ASSERT_EQ(entry.overlay_id, overlay_resid); \
- ASSERT_EQ(entry.target_id, target_resid)
+ ASSERT_EQ((entry).overlay_id, (overlay_resid)); \
+ ASSERT_EQ((entry).target_id, (target_resid))
TEST(IdmapTests, TestCanonicalIdmapPathFor) {
ASSERT_EQ(Idmap::CanonicalIdmapPathFor("/foo", "/vendor/overlay/bar.apk"),
@@ -62,7 +66,7 @@ TEST(IdmapTests, CreateIdmapHeaderFromBinaryStream) {
std::unique_ptr<const IdmapHeader> header = IdmapHeader::FromBinaryStream(stream);
ASSERT_THAT(header, NotNull());
ASSERT_EQ(header->GetMagic(), 0x504d4449U);
- ASSERT_EQ(header->GetVersion(), 0x04U);
+ ASSERT_EQ(header->GetVersion(), 0x05U);
ASSERT_EQ(header->GetTargetCrc(), 0x1234U);
ASSERT_EQ(header->GetOverlayCrc(), 0x5678U);
ASSERT_EQ(header->GetFulfilledPolicies(), 0x11);
@@ -75,7 +79,7 @@ TEST(IdmapTests, CreateIdmapHeaderFromBinaryStream) {
TEST(IdmapTests, FailToCreateIdmapHeaderFromBinaryStreamIfPathTooLong) {
std::string raw(reinterpret_cast<const char*>(idmap_raw_data), idmap_raw_data_len);
// overwrite the target path string, including the terminating null, with '.'
- for (size_t i = 0x15; i < 0x115; i++) {
+ for (size_t i = 0x18; i < 0x118; i++) {
raw[i] = '.';
}
std::istringstream stream(raw);
@@ -84,7 +88,7 @@ TEST(IdmapTests, FailToCreateIdmapHeaderFromBinaryStreamIfPathTooLong) {
}
TEST(IdmapTests, CreateIdmapDataHeaderFromBinaryStream) {
- const size_t offset = 0x221;
+ const size_t offset = 0x224;
std::string raw(reinterpret_cast<const char*>(idmap_raw_data + offset),
idmap_raw_data_len - offset);
std::istringstream stream(raw);
@@ -96,7 +100,7 @@ TEST(IdmapTests, CreateIdmapDataHeaderFromBinaryStream) {
}
TEST(IdmapTests, CreateIdmapDataFromBinaryStream) {
- const size_t offset = 0x221;
+ const size_t offset = 0x224;
std::string raw(reinterpret_cast<const char*>(idmap_raw_data + offset),
idmap_raw_data_len - offset);
std::istringstream stream(raw);
@@ -106,12 +110,14 @@ TEST(IdmapTests, CreateIdmapDataFromBinaryStream) {
const auto& target_entries = data->GetTargetEntries();
ASSERT_EQ(target_entries.size(), 3U);
- ASSERT_TARGET_ENTRY(target_entries[0], 0x7f020000, 0x01 /* Res_value::TYPE_REFERENCE */,
- 0x7f020000);
- ASSERT_TARGET_ENTRY(target_entries[1], 0x7f030000, 0x01 /* Res_value::TYPE_REFERENCE */,
- 0x7f030000);
- ASSERT_TARGET_ENTRY(target_entries[2], 0x7f030002, 0x01 /* Res_value::TYPE_REFERENCE */,
- 0x7f030001);
+ ASSERT_TARGET_ENTRY(target_entries[0], 0x7f020000, 0x7f020000);
+ ASSERT_TARGET_ENTRY(target_entries[1], 0x7f030000, 0x7f030000);
+ ASSERT_TARGET_ENTRY(target_entries[2], 0x7f030002, 0x7f030001);
+
+ const auto& target_inline_entries = data->GetTargetInlineEntries();
+ ASSERT_EQ(target_inline_entries.size(), 1U);
+ ASSERT_TARGET_INLINE_ENTRY(target_inline_entries[0], 0x7f040000, Res_value::TYPE_INT_HEX,
+ 0x12345678);
const auto& overlay_entries = data->GetOverlayEntries();
ASSERT_EQ(target_entries.size(), 3U);
@@ -130,7 +136,7 @@ TEST(IdmapTests, CreateIdmapFromBinaryStream) {
ASSERT_THAT(idmap->GetHeader(), NotNull());
ASSERT_EQ(idmap->GetHeader()->GetMagic(), 0x504d4449U);
- ASSERT_EQ(idmap->GetHeader()->GetVersion(), 0x04U);
+ ASSERT_EQ(idmap->GetHeader()->GetVersion(), 0x05U);
ASSERT_EQ(idmap->GetHeader()->GetTargetCrc(), 0x1234U);
ASSERT_EQ(idmap->GetHeader()->GetOverlayCrc(), 0x5678U);
ASSERT_EQ(idmap->GetHeader()->GetFulfilledPolicies(), 0x11);
@@ -146,9 +152,14 @@ TEST(IdmapTests, CreateIdmapFromBinaryStream) {
const auto& target_entries = data->GetTargetEntries();
ASSERT_EQ(target_entries.size(), 3U);
- ASSERT_TARGET_ENTRY(target_entries[0], 0x7f020000, Res_value::TYPE_REFERENCE, 0x7f020000);
- ASSERT_TARGET_ENTRY(target_entries[1], 0x7f030000, Res_value::TYPE_REFERENCE, 0x7f030000);
- ASSERT_TARGET_ENTRY(target_entries[2], 0x7f030002, Res_value::TYPE_REFERENCE, 0x7f030001);
+ ASSERT_TARGET_ENTRY(target_entries[0], 0x7f020000, 0x7f020000);
+ ASSERT_TARGET_ENTRY(target_entries[1], 0x7f030000, 0x7f030000);
+ ASSERT_TARGET_ENTRY(target_entries[2], 0x7f030002, 0x7f030001);
+
+ const auto& target_inline_entries = data->GetTargetInlineEntries();
+ ASSERT_EQ(target_inline_entries.size(), 1U);
+ ASSERT_TARGET_INLINE_ENTRY(target_inline_entries[0], 0x7f040000, Res_value::TYPE_INT_HEX,
+ 0x12345678);
const auto& overlay_entries = data->GetOverlayEntries();
ASSERT_EQ(target_entries.size(), 3U);
@@ -184,7 +195,7 @@ TEST(IdmapTests, CreateIdmapHeaderFromApkAssets) {
ASSERT_THAT(idmap->GetHeader(), NotNull());
ASSERT_EQ(idmap->GetHeader()->GetMagic(), 0x504d4449U);
- ASSERT_EQ(idmap->GetHeader()->GetVersion(), 0x04U);
+ ASSERT_EQ(idmap->GetHeader()->GetVersion(), 0x05U);
ASSERT_EQ(idmap->GetHeader()->GetTargetCrc(), android::idmap2::TestConstants::TARGET_CRC);
ASSERT_EQ(idmap->GetHeader()->GetOverlayCrc(), android::idmap2::TestConstants::OVERLAY_CRC);
ASSERT_EQ(idmap->GetHeader()->GetFulfilledPolicies(), PolicyFlags::PUBLIC);
@@ -244,14 +255,13 @@ TEST(IdmapTests, CreateIdmapDataFromApkAssets) {
const auto& target_entries = data->GetTargetEntries();
ASSERT_EQ(target_entries.size(), 4U);
- ASSERT_TARGET_ENTRY(target_entries[0], R::target::integer::int1,
- Res_value::TYPE_DYNAMIC_REFERENCE, R::overlay::integer::int1);
- ASSERT_TARGET_ENTRY(target_entries[1], R::target::string::str1, Res_value::TYPE_DYNAMIC_REFERENCE,
- R::overlay::string::str1);
- ASSERT_TARGET_ENTRY(target_entries[2], R::target::string::str3, Res_value::TYPE_DYNAMIC_REFERENCE,
- R::overlay::string::str3);
- ASSERT_TARGET_ENTRY(target_entries[3], R::target::string::str4, Res_value::TYPE_DYNAMIC_REFERENCE,
- R::overlay::string::str4);
+ ASSERT_TARGET_ENTRY(target_entries[0], R::target::integer::int1, R::overlay::integer::int1);
+ ASSERT_TARGET_ENTRY(target_entries[1], R::target::string::str1, R::overlay::string::str1);
+ ASSERT_TARGET_ENTRY(target_entries[2], R::target::string::str3, R::overlay::string::str3);
+ ASSERT_TARGET_ENTRY(target_entries[3], R::target::string::str4, R::overlay::string::str4);
+
+ const auto& target_inline_entries = data->GetTargetInlineEntries();
+ ASSERT_EQ(target_inline_entries.size(), 0U);
const auto& overlay_entries = data->GetOverlayEntries();
ASSERT_EQ(target_entries.size(), 4U);
@@ -286,13 +296,13 @@ TEST(IdmapTests, CreateIdmapDataFromApkAssetsSharedLibOverlay) {
const auto& target_entries = data->GetTargetEntries();
ASSERT_EQ(target_entries.size(), 4U);
ASSERT_TARGET_ENTRY(target_entries[0], R::target::integer::int1,
- Res_value::TYPE_DYNAMIC_REFERENCE, R::overlay_shared::integer::int1);
- ASSERT_TARGET_ENTRY(target_entries[1], R::target::string::str1, Res_value::TYPE_DYNAMIC_REFERENCE,
- R::overlay_shared::string::str1);
- ASSERT_TARGET_ENTRY(target_entries[2], R::target::string::str3, Res_value::TYPE_DYNAMIC_REFERENCE,
- R::overlay_shared::string::str3);
- ASSERT_TARGET_ENTRY(target_entries[3], R::target::string::str4, Res_value::TYPE_DYNAMIC_REFERENCE,
- R::overlay_shared::string::str4);
+ R::overlay_shared::integer::int1);
+ ASSERT_TARGET_ENTRY(target_entries[1], R::target::string::str1, R::overlay_shared::string::str1);
+ ASSERT_TARGET_ENTRY(target_entries[2], R::target::string::str3, R::overlay_shared::string::str3);
+ ASSERT_TARGET_ENTRY(target_entries[3], R::target::string::str4, R::overlay_shared::string::str4);
+
+ const auto& target_inline_entries = data->GetTargetInlineEntries();
+ ASSERT_EQ(target_inline_entries.size(), 0U);
const auto& overlay_entries = data->GetOverlayEntries();
ASSERT_EQ(target_entries.size(), 4U);
@@ -320,10 +330,12 @@ TEST(IdmapTests, CreateIdmapDataDoNotRewriteNonOverlayResourceId) {
const auto& target_entries = data->GetTargetEntries();
ASSERT_EQ(target_entries.size(), 2U);
- ASSERT_TARGET_ENTRY(target_entries[0], R::target::string::str1, Res_value::TYPE_REFERENCE,
+ ASSERT_TARGET_ENTRY(target_entries[0], R::target::string::str1,
0x0104000a); // -> android:string/ok
- ASSERT_TARGET_ENTRY(target_entries[1], R::target::string::str3, Res_value::TYPE_DYNAMIC_REFERENCE,
- R::overlay::string::str3);
+ ASSERT_TARGET_ENTRY(target_entries[1], R::target::string::str3, R::overlay::string::str3);
+
+ const auto& target_inline_entries = data->GetTargetInlineEntries();
+ ASSERT_EQ(target_inline_entries.size(), 0U);
const auto& overlay_entries = data->GetOverlayEntries();
ASSERT_EQ(overlay_entries.size(), 1U);
@@ -342,13 +354,17 @@ TEST(IdmapTests, CreateIdmapDataInlineResources) {
ASSERT_TRUE(idmap_data) << idmap_data.GetErrorMessage();
auto& data = *idmap_data;
- constexpr size_t overlay_string_pool_size = 8U;
const auto& target_entries = data->GetTargetEntries();
- ASSERT_EQ(target_entries.size(), 2U);
- ASSERT_TARGET_ENTRY(target_entries[0], R::target::integer::int1, Res_value::TYPE_INT_DEC,
- 73U); // -> 73
- ASSERT_TARGET_ENTRY(target_entries[1], R::target::string::str1, Res_value::TYPE_STRING,
- overlay_string_pool_size + 0U); // -> "Hello World"
+ ASSERT_EQ(target_entries.size(), 0U);
+
+ constexpr size_t overlay_string_pool_size = 8U;
+ const auto& target_inline_entries = data->GetTargetInlineEntries();
+ ASSERT_EQ(target_inline_entries.size(), 2U);
+ ASSERT_TARGET_INLINE_ENTRY(target_inline_entries[0], R::target::integer::int1,
+ Res_value::TYPE_INT_DEC, 73U); // -> 73
+ ASSERT_TARGET_INLINE_ENTRY(target_inline_entries[1], R::target::string::str1,
+ Res_value::TYPE_STRING,
+ overlay_string_pool_size + 0U); // -> "Hello World"
const auto& overlay_entries = data->GetOverlayEntries();
ASSERT_EQ(overlay_entries.size(), 0U);
@@ -479,9 +495,9 @@ TEST(IdmapTests, IdmapHeaderIsUpToDate) {
ASSERT_FALSE(bad_enforce_header->IsUpToDate(target_apk_path.c_str(), overlay_apk_path.c_str(),
PolicyFlags::PUBLIC, /* enforce_overlayable */ true));
- // target path: bytes (0x15, 0x114)
+ // target path: bytes (0x18, 0x117)
std::string bad_target_path_string(stream.str());
- bad_target_path_string[0x15] = '\0';
+ bad_target_path_string[0x18] = '\0';
std::stringstream bad_target_path_stream(bad_target_path_string);
std::unique_ptr<const IdmapHeader> bad_target_path_header =
IdmapHeader::FromBinaryStream(bad_target_path_stream);
@@ -490,9 +506,9 @@ TEST(IdmapTests, IdmapHeaderIsUpToDate) {
ASSERT_FALSE(bad_magic_header->IsUpToDate(target_apk_path.c_str(), overlay_apk_path.c_str(),
PolicyFlags::PUBLIC, /* enforce_overlayable */ true));
- // overlay path: bytes (0x115, 0x214)
+ // overlay path: bytes (0x118, 0x217)
std::string bad_overlay_path_string(stream.str());
- bad_overlay_path_string[0x115] = '\0';
+ bad_overlay_path_string[0x118] = '\0';
std::stringstream bad_overlay_path_stream(bad_overlay_path_string);
std::unique_ptr<const IdmapHeader> bad_overlay_path_header =
IdmapHeader::FromBinaryStream(bad_overlay_path_stream);
diff --git a/cmds/idmap2/tests/PrettyPrintVisitorTests.cpp b/cmds/idmap2/tests/PrettyPrintVisitorTests.cpp
index 9a10079772bf..d30fbfcb1d3c 100644
--- a/cmds/idmap2/tests/PrettyPrintVisitorTests.cpp
+++ b/cmds/idmap2/tests/PrettyPrintVisitorTests.cpp
@@ -56,7 +56,8 @@ TEST(PrettyPrintVisitorTests, CreatePrettyPrintVisitor) {
ASSERT_NE(stream.str().find("target apk path : "), std::string::npos);
ASSERT_NE(stream.str().find("overlay apk path : "), std::string::npos);
- ASSERT_NE(stream.str().find(R::target::integer::literal::int1 + " -> 0x7f010000 integer/int1\n"),
+ ASSERT_NE(stream.str().find(R::target::integer::literal::int1 +
+ " -> 0x7f010000 (integer/int1 -> integer/int1)\n"),
std::string::npos);
}
@@ -75,7 +76,7 @@ TEST(PrettyPrintVisitorTests, CreatePrettyPrintVisitorWithoutAccessToApks) {
ASSERT_NE(stream.str().find("target apk path : "), std::string::npos);
ASSERT_NE(stream.str().find("overlay apk path : "), std::string::npos);
- ASSERT_NE(stream.str().find("0x7f020000 -> 0x7f020000\n"), std::string::npos);
+ ASSERT_NE(stream.str().find("0x7f020000 -> 0x7f020000 (\?\?\? -> \?\?\?)\n"), std::string::npos);
}
} // namespace android::idmap2
diff --git a/cmds/idmap2/tests/RawPrintVisitorTests.cpp b/cmds/idmap2/tests/RawPrintVisitorTests.cpp
index b268d5add141..95bd94733ab3 100644
--- a/cmds/idmap2/tests/RawPrintVisitorTests.cpp
+++ b/cmds/idmap2/tests/RawPrintVisitorTests.cpp
@@ -65,7 +65,7 @@ TEST(RawPrintVisitorTests, CreateRawPrintVisitor) {
(*idmap)->accept(&visitor);
ASSERT_CONTAINS_REGEX(ADDRESS "504d4449 magic\n", stream.str());
- ASSERT_CONTAINS_REGEX(ADDRESS "00000004 version\n", stream.str());
+ ASSERT_CONTAINS_REGEX(ADDRESS "00000005 version\n", stream.str());
ASSERT_CONTAINS_REGEX(
StringPrintf(ADDRESS "%s target crc\n", android::idmap2::TestConstants::TARGET_CRC_STRING),
stream.str());
@@ -73,19 +73,19 @@ TEST(RawPrintVisitorTests, CreateRawPrintVisitor) {
StringPrintf(ADDRESS "%s overlay crc\n", android::idmap2::TestConstants::OVERLAY_CRC_STRING),
stream.str());
ASSERT_CONTAINS_REGEX(ADDRESS "00000001 fulfilled policies: public\n", stream.str());
- ASSERT_CONTAINS_REGEX(ADDRESS " 01 enforce overlayable\n", stream.str());
+ ASSERT_CONTAINS_REGEX(ADDRESS "00000001 enforce overlayable\n", stream.str());
ASSERT_CONTAINS_REGEX(ADDRESS " 7f target package id\n", stream.str());
ASSERT_CONTAINS_REGEX(ADDRESS " 7f overlay package id\n", stream.str());
ASSERT_CONTAINS_REGEX(ADDRESS "00000004 target entry count\n", stream.str());
ASSERT_CONTAINS_REGEX(ADDRESS "00000004 overlay entry count\n", stream.str());
ASSERT_CONTAINS_REGEX(ADDRESS "00000004 overlay entry count\n", stream.str());
ASSERT_CONTAINS_REGEX(ADDRESS "00000008 string pool index offset\n", stream.str());
- ASSERT_CONTAINS_REGEX(ADDRESS "000000b4 string pool byte length\n", stream.str());
ASSERT_CONTAINS_REGEX(ADDRESS "7f010000 target id: integer/int1\n", stream.str());
- ASSERT_CONTAINS_REGEX(ADDRESS " 07 type: reference \\(dynamic\\)\n", stream.str());
- ASSERT_CONTAINS_REGEX(ADDRESS "7f010000 value: integer/int1\n", stream.str());
+ ASSERT_CONTAINS_REGEX(ADDRESS "7f010000 overlay id: integer/int1\n", stream.str());
ASSERT_CONTAINS_REGEX(ADDRESS "7f010000 overlay id: integer/int1\n", stream.str());
ASSERT_CONTAINS_REGEX(ADDRESS "7f010000 target id: integer/int1\n", stream.str());
+ ASSERT_CONTAINS_REGEX(ADDRESS "000000b4 string pool size\n", stream.str());
+ ASSERT_CONTAINS_REGEX("000002bc: ........ string pool: ...\n", stream.str());
}
TEST(RawPrintVisitorTests, CreateRawPrintVisitorWithoutAccessToApks) {
@@ -102,22 +102,26 @@ TEST(RawPrintVisitorTests, CreateRawPrintVisitorWithoutAccessToApks) {
(*idmap)->accept(&visitor);
ASSERT_CONTAINS_REGEX(ADDRESS "504d4449 magic\n", stream.str());
- ASSERT_CONTAINS_REGEX(ADDRESS "00000004 version\n", stream.str());
+ ASSERT_CONTAINS_REGEX(ADDRESS "00000005 version\n", stream.str());
ASSERT_CONTAINS_REGEX(ADDRESS "00001234 target crc\n", stream.str());
ASSERT_CONTAINS_REGEX(ADDRESS "00005678 overlay crc\n", stream.str());
ASSERT_CONTAINS_REGEX(ADDRESS "00000011 fulfilled policies: public|signature\n", stream.str());
- ASSERT_CONTAINS_REGEX(ADDRESS " 01 enforce overlayable\n", stream.str());
+ ASSERT_CONTAINS_REGEX(ADDRESS "00000001 enforce overlayable\n", stream.str());
ASSERT_CONTAINS_REGEX(ADDRESS " 7f target package id\n", stream.str());
ASSERT_CONTAINS_REGEX(ADDRESS " 7f overlay package id\n", stream.str());
ASSERT_CONTAINS_REGEX(ADDRESS "00000003 target entry count\n", stream.str());
+ ASSERT_CONTAINS_REGEX(ADDRESS "00000001 target inline entry count\n", stream.str());
ASSERT_CONTAINS_REGEX(ADDRESS "00000003 overlay entry count\n", stream.str());
ASSERT_CONTAINS_REGEX(ADDRESS "00000000 string pool index offset\n", stream.str());
- ASSERT_CONTAINS_REGEX(ADDRESS "00000000 string pool byte length\n", stream.str());
ASSERT_CONTAINS_REGEX(ADDRESS "7f020000 target id\n", stream.str());
- ASSERT_CONTAINS_REGEX(ADDRESS " 01 type: reference\n", stream.str());
- ASSERT_CONTAINS_REGEX(ADDRESS "7f020000 value\n", stream.str());
ASSERT_CONTAINS_REGEX(ADDRESS "7f020000 overlay id\n", stream.str());
ASSERT_CONTAINS_REGEX(ADDRESS "7f020000 target id\n", stream.str());
+ ASSERT_CONTAINS_REGEX(ADDRESS " 11 type: integer\n", stream.str());
+ ASSERT_CONTAINS_REGEX(ADDRESS "12345678 data\n", stream.str());
+ ASSERT_CONTAINS_REGEX(ADDRESS "7f020000 overlay id\n", stream.str());
+ ASSERT_CONTAINS_REGEX(ADDRESS "7f030002 target id\n", stream.str());
+ ASSERT_CONTAINS_REGEX(ADDRESS "00000004 string pool size\n", stream.str());
+ ASSERT_CONTAINS_REGEX("00000278: ........ string pool: ...\n", stream.str());
}
} // namespace android::idmap2
diff --git a/cmds/idmap2/tests/ResourceMappingTests.cpp b/cmds/idmap2/tests/ResourceMappingTests.cpp
index 3ec6ac24b238..185e9292346d 100644
--- a/cmds/idmap2/tests/ResourceMappingTests.cpp
+++ b/cmds/idmap2/tests/ResourceMappingTests.cpp
@@ -77,30 +77,61 @@ Result<ResourceMapping> TestGetResourceMapping(const android::StringPiece& local
fulfilled_policies, enforce_overlayable);
}
-Result<Unit> MappingExists(const ResourceMapping& mapping, const ResourceId& target_resource,
- const uint8_t type, const uint32_t value, bool rewrite) {
+Result<Unit> MappingExists(const ResourceMapping& mapping, ResourceId target_resource,
+ ResourceId overlay_resource, bool rewrite) {
auto target_map = mapping.GetTargetToOverlayMap();
auto entry_map = target_map.find(target_resource);
if (entry_map == target_map.end()) {
return Error("Failed to find mapping for target resource");
}
- if (entry_map->second.data_type != type) {
- return Error(R"(Expected type: "0x%02x" Actual type: "0x%02x")", type,
- entry_map->second.data_type);
+ auto actual_overlay_resource = std::get_if<ResourceId>(&entry_map->second);
+ if (actual_overlay_resource == nullptr) {
+ return Error("Target resource is not mapped to an overlay resource id");
}
- if (entry_map->second.data_value != value) {
- return Error(R"(Expected value: "0x%08x" Actual value: "0x%08x")", type,
- entry_map->second.data_value);
+ if (*actual_overlay_resource != overlay_resource) {
+ return Error(R"(Expected id: "0x%02x" Actual id: "0x%02x")", overlay_resource,
+ *actual_overlay_resource);
}
auto overlay_map = mapping.GetOverlayToTargetMap();
- auto overlay_iter = overlay_map.find(entry_map->second.data_value);
+ auto overlay_iter = overlay_map.find(overlay_resource);
if ((overlay_iter != overlay_map.end()) != rewrite) {
return Error(R"(Expected rewriting: "%s")", rewrite ? "true" : "false");
}
+ if (rewrite && overlay_iter->second != target_resource) {
+ return Error(R"(Expected rewrite id: "0x%02x" Actual id: "0x%02x")", target_resource,
+ overlay_iter->second);
+ }
+
+ return Result<Unit>({});
+}
+
+Result<Unit> MappingExists(const ResourceMapping& mapping, const ResourceId& target_resource,
+ const uint8_t type, const uint32_t value) {
+ auto target_map = mapping.GetTargetToOverlayMap();
+ auto entry_map = target_map.find(target_resource);
+ if (entry_map == target_map.end()) {
+ return Error("Failed to find mapping for target resource");
+ }
+
+ auto actual_overlay_value = std::get_if<TargetValue>(&entry_map->second);
+ if (actual_overlay_value == nullptr) {
+ return Error("Target resource is not mapped to an inline value");
+ }
+
+ if (actual_overlay_value->data_type != type) {
+ return Error(R"(Expected type: "0x%02x" Actual type: "0x%02x")", type,
+ actual_overlay_value->data_type);
+ }
+
+ if (actual_overlay_value->data_value != value) {
+ return Error(R"(Expected value: "0x%08x" Actual value: "0x%08x")", type,
+ actual_overlay_value->data_value);
+ }
+
return Result<Unit>({});
}
@@ -116,14 +147,14 @@ TEST(ResourceMappingTests, ResourcesFromApkAssetsLegacy) {
ASSERT_TRUE(resources) << resources.GetErrorMessage();
auto& res = *resources;
ASSERT_EQ(res.GetTargetToOverlayMap().size(), 4U);
- ASSERT_RESULT(MappingExists(res, R::target::integer::int1, Res_value::TYPE_REFERENCE,
- R::overlay::integer::int1, false /* rewrite */));
- ASSERT_RESULT(MappingExists(res, R::target::string::str1, Res_value::TYPE_REFERENCE,
- R::overlay::string::str1, false /* rewrite */));
- ASSERT_RESULT(MappingExists(res, R::target::string::str3, Res_value::TYPE_REFERENCE,
- R::overlay::string::str3, false /* rewrite */));
- ASSERT_RESULT(MappingExists(res, R::target::string::str4, Res_value::TYPE_REFERENCE,
- R::overlay::string::str4, false /* rewrite */));
+ ASSERT_RESULT(
+ MappingExists(res, R::target::integer::int1, R::overlay::integer::int1, false /* rewrite */));
+ ASSERT_RESULT(
+ MappingExists(res, R::target::string::str1, R::overlay::string::str1, false /* rewrite */));
+ ASSERT_RESULT(
+ MappingExists(res, R::target::string::str3, R::overlay::string::str3, false /* rewrite */));
+ ASSERT_RESULT(
+ MappingExists(res, R::target::string::str4, R::overlay::string::str4, false /* rewrite */));
}
TEST(ResourceMappingTests, ResourcesFromApkAssetsNonMatchingNames) {
@@ -138,12 +169,12 @@ TEST(ResourceMappingTests, ResourcesFromApkAssetsNonMatchingNames) {
ASSERT_TRUE(resources) << resources.GetErrorMessage();
auto& res = *resources;
ASSERT_EQ(res.GetTargetToOverlayMap().size(), 3U);
- ASSERT_RESULT(MappingExists(res, R::target::string::str1, Res_value::TYPE_DYNAMIC_REFERENCE,
- R::overlay::string::str4, true /* rewrite */));
- ASSERT_RESULT(MappingExists(res, R::target::string::str3, Res_value::TYPE_DYNAMIC_REFERENCE,
- R::overlay::string::str1, true /* rewrite */));
- ASSERT_RESULT(MappingExists(res, R::target::string::str4, Res_value::TYPE_DYNAMIC_REFERENCE,
- R::overlay::string::str3, true /* rewrite */));
+ ASSERT_RESULT(
+ MappingExists(res, R::target::string::str1, R::overlay::string::str4, true /* rewrite */));
+ ASSERT_RESULT(
+ MappingExists(res, R::target::string::str3, R::overlay::string::str1, true /* rewrite */));
+ ASSERT_RESULT(
+ MappingExists(res, R::target::string::str4, R::overlay::string::str3, true /* rewrite */));
}
TEST(ResourceMappingTests, DoNotRewriteNonOverlayResourceId) {
@@ -159,10 +190,9 @@ TEST(ResourceMappingTests, DoNotRewriteNonOverlayResourceId) {
auto& res = *resources;
ASSERT_EQ(res.GetTargetToOverlayMap().size(), 2U);
ASSERT_EQ(res.GetOverlayToTargetMap().size(), 1U);
- ASSERT_RESULT(MappingExists(res, R::target::string::str1, Res_value::TYPE_REFERENCE, 0x0104000a,
+ ASSERT_RESULT(MappingExists(res, R::target::string::str1, 0x0104000a,
false /* rewrite */)); // -> android:string/ok
- ASSERT_RESULT(MappingExists(res, R::target::string::str3, Res_value::TYPE_DYNAMIC_REFERENCE,
- 0x7f020001, true /* rewrite */));
+ ASSERT_RESULT(MappingExists(res, R::target::string::str3, 0x7f020001, true /* rewrite */));
}
TEST(ResourceMappingTests, InlineResources) {
@@ -180,10 +210,8 @@ TEST(ResourceMappingTests, InlineResources) {
ASSERT_EQ(res.GetTargetToOverlayMap().size(), 2U);
ASSERT_EQ(res.GetOverlayToTargetMap().size(), 0U);
ASSERT_RESULT(MappingExists(res, R::target::string::str1, Res_value::TYPE_STRING,
- overlay_string_pool_size + 0U,
- false /* rewrite */)); // -> "Hello World"
- ASSERT_RESULT(MappingExists(res, R::target::integer::int1, Res_value::TYPE_INT_DEC, 73U,
- false /* rewrite */)); // -> 73
+ overlay_string_pool_size + 0U)); // -> "Hello World"
+ ASSERT_RESULT(MappingExists(res, R::target::integer::int1, Res_value::TYPE_INT_DEC, 73U));
}
TEST(ResourceMappingTests, CreateIdmapFromApkAssetsPolicySystemPublic) {
@@ -195,13 +223,13 @@ TEST(ResourceMappingTests, CreateIdmapFromApkAssetsPolicySystemPublic) {
ASSERT_TRUE(resources) << resources.GetErrorMessage();
auto& res = *resources;
ASSERT_EQ(res.GetTargetToOverlayMap().size(), 3U);
- ASSERT_RESULT(MappingExists(res, R::target::string::policy_public, Res_value::TYPE_REFERENCE,
+ ASSERT_RESULT(MappingExists(res, R::target::string::policy_public,
R::system_overlay::string::policy_public, false /* rewrite */));
- ASSERT_RESULT(MappingExists(res, R::target::string::policy_system, Res_value::TYPE_REFERENCE,
+ ASSERT_RESULT(MappingExists(res, R::target::string::policy_system,
R::system_overlay::string::policy_system, false /* rewrite */));
- ASSERT_RESULT(
- MappingExists(res, R::target::string::policy_system_vendor, Res_value::TYPE_REFERENCE,
- R::system_overlay::string::policy_system_vendor, false /* rewrite */));
+ ASSERT_RESULT(MappingExists(res, R::target::string::policy_system_vendor,
+ R::system_overlay::string::policy_system_vendor,
+ false /* rewrite */));
}
// Resources that are not declared as overlayable and resources that a protected by policies the
@@ -215,15 +243,15 @@ TEST(ResourceMappingTests, CreateIdmapFromApkAssetsPolicySystemPublicInvalid) {
ASSERT_TRUE(resources) << resources.GetErrorMessage();
auto& res = *resources;
ASSERT_EQ(res.GetTargetToOverlayMap().size(), 3U);
- ASSERT_RESULT(MappingExists(res, R::target::string::policy_public, Res_value::TYPE_REFERENCE,
+ ASSERT_RESULT(MappingExists(res, R::target::string::policy_public,
R::system_overlay_invalid::string::policy_public,
false /* rewrite */));
- ASSERT_RESULT(MappingExists(res, R::target::string::policy_system, Res_value::TYPE_REFERENCE,
+ ASSERT_RESULT(MappingExists(res, R::target::string::policy_system,
R::system_overlay_invalid::string::policy_system,
false /* rewrite */));
- ASSERT_RESULT(
- MappingExists(res, R::target::string::policy_system_vendor, Res_value::TYPE_REFERENCE,
- R::system_overlay_invalid::string::policy_system_vendor, false /* rewrite */));
+ ASSERT_RESULT(MappingExists(res, R::target::string::policy_system_vendor,
+ R::system_overlay_invalid::string::policy_system_vendor,
+ false /* rewrite */));
}
// Resources that are not declared as overlayable and resources that a protected by policies the
@@ -238,37 +266,36 @@ TEST(ResourceMappingTests, ResourcesFromApkAssetsPolicySystemPublicInvalidIgnore
ASSERT_TRUE(resources) << resources.GetErrorMessage();
auto& res = *resources;
ASSERT_EQ(res.GetTargetToOverlayMap().size(), 11U);
- ASSERT_RESULT(MappingExists(res, R::target::string::not_overlayable, Res_value::TYPE_REFERENCE,
+ ASSERT_RESULT(MappingExists(res, R::target::string::not_overlayable,
R::system_overlay_invalid::string::not_overlayable,
false /* rewrite */));
- ASSERT_RESULT(MappingExists(res, R::target::string::other, Res_value::TYPE_REFERENCE,
+ ASSERT_RESULT(MappingExists(res, R::target::string::other,
R::system_overlay_invalid::string::other, false /* rewrite */));
- ASSERT_RESULT(MappingExists(res, R::target::string::policy_actor, Res_value::TYPE_REFERENCE,
+ ASSERT_RESULT(MappingExists(res, R::target::string::policy_actor,
R::system_overlay_invalid::string::policy_actor,
false /* rewrite */));
- ASSERT_RESULT(MappingExists(res, R::target::string::policy_odm, Res_value::TYPE_REFERENCE,
+ ASSERT_RESULT(MappingExists(res, R::target::string::policy_odm,
R::system_overlay_invalid::string::policy_odm, false /* rewrite */));
- ASSERT_RESULT(MappingExists(res, R::target::string::policy_oem, Res_value::TYPE_REFERENCE,
+ ASSERT_RESULT(MappingExists(res, R::target::string::policy_oem,
R::system_overlay_invalid::string::policy_oem, false /* rewrite */));
- ASSERT_RESULT(MappingExists(res, R::target::string::policy_product, Res_value::TYPE_REFERENCE,
+ ASSERT_RESULT(MappingExists(res, R::target::string::policy_product,
R::system_overlay_invalid::string::policy_product,
false /* rewrite */));
- ASSERT_RESULT(MappingExists(res, R::target::string::policy_public, Res_value::TYPE_REFERENCE,
+ ASSERT_RESULT(MappingExists(res, R::target::string::policy_public,
R::system_overlay_invalid::string::policy_public,
false /* rewrite */));
ASSERT_RESULT(MappingExists(res, R::target::string::policy_config_signature,
- Res_value::TYPE_REFERENCE,
R::system_overlay_invalid::string::policy_config_signature,
false /* rewrite */));
- ASSERT_RESULT(MappingExists(res, R::target::string::policy_signature, Res_value::TYPE_REFERENCE,
+ ASSERT_RESULT(MappingExists(res, R::target::string::policy_signature,
R::system_overlay_invalid::string::policy_signature,
false /* rewrite */));
- ASSERT_RESULT(MappingExists(res, R::target::string::policy_system, Res_value::TYPE_REFERENCE,
+ ASSERT_RESULT(MappingExists(res, R::target::string::policy_system,
R::system_overlay_invalid::string::policy_system,
false /* rewrite */));
- ASSERT_RESULT(
- MappingExists(res, R::target::string::policy_system_vendor, Res_value::TYPE_REFERENCE,
- R::system_overlay_invalid::string::policy_system_vendor, false /* rewrite */));
+ ASSERT_RESULT(MappingExists(res, R::target::string::policy_system_vendor,
+ R::system_overlay_invalid::string::policy_system_vendor,
+ false /* rewrite */));
}
// Overlays that do not target an <overlayable> tag can overlay resources defined within any
@@ -281,14 +308,14 @@ TEST(ResourceMappingTests, ResourcesFromApkAssetsNoDefinedOverlayableAndNoTarget
ASSERT_TRUE(resources) << resources.GetErrorMessage();
auto& res = *resources;
ASSERT_EQ(res.GetTargetToOverlayMap().size(), 4U);
- ASSERT_RESULT(MappingExists(res, R::target::integer::int1, Res_value::TYPE_REFERENCE,
- R::overlay::integer::int1, false /* rewrite */));
- ASSERT_RESULT(MappingExists(res, R::target::string::str1, Res_value::TYPE_REFERENCE,
- R::overlay::string::str1, false /* rewrite */));
- ASSERT_RESULT(MappingExists(res, R::target::string::str3, Res_value::TYPE_REFERENCE,
- R::overlay::string::str3, false /* rewrite */));
- ASSERT_RESULT(MappingExists(res, R::target::string::str4, Res_value::TYPE_REFERENCE,
- R::overlay::string::str4, false /* rewrite */));
+ ASSERT_RESULT(
+ MappingExists(res, R::target::integer::int1, R::overlay::integer::int1, false /* rewrite */));
+ ASSERT_RESULT(
+ MappingExists(res, R::target::string::str1, R::overlay::string::str1, false /* rewrite */));
+ ASSERT_RESULT(
+ MappingExists(res, R::target::string::str3, R::overlay::string::str3, false /* rewrite */));
+ ASSERT_RESULT(
+ MappingExists(res, R::target::string::str4, R::overlay::string::str4, false /* rewrite */));
}
// Overlays that are neither pre-installed nor signed with the same signature as the target cannot
@@ -302,9 +329,9 @@ TEST(ResourceMappingTests, ResourcesFromApkAssetsDefaultPoliciesPublicFail) {
ASSERT_EQ(resources->GetTargetToOverlayMap().size(), 0U);
}
-// Overlays that are pre-installed or are signed with the same signature as the target or are signed
-// with the same signature as the reference package can overlay packages that have not defined
-// overlayable resources.
+// Overlays that are pre-installed or are signed with the same signature as the target or are
+// signed with the same signature as the reference package can overlay packages that have not
+// defined overlayable resources.
TEST(ResourceMappingTests, ResourcesFromApkAssetsDefaultPolicies) {
auto CheckEntries = [&](const PolicyBitmask& fulfilled_policies) -> void {
auto resources = TestGetResourceMapping("/target/target-no-overlayable.apk",
@@ -315,39 +342,38 @@ TEST(ResourceMappingTests, ResourcesFromApkAssetsDefaultPolicies) {
ASSERT_TRUE(resources) << resources.GetErrorMessage();
auto& res = *resources;
ASSERT_EQ(resources->GetTargetToOverlayMap().size(), 11U);
- ASSERT_RESULT(MappingExists(res, R::target::string::not_overlayable, Res_value::TYPE_REFERENCE,
+ ASSERT_RESULT(MappingExists(res, R::target::string::not_overlayable,
R::system_overlay_invalid::string::not_overlayable,
false /* rewrite */));
- ASSERT_RESULT(MappingExists(res, R::target::string::other, Res_value::TYPE_REFERENCE,
+ ASSERT_RESULT(MappingExists(res, R::target::string::other,
R::system_overlay_invalid::string::other, false /* rewrite */));
- ASSERT_RESULT(MappingExists(res, R::target::string::policy_actor, Res_value::TYPE_REFERENCE,
+ ASSERT_RESULT(MappingExists(res, R::target::string::policy_actor,
R::system_overlay_invalid::string::policy_actor,
false /* rewrite */));
- ASSERT_RESULT(MappingExists(res, R::target::string::policy_odm, Res_value::TYPE_REFERENCE,
+ ASSERT_RESULT(MappingExists(res, R::target::string::policy_odm,
R::system_overlay_invalid::string::policy_odm,
false /* rewrite */));
- ASSERT_RESULT(MappingExists(res, R::target::string::policy_oem, Res_value::TYPE_REFERENCE,
+ ASSERT_RESULT(MappingExists(res, R::target::string::policy_oem,
R::system_overlay_invalid::string::policy_oem,
false /* rewrite */));
- ASSERT_RESULT(MappingExists(res, R::target::string::policy_product, Res_value::TYPE_REFERENCE,
+ ASSERT_RESULT(MappingExists(res, R::target::string::policy_product,
R::system_overlay_invalid::string::policy_product,
false /* rewrite */));
- ASSERT_RESULT(MappingExists(res, R::target::string::policy_public, Res_value::TYPE_REFERENCE,
+ ASSERT_RESULT(MappingExists(res, R::target::string::policy_public,
R::system_overlay_invalid::string::policy_public,
false /* rewrite */));
ASSERT_RESULT(MappingExists(res, R::target::string::policy_config_signature,
- Res_value::TYPE_REFERENCE,
R::system_overlay_invalid::string::policy_config_signature,
false /* rewrite */));
- ASSERT_RESULT(MappingExists(res, R::target::string::policy_signature, Res_value::TYPE_REFERENCE,
+ ASSERT_RESULT(MappingExists(res, R::target::string::policy_signature,
R::system_overlay_invalid::string::policy_signature,
false /* rewrite */));
- ASSERT_RESULT(MappingExists(res, R::target::string::policy_system, Res_value::TYPE_REFERENCE,
+ ASSERT_RESULT(MappingExists(res, R::target::string::policy_system,
R::system_overlay_invalid::string::policy_system,
false /* rewrite */));
- ASSERT_RESULT(MappingExists(
- res, R::target::string::policy_system_vendor, Res_value::TYPE_REFERENCE,
- R::system_overlay_invalid::string::policy_system_vendor, false /* rewrite */));
+ ASSERT_RESULT(MappingExists(res, R::target::string::policy_system_vendor,
+ R::system_overlay_invalid::string::policy_system_vendor,
+ false /* rewrite */));
};
CheckEntries(PolicyFlags::SIGNATURE);
diff --git a/cmds/idmap2/tests/TestConstants.h b/cmds/idmap2/tests/TestConstants.h
index 9641f6b55670..69575b8f9c01 100644
--- a/cmds/idmap2/tests/TestConstants.h
+++ b/cmds/idmap2/tests/TestConstants.h
@@ -19,7 +19,7 @@
namespace android::idmap2::TestConstants {
-constexpr const auto TARGET_CRC = 0x7c2d4719;
+constexpr const auto TARGET_CRC = 0x7c2d4719;
constexpr const auto TARGET_CRC_STRING = "7c2d4719";
constexpr const auto OVERLAY_CRC = 0x5afff726;
diff --git a/cmds/idmap2/tests/TestHelpers.h b/cmds/idmap2/tests/TestHelpers.h
index b599dcb0069a..d0a8e3db8eca 100644
--- a/cmds/idmap2/tests/TestHelpers.h
+++ b/cmds/idmap2/tests/TestHelpers.h
@@ -30,7 +30,7 @@ const unsigned char idmap_raw_data[] = {
0x49, 0x44, 0x4d, 0x50,
// 0x4: version
- 0x04, 0x00, 0x00, 0x00,
+ 0x05, 0x00, 0x00, 0x00,
// 0x8: target crc
0x34, 0x12, 0x00, 0x00,
@@ -42,9 +42,9 @@ const unsigned char idmap_raw_data[] = {
0x11, 0x00, 0x00, 0x00,
// 0x14: enforce overlayable
- 0x01,
+ 0x01, 0x00, 0x00, 0x00,
- // 0x15: target path "targetX.apk"
+ // 0x18: target path "targetX.apk"
0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x58, 0x2e, 0x61, 0x70, 0x6b, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
@@ -62,7 +62,7 @@ const unsigned char idmap_raw_data[] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- // 0x115: overlay path "overlayX.apk"
+ // 0x118: overlay path "overlayX.apk"
0x6f, 0x76, 0x65, 0x72, 0x6c, 0x61, 0x79, 0x58, 0x2e, 0x61, 0x70, 0x6b, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
@@ -80,71 +80,89 @@ const unsigned char idmap_raw_data[] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- // 0x215: debug string
- // string length, including terminating null
- 0x08, 0x00, 0x00, 0x00,
+ // 0x218: debug string
+ // string length,
+ 0x05, 0x00, 0x00, 0x00,
- // string contents "debug\0\0\0" (padded to word alignment)
+ // 0x21c string contents "debug\0\0\0" (padded to word alignment)
0x64, 0x65, 0x62, 0x75, 0x67, 0x00, 0x00, 0x00,
// DATA HEADER
- // 0x221: target_package_id
+ // 0x224: target_package_id
0x7f,
- // 0x222: overlay_package_id
+ // 0x225: overlay_package_id
0x7f,
- // 0x223: target_entry_count
- 0x03, 0x00, 0x00, 0x00,
+ // 0x226: padding
+ 0x00, 0x00,
- // 0x227: overlay_entry_count
+ // 0x228: target_entry_count
0x03, 0x00, 0x00, 0x00,
- // 0x22b: string_pool_offset
- 0x00, 0x00, 0x00, 0x00,
+ // 0x22c: target_inline_entry_count
+ 0x01, 0x00, 0x00, 0x00,
+
+ // 0x230: overlay_entry_count
+ 0x03, 0x00, 0x00, 0x00,
- // 0x22f: string_pool_byte_length
+ // 0x234: string_pool_offset
0x00, 0x00, 0x00, 0x00,
// TARGET ENTRIES
- // 0x233: 0x7f020000
+ // 0x238: target id (0x7f020000)
0x00, 0x00, 0x02, 0x7f,
- // 0x237: TYPE_REFERENCE
- 0x01,
-
- // 0x238: 0x7f020000
+ // 0x23c: overlay_id (0x7f020000)
0x00, 0x00, 0x02, 0x7f,
- // 0x23c: 0x7f030000
+ // 0x240: target id (0x7f030000)
0x00, 0x00, 0x03, 0x7f,
- // 0x240: TYPE_REFERENCE
- 0x01,
-
- // 0x241: 0x7f030000
+ // 0x244: overlay_id (0x7f030000)
0x00, 0x00, 0x03, 0x7f,
- // 0x245: 0x7f030002
+ // 0x248: target id (0x7f030002)
0x02, 0x00, 0x03, 0x7f,
- // 0x249: TYPE_REFERENCE
- 0x01,
-
- // 0x24a: 0x7f030001
+ // 0x24c: overlay_id (0x7f030001)
0x01, 0x00, 0x03, 0x7f,
+ // INLINE TARGET ENTRIES
+
+ // 0x250: target_id
+ 0x00, 0x00, 0x04, 0x7f,
+
+ // 0x254: Res_value::size (value ignored by idmap)
+ 0x08, 0x00,
+
+ // 0x256: Res_value::res0 (value ignored by idmap)
+ 0x00,
+
+ // 0x257: Res_value::dataType (TYPE_INT_HEX)
+ 0x11,
+
+ // 0x258: Res_value::data
+ 0x78, 0x56, 0x34, 0x12,
+
// OVERLAY ENTRIES
- // 0x24e: 0x7f020000 -> 0x7f020000
+ // 0x25c: 0x7f020000 -> 0x7f020000
0x00, 0x00, 0x02, 0x7f, 0x00, 0x00, 0x02, 0x7f,
- // 0x256: 0x7f030000 -> 0x7f030000
+ // 0x264: 0x7f030000 -> 0x7f030000
0x00, 0x00, 0x03, 0x7f, 0x00, 0x00, 0x03, 0x7f,
- // 0x25e: 0x7f030001 -> 0x7f030002
- 0x01, 0x00, 0x03, 0x7f, 0x02, 0x00, 0x03, 0x7f};
+ // 0x26c: 0x7f030001 -> 0x7f030002
+ 0x01, 0x00, 0x03, 0x7f, 0x02, 0x00, 0x03, 0x7f,
+
+ // 0x274: string pool
+ // string length,
+ 0x04, 0x00, 0x00, 0x00,
+
+ // 0x278 string contents "test" (padded to word alignment)
+ 0x74, 0x65, 0x73, 0x74};
-const unsigned int idmap_raw_data_len = 0x266;
+const unsigned int idmap_raw_data_len = 0x27c;
std::string GetTestDataPath();
diff --git a/cmds/statsd/Android.bp b/cmds/statsd/Android.bp
index 88db1d84df8e..012450d73266 100644
--- a/cmds/statsd/Android.bp
+++ b/cmds/statsd/Android.bp
@@ -430,6 +430,30 @@ java_library {
},
}
+java_library {
+ name: "statsdprotonano",
+ sdk_version: "9",
+ proto: {
+ type: "nano",
+ output_params: ["store_unknown_fields=true"],
+ include_dirs: ["external/protobuf/src"],
+ },
+ srcs: [
+ "src/atoms.proto",
+ "src/shell/shell_config.proto",
+ "src/shell/shell_data.proto",
+ "src/stats_log.proto",
+ "src/statsd_config.proto",
+ ],
+ static_libs: [
+ "platformprotosnano",
+ ],
+ // Protos have lots of MissingOverride and similar.
+ errorprone: {
+ javacflags: ["-XepDisableAllChecks"],
+ },
+}
+
// Filegroup for statsd config proto definition.
filegroup {
name: "statsd-config-proto-def",
diff --git a/cmds/statsd/src/atoms.proto b/cmds/statsd/src/atoms.proto
index 6eba5c691722..3d67e6574652 100644
--- a/cmds/statsd/src/atoms.proto
+++ b/cmds/statsd/src/atoms.proto
@@ -497,13 +497,14 @@ message Atom {
ModemRestart modem_restart = 312 [(module) = "telephony"];
CarrierIdMismatchEvent carrier_id_mismatch_event = 313 [(module) = "telephony"];
CarrierIdMatchingTable carrier_id_table_update = 314 [(module) = "telephony"];
+ DataStallRecoveryReported data_stall_recovery_reported = 315 [(module) = "telephony"];
// StatsdStats tracks platform atoms with ids upto 500.
// Update StatsdStats::kMaxPushedAtomId when atom ids here approach that value.
}
// Pulled events will start at field 10000.
- // Next: 10089
+ // Next: 10092
oneof pulled {
WifiBytesTransfer wifi_bytes_transfer = 10000 [(module) = "framework"];
WifiBytesTransferByFgBg wifi_bytes_transfer_by_fg_bg = 10001 [(module) = "framework"];
@@ -605,6 +606,9 @@ message Atom {
IncomingSms incoming_sms = 10086 [(module) = "telephony"];
OutgoingSms outgoing_sms = 10087 [(module) = "telephony"];
CarrierIdMatchingTable carrier_id_table_version = 10088 [(module) = "telephony"];
+ DataCallSession data_call_session = 10089 [(module) = "telephony"];
+ CellularServiceState cellular_service_state = 10090 [(module) = "telephony"];
+ CellularDataServiceSwitch cellular_data_service_switch = 10091 [(module) = "telephony"];
}
// DO NOT USE field numbers above 100,000 in AOSP.
@@ -10396,7 +10400,7 @@ message VoiceCallSession {
// Number of other calls going on during call termination, for the same SIM slot.
optional int32 concurrent_call_count_at_end = 14;
- // Index of the SIM is used, 0 for single-SIM devices.
+ // Index of the SIM used, 0 for single-SIM devices.
optional int32 sim_slot_index = 15;
// Whether the device was in multi-SIM mode (with multiple active SIM profiles).
@@ -10448,7 +10452,7 @@ message VoiceCallRatUsage {
// Radio access technology.
optional android.telephony.NetworkTypeEnum rat = 2;
- // Total duration that voice calls spent on this carrier and RAT.
+ // Total duration that voice calls spent on this carrier and RAT, rounded to 5 minute.
optional int64 total_duration_seconds = 3;
// Total number of calls using this carrier and RAT.
@@ -10457,6 +10461,82 @@ message VoiceCallRatUsage {
}
/**
+ * Pulls amount of time spend in each cellular service state.
+ *
+ * Each pull creates multiple atoms, one for each SIM slot/carrier/RAT(including ENDC), the order of
+ * which is irrelevant to time. If multi SIM settings changes during the period, durations will be
+ * counted separately before and after the change. Airplane mode does not count towards durations.
+ *
+ * Pulled from:
+ * frameworks/opt/telephony/src/java/com/android/internal/telephony/metrics/MetricsCollector.java
+ */
+message CellularServiceState {
+ // Radio access technology (RAT) for voice.
+ // NETWORK_TYPE_UNKNOWN when the device is out of service.
+ // NETWORK_TYPE_IWLAN when the device is using VoWiFi.
+ optional android.telephony.NetworkTypeEnum voice_rat = 1;
+
+ // Radio access technology (RAT) for data.
+ // NETWORK_TYPE_UNKNOWN when the device is out of service.
+ // Only cellular RATs are valid and show where the device is camped.
+ optional android.telephony.NetworkTypeEnum data_rat = 2;
+
+ // Whether the device was in roaming (domestic or international) for voice.
+ optional android.telephony.RoamingTypeEnum voice_roaming_type = 3;
+
+ // Whether the device was in roaming (domestic or international) for data.
+ optional android.telephony.RoamingTypeEnum data_roaming_type = 4;
+
+ // Whether the device is on LTE and has access to NR NSA, i.e. cell supports 5G (ENDC) and UE
+ // registration (attach/TAU) indicates ENDC is not restricted.
+ optional bool is_endc = 5;
+
+ // Index of the SIM used, 0 for single-SIM devices.
+ optional int32 sim_slot_index = 6;
+
+ // Whether the device was in multi-SIM mode (with multiple active SIM profiles).
+ optional bool is_multi_sim = 7;
+
+ // Carrier ID of the SIM card.
+ // See https://source.android.com/devices/tech/config/carrierid.
+ optional int32 carrier_id = 8;
+
+ // Total time spent in this service state, rounded to 5 minutes.
+ optional int32 total_time_seconds = 9;
+}
+
+/**
+ * Pulls the number of times cellular data service state switches.
+ *
+ * Each pull creates multiple atoms, one for each RAT combination, the order of which is irrelevant
+ * to time. Switches for different SIM slots, carrier IDs, or multi-SIM settings are counted
+ * separately.
+ *
+ * Pulled from:
+ * frameworks/opt/telephony/src/java/com/android/internal/telephony/metrics/MetricsCollector.java
+ */
+message CellularDataServiceSwitch {
+ // Cellular RAT of the DATA domain from where the switch occurred.
+ optional android.telephony.NetworkTypeEnum rat_from = 1;
+
+ // Cellular RAT of the DATA domain to where the switch occurred.
+ optional android.telephony.NetworkTypeEnum rat_to = 2;
+
+ // Index of the SIM used, 0 for single-SIM devices.
+ optional int32 sim_slot_index = 3;
+
+ // Whether the device was in multi-SIM mode (with multiple active SIM profiles).
+ optional bool is_multi_sim = 4;
+
+ // Carrier ID of the SIM card.
+ // See https://source.android.com/devices/tech/config/carrierid.
+ optional int32 carrier_id = 5;
+
+ // Number of switches from rat_from to rat_to.
+ optional int32 switch_count = 6;
+}
+
+/**
* Pulls the number of active SIM slots and SIMs/eSIM profiles.
*
* Pulled from:
@@ -10525,7 +10605,7 @@ message IncomingSms {
// Whether the SMS was received while roaming.
optional bool is_roaming = 9;
- // Index of the SIM is used, 0 for single-SIM devices.
+ // Index of the SIM used, 0 for single-SIM devices.
optional int32 sim_slot_index = 10;
// Whether the device was in multi-SIM mode (with multiple active SIM profiles).
@@ -10577,7 +10657,7 @@ message OutgoingSms {
// Whether the default SMS application generated the SMS (regardless of which application).
optional bool is_from_default_app = 7;
- // Index of the SIM is used, 0 for single-SIM devices.
+ // Index of the SIM used, 0 for single-SIM devices.
optional int32 sim_slot_index = 8;
// Whether the device was in multi-SIM mode (with multiple active SIM profiles).
@@ -10672,6 +10752,104 @@ message CarrierIdMatchingTable {
}
/**
+ * Pulls information for a single data call session
+ *
+ * Each pull creates multiple atoms, one for each data call session.
+ * The sequence is randomized when pulled.
+ *
+ * Pulled from:
+ * frameworks/opt/telephony/src/java/com/android/internal/telephony/metrics/MetricsCollector.java
+ */
+message DataCallSession {
+ // A random number to be used as dimension to capture multiple atoms
+ optional int32 dimension = 1;
+
+ // Whether the device was in multi-SIM mode (with multiple active SIM profiles).
+ optional bool is_multi_sim = 2;
+
+ // Whether the call was made with an eSIM profile.
+ optional bool is_esim = 3;
+
+ // Data profile of this call (for what purpose this call was made)
+ optional android.telephony.DataProfileEnum profile = 4;
+
+ // APN type bitmask of the APN used:
+ // @ApnType in frameworks/base/telephony/java/android/telephony/Annotation.java.
+ optional int32 apn_type_bitmask = 5;
+
+ // Carrier ID of the SIM
+ // See https://source.android.com/devices/tech/config/carrierid.
+ optional int32 carrier_id = 6;
+
+ // Whether the subscription is roaming
+ optional bool is_roaming = 7;
+
+ // Data RAT when the call ended, can be IWLAN for IMS/MMS, otherwise should be WWAN PS RAT.
+ // In the case that the connection hasn't ended yet, this field holds the current RAT.
+ // In the case the call ended due to Out Of Service (OOS),
+ // this field should be the last known RAT.
+ optional android.telephony.NetworkTypeEnum rat_at_end = 8;
+
+ // Was the data call ended due to OOS
+ optional bool oos_at_end = 9;
+
+ // Number of RAT switches during the data call
+ optional int64 rat_switch_count = 10;
+
+ // Whether the call is on an opportunistic subscription
+ optional bool is_opportunistic = 11;
+
+ // Packet data protocol used
+ optional android.telephony.ApnProtocolEnum ip_type = 12;
+
+ // Whether the data call terminated before being established
+ optional bool setup_failed = 13;
+
+ // Reason why the data call terminated, as in RIL_DataCallFailCause from ril.h
+ optional int32 failure_cause = 14;
+
+ // Suggested retry back-off timer value from RIL
+ optional int32 suggested_retry_millis = 15;
+
+ // Why the data call was deactivated
+ // Set by telephony for MO deactivations (unrelated to failure_cause)
+ optional android.telephony.DataDeactivateReasonEnum deactivate_reason = 16;
+
+ // Duration of the data call, rounded into the closest 5 minutes.
+ optional int64 duration_minutes = 17;
+
+ // Whether the data call is still connected when the atom is collected.
+ optional bool ongoing = 18;
+}
+
+/**
+ * Logs data stall recovery event
+ *
+ * Logged from:
+ * frameworks/opt/telephony/src/java/com/android/internal/telephony/dataconnection/DcTracker.java
+ */
+message DataStallRecoveryReported {
+ // Carrier ID of the SIM
+ // See https://source.android.com/devices/tech/config/carrierid.
+ optional int32 carrier_id = 1;
+
+ // Data RAT when the stall happened
+ optional android.telephony.NetworkTypeEnum rat = 2;
+
+ // Signal strength when stall happened
+ optional android.telephony.SignalStrengthEnum signal_strength = 3;
+
+ // Action taken to recover
+ optional android.telephony.DataStallRecoveryActionEnum action = 4;
+
+ // Whether the subscription is opportunistic
+ optional bool is_opportunistic = 5;
+
+ // Whether the device is in multi-SIM mode
+ optional bool is_multi_sim = 6;
+}
+
+/**
* Logs gnss stats from location service provider
*
* Pulled from:
diff --git a/cmds/statsd/src/metrics/DurationMetricProducer.cpp b/cmds/statsd/src/metrics/DurationMetricProducer.cpp
index 3acafaa3560e..b2c0b32bf5ef 100644
--- a/cmds/statsd/src/metrics/DurationMetricProducer.cpp
+++ b/cmds/statsd/src/metrics/DurationMetricProducer.cpp
@@ -17,14 +17,17 @@
#define DEBUG false
#include "Log.h"
+
#include "DurationMetricProducer.h"
-#include "guardrail/StatsdStats.h"
-#include "stats_util.h"
-#include "stats_log_util.h"
#include <limits.h>
#include <stdlib.h>
+#include "guardrail/StatsdStats.h"
+#include "metrics/parsing_utils/metrics_manager_util.h"
+#include "stats_log_util.h"
+#include "stats_util.h"
+
using android::util::FIELD_COUNT_REPEATED;
using android::util::FIELD_TYPE_BOOL;
using android::util::FIELD_TYPE_FLOAT;
@@ -64,8 +67,8 @@ const int FIELD_ID_END_BUCKET_ELAPSED_MILLIS = 6;
DurationMetricProducer::DurationMetricProducer(
const ConfigKey& key, const DurationMetric& metric, const int conditionIndex,
- const vector<ConditionState>& initialConditionCache, const size_t startIndex,
- const size_t stopIndex, const size_t stopAllIndex, const bool nesting,
+ const vector<ConditionState>& initialConditionCache, const int startIndex,
+ const int stopIndex, const int stopAllIndex, const bool nesting,
const sp<ConditionWizard>& wizard, const uint64_t protoHash,
const FieldMatcher& internalDimensions, const int64_t timeBaseNs, const int64_t startTimeNs,
const unordered_map<int, shared_ptr<Activation>>& eventActivationMap,
@@ -143,6 +146,84 @@ DurationMetricProducer::~DurationMetricProducer() {
VLOG("~DurationMetric() called");
}
+bool DurationMetricProducer::onConfigUpdatedLocked(
+ const StatsdConfig& config, const int configIndex, const int metricIndex,
+ const vector<sp<AtomMatchingTracker>>& allAtomMatchingTrackers,
+ const unordered_map<int64_t, int>& oldAtomMatchingTrackerMap,
+ const unordered_map<int64_t, int>& newAtomMatchingTrackerMap,
+ const sp<EventMatcherWizard>& matcherWizard,
+ const vector<sp<ConditionTracker>>& allConditionTrackers,
+ const unordered_map<int64_t, int>& conditionTrackerMap, const sp<ConditionWizard>& wizard,
+ const unordered_map<int64_t, int>& metricToActivationMap,
+ unordered_map<int, vector<int>>& trackerToMetricMap,
+ unordered_map<int, vector<int>>& conditionToMetricMap,
+ unordered_map<int, vector<int>>& activationAtomTrackerToMetricMap,
+ unordered_map<int, vector<int>>& deactivationAtomTrackerToMetricMap,
+ vector<int>& metricsWithActivation) {
+ if (!MetricProducer::onConfigUpdatedLocked(
+ config, configIndex, metricIndex, allAtomMatchingTrackers,
+ oldAtomMatchingTrackerMap, newAtomMatchingTrackerMap, matcherWizard,
+ allConditionTrackers, conditionTrackerMap, wizard, metricToActivationMap,
+ trackerToMetricMap, conditionToMetricMap, activationAtomTrackerToMetricMap,
+ deactivationAtomTrackerToMetricMap, metricsWithActivation)) {
+ return false;
+ }
+
+ const DurationMetric& metric = config.duration_metric(configIndex);
+ const auto& what_it = conditionTrackerMap.find(metric.what());
+ if (what_it == conditionTrackerMap.end()) {
+ ALOGE("DurationMetric's \"what\" is not present in the config");
+ return false;
+ }
+
+ const Predicate& durationWhat = config.predicate(what_it->second);
+ if (durationWhat.contents_case() != Predicate::ContentsCase::kSimplePredicate) {
+ ALOGE("DurationMetric's \"what\" must be a simple condition");
+ return false;
+ }
+
+ const SimplePredicate& simplePredicate = durationWhat.simple_predicate();
+
+ // Update indices: mStartIndex, mStopIndex, mStopAllIndex, mConditionIndex and MetricsManager
+ // maps.
+ if (!handleMetricWithAtomMatchingTrackers(simplePredicate.start(), metricIndex,
+ metric.has_dimensions_in_what(),
+ allAtomMatchingTrackers, newAtomMatchingTrackerMap,
+ trackerToMetricMap, mStartIndex)) {
+ ALOGE("Duration metrics must specify a valid start event matcher");
+ return false;
+ }
+
+ if (simplePredicate.has_stop() &&
+ !handleMetricWithAtomMatchingTrackers(simplePredicate.stop(), metricIndex,
+ metric.has_dimensions_in_what(),
+ allAtomMatchingTrackers, newAtomMatchingTrackerMap,
+ trackerToMetricMap, mStopIndex)) {
+ return false;
+ }
+
+ if (simplePredicate.has_stop_all() &&
+ !handleMetricWithAtomMatchingTrackers(simplePredicate.stop_all(), metricIndex,
+ metric.has_dimensions_in_what(),
+ allAtomMatchingTrackers, newAtomMatchingTrackerMap,
+ trackerToMetricMap, mStopAllIndex)) {
+ return false;
+ }
+
+ if (metric.has_condition() &&
+ !handleMetricWithConditions(metric.condition(), metricIndex, conditionTrackerMap,
+ metric.links(), allConditionTrackers, mConditionTrackerIndex,
+ conditionToMetricMap)) {
+ return false;
+ }
+
+ for (const auto& it : mCurrentSlicedDurationTrackerMap) {
+ it.second->onConfigUpdated(wizard, mConditionTrackerIndex);
+ }
+
+ return true;
+}
+
sp<AnomalyTracker> DurationMetricProducer::addAnomalyTracker(
const Alert &alert, const sp<AlarmMonitor>& anomalyAlarmMonitor) {
std::lock_guard<std::mutex> lock(mMutex);
@@ -550,7 +631,7 @@ void DurationMetricProducer::onMatchedLogEventLocked(const size_t matcherIndex,
}
// Handles Stopall events.
- if (matcherIndex == mStopAllIndex) {
+ if ((int)matcherIndex == mStopAllIndex) {
for (auto& whatIt : mCurrentSlicedDurationTrackerMap) {
whatIt.second->noteStopAll(event.GetElapsedTimestampNs());
}
@@ -598,7 +679,7 @@ void DurationMetricProducer::onMatchedLogEventLocked(const size_t matcherIndex,
}
// Handles Stop events.
- if (matcherIndex == mStopIndex) {
+ if ((int)matcherIndex == mStopIndex) {
if (mUseWhatDimensionAsInternalDimension) {
auto whatIt = mCurrentSlicedDurationTrackerMap.find(dimensionInWhat);
if (whatIt != mCurrentSlicedDurationTrackerMap.end()) {
diff --git a/cmds/statsd/src/metrics/DurationMetricProducer.h b/cmds/statsd/src/metrics/DurationMetricProducer.h
index 3a94d9c775aa..01198a9271d3 100644
--- a/cmds/statsd/src/metrics/DurationMetricProducer.h
+++ b/cmds/statsd/src/metrics/DurationMetricProducer.h
@@ -40,8 +40,8 @@ class DurationMetricProducer : public MetricProducer {
public:
DurationMetricProducer(
const ConfigKey& key, const DurationMetric& durationMetric, const int conditionIndex,
- const vector<ConditionState>& initialConditionCache, const size_t startIndex,
- const size_t stopIndex, const size_t stopAllIndex, const bool nesting,
+ const vector<ConditionState>& initialConditionCache, const int startIndex,
+ const int stopIndex, const int stopAllIndex, const bool nesting,
const sp<ConditionWizard>& wizard, const uint64_t protoHash,
const FieldMatcher& internalDimensions, const int64_t timeBaseNs,
const int64_t startTimeNs,
@@ -112,16 +112,32 @@ private:
void flushCurrentBucketLocked(const int64_t& eventTimeNs,
const int64_t& nextBucketStartTimeNs) override;
+ bool onConfigUpdatedLocked(
+ const StatsdConfig& config, const int configIndex, const int metricIndex,
+ const std::vector<sp<AtomMatchingTracker>>& allAtomMatchingTrackers,
+ const std::unordered_map<int64_t, int>& oldAtomMatchingTrackerMap,
+ const std::unordered_map<int64_t, int>& newAtomMatchingTrackerMap,
+ const sp<EventMatcherWizard>& matcherWizard,
+ const std::vector<sp<ConditionTracker>>& allConditionTrackers,
+ const std::unordered_map<int64_t, int>& conditionTrackerMap,
+ const sp<ConditionWizard>& wizard,
+ const std::unordered_map<int64_t, int>& metricToActivationMap,
+ std::unordered_map<int, std::vector<int>>& trackerToMetricMap,
+ std::unordered_map<int, std::vector<int>>& conditionToMetricMap,
+ std::unordered_map<int, std::vector<int>>& activationAtomTrackerToMetricMap,
+ std::unordered_map<int, std::vector<int>>& deactivationAtomTrackerToMetricMap,
+ std::vector<int>& metricsWithActivation) override;
+
const DurationMetric_AggregationType mAggregationType;
// Index of the SimpleAtomMatcher which defines the start.
- const size_t mStartIndex;
+ int mStartIndex;
// Index of the SimpleAtomMatcher which defines the stop.
- const size_t mStopIndex;
+ int mStopIndex;
// Index of the SimpleAtomMatcher which defines the stop all for all dimensions.
- const size_t mStopAllIndex;
+ int mStopAllIndex;
// nest counting -- for the same key, stops must match the number of starts to make real stop
const bool mNested;
@@ -167,6 +183,8 @@ private:
TestSumDurationWithSplitInFollowingBucket);
FRIEND_TEST(DurationMetricProducerTest_PartialBucket, TestMaxDuration);
FRIEND_TEST(DurationMetricProducerTest_PartialBucket, TestMaxDurationWithSplitInNextBucket);
+
+ FRIEND_TEST(ConfigUpdateTest, TestUpdateDurationMetrics);
};
} // namespace statsd
diff --git a/cmds/statsd/src/metrics/MetricProducer.h b/cmds/statsd/src/metrics/MetricProducer.h
index 18e62d28ba46..92c1a6e62640 100644
--- a/cmds/statsd/src/metrics/MetricProducer.h
+++ b/cmds/statsd/src/metrics/MetricProducer.h
@@ -569,6 +569,7 @@ protected:
FRIEND_TEST(ConfigUpdateTest, TestUpdateCountMetrics);
FRIEND_TEST(ConfigUpdateTest, TestUpdateEventMetrics);
FRIEND_TEST(ConfigUpdateTest, TestUpdateGaugeMetrics);
+ FRIEND_TEST(ConfigUpdateTest, TestUpdateDurationMetrics);
FRIEND_TEST(ConfigUpdateTest, TestUpdateMetricsMultipleTypes);
};
diff --git a/cmds/statsd/src/metrics/duration_helper/DurationTracker.h b/cmds/statsd/src/metrics/duration_helper/DurationTracker.h
index 8d59d1362919..657b2e4c3ddf 100644
--- a/cmds/statsd/src/metrics/duration_helper/DurationTracker.h
+++ b/cmds/statsd/src/metrics/duration_helper/DurationTracker.h
@@ -89,6 +89,12 @@ public:
virtual ~DurationTracker(){};
+ void onConfigUpdated(const sp<ConditionWizard>& wizard, const int conditionTrackerIndex) {
+ sp<ConditionWizard> tmpWizard = mWizard;
+ mWizard = wizard;
+ mConditionTrackerIndex = conditionTrackerIndex;
+ };
+
virtual void noteStart(const HashableDimensionKey& key, bool condition, const int64_t eventTime,
const ConditionKey& conditionKey) = 0;
virtual void noteStop(const HashableDimensionKey& key, const int64_t eventTime,
@@ -191,7 +197,7 @@ protected:
sp<ConditionWizard> mWizard;
- const int mConditionTrackerIndex;
+ int mConditionTrackerIndex;
const int64_t mBucketSizeNs;
@@ -217,6 +223,8 @@ protected:
FRIEND_TEST(OringDurationTrackerTest, TestPredictAnomalyTimestamp);
FRIEND_TEST(OringDurationTrackerTest, TestAnomalyDetectionExpiredAlarm);
FRIEND_TEST(OringDurationTrackerTest, TestAnomalyDetectionFiredAlarm);
+
+ FRIEND_TEST(ConfigUpdateTest, TestUpdateDurationMetrics);
};
} // namespace statsd
diff --git a/cmds/statsd/src/metrics/parsing_utils/config_update_utils.cpp b/cmds/statsd/src/metrics/parsing_utils/config_update_utils.cpp
index d32f5a947d12..cfc6e3f008d5 100644
--- a/cmds/statsd/src/metrics/parsing_utils/config_update_utils.cpp
+++ b/cmds/statsd/src/metrics/parsing_utils/config_update_utils.cpp
@@ -697,6 +697,43 @@ bool updateMetrics(const ConfigKey& key, const StatsdConfig& config, const int64
}
newMetricProducers.push_back(producer.value());
}
+ for (int i = 0; i < config.duration_metric_size(); i++, metricIndex++) {
+ const DurationMetric& metric = config.duration_metric(i);
+ newMetricProducerMap[metric.id()] = metricIndex;
+ optional<sp<MetricProducer>> producer;
+ switch (metricsToUpdate[metricIndex]) {
+ case UPDATE_PRESERVE: {
+ producer = updateMetric(
+ config, i, metricIndex, metric.id(), allAtomMatchingTrackers,
+ oldAtomMatchingTrackerMap, newAtomMatchingTrackerMap, matcherWizard,
+ allConditionTrackers, conditionTrackerMap, wizard, oldMetricProducerMap,
+ oldMetricProducers, metricToActivationMap, trackerToMetricMap,
+ conditionToMetricMap, activationAtomTrackerToMetricMap,
+ deactivationAtomTrackerToMetricMap, metricsWithActivation);
+ break;
+ }
+ case UPDATE_REPLACE:
+ case UPDATE_NEW: {
+ producer = createDurationMetricProducerAndUpdateMetadata(
+ key, config, timeBaseNs, currentTimeNs, metric, metricIndex,
+ allAtomMatchingTrackers, newAtomMatchingTrackerMap, allConditionTrackers,
+ conditionTrackerMap, initialConditionCache, wizard, stateAtomIdMap,
+ allStateGroupMaps, metricToActivationMap, trackerToMetricMap,
+ conditionToMetricMap, activationAtomTrackerToMetricMap,
+ deactivationAtomTrackerToMetricMap, metricsWithActivation);
+ break;
+ }
+ default: {
+ ALOGE("Metric \"%lld\" update state is unknown. This should never happen",
+ (long long)metric.id());
+ return false;
+ }
+ }
+ if (!producer) {
+ return false;
+ }
+ newMetricProducers.push_back(producer.value());
+ }
for (int i = 0; i < config.event_metric_size(); i++, metricIndex++) {
newMetricProducerMap[config.event_metric(i).id()] = metricIndex;
const EventMetric& metric = config.event_metric(i);
@@ -770,7 +807,7 @@ bool updateMetrics(const ConfigKey& key, const StatsdConfig& config, const int64
}
newMetricProducers.push_back(producer.value());
}
- // TODO: perform update for value, duration metric.
+ // TODO: perform update for value metric.
const set<int> atomsAllowedFromAnyUid(config.whitelisted_atom_ids().begin(),
config.whitelisted_atom_ids().end());
diff --git a/cmds/statsd/src/metrics/parsing_utils/metrics_manager_util.cpp b/cmds/statsd/src/metrics/parsing_utils/metrics_manager_util.cpp
index 34e265c3b2ea..b7dc2c7fd0de 100644
--- a/cmds/statsd/src/metrics/parsing_utils/metrics_manager_util.cpp
+++ b/cmds/statsd/src/metrics/parsing_utils/metrics_manager_util.cpp
@@ -365,7 +365,7 @@ optional<sp<MetricProducer>> createCountMetricProducerAndUpdateMetadata(
unordered_map<int, vector<int>>& deactivationAtomTrackerToMetricMap,
vector<int>& metricsWithActivation) {
if (!metric.has_id() || !metric.has_what()) {
- ALOGW("cannot find metric id or \"what\" in CountMetric \"%lld\"", (long long)metric.id());
+ ALOGE("cannot find metric id or \"what\" in CountMetric \"%lld\"", (long long)metric.id());
return nullopt;
}
int trackerIndex;
@@ -423,6 +423,125 @@ optional<sp<MetricProducer>> createCountMetricProducerAndUpdateMetadata(
eventDeactivationMap, slicedStateAtoms, stateGroupMap)};
}
+optional<sp<MetricProducer>> createDurationMetricProducerAndUpdateMetadata(
+ const ConfigKey& key, const StatsdConfig& config, const int64_t timeBaseNs,
+ const int64_t currentTimeNs, const DurationMetric& metric, const int metricIndex,
+ const vector<sp<AtomMatchingTracker>>& allAtomMatchingTrackers,
+ const unordered_map<int64_t, int>& atomMatchingTrackerMap,
+ vector<sp<ConditionTracker>>& allConditionTrackers,
+ const unordered_map<int64_t, int>& conditionTrackerMap,
+ const vector<ConditionState>& initialConditionCache, const sp<ConditionWizard>& wizard,
+ const unordered_map<int64_t, int>& stateAtomIdMap,
+ const unordered_map<int64_t, unordered_map<int, int64_t>>& allStateGroupMaps,
+ const unordered_map<int64_t, int>& metricToActivationMap,
+ unordered_map<int, vector<int>>& trackerToMetricMap,
+ unordered_map<int, vector<int>>& conditionToMetricMap,
+ unordered_map<int, vector<int>>& activationAtomTrackerToMetricMap,
+ unordered_map<int, vector<int>>& deactivationAtomTrackerToMetricMap,
+ vector<int>& metricsWithActivation) {
+ if (!metric.has_id() || !metric.has_what()) {
+ ALOGE("cannot find metric id or \"what\" in DurationMetric \"%lld\"",
+ (long long)metric.id());
+ return nullopt;
+ }
+ const auto& what_it = conditionTrackerMap.find(metric.what());
+ if (what_it == conditionTrackerMap.end()) {
+ ALOGE("DurationMetric's \"what\" is not present in the condition trackers");
+ return nullopt;
+ }
+
+ const Predicate& durationWhat = config.predicate(what_it->second);
+ if (durationWhat.contents_case() != Predicate::ContentsCase::kSimplePredicate) {
+ ALOGE("DurationMetric's \"what\" must be a simple condition");
+ return nullopt;
+ }
+
+ const SimplePredicate& simplePredicate = durationWhat.simple_predicate();
+ bool nesting = simplePredicate.count_nesting();
+
+ int startIndex = -1, stopIndex = -1, stopAllIndex = -1;
+ if (!simplePredicate.has_start() ||
+ !handleMetricWithAtomMatchingTrackers(
+ simplePredicate.start(), metricIndex, metric.has_dimensions_in_what(),
+ allAtomMatchingTrackers, atomMatchingTrackerMap, trackerToMetricMap, startIndex)) {
+ ALOGE("Duration metrics must specify a valid start event matcher");
+ return nullopt;
+ }
+
+ if (simplePredicate.has_stop() &&
+ !handleMetricWithAtomMatchingTrackers(
+ simplePredicate.stop(), metricIndex, metric.has_dimensions_in_what(),
+ allAtomMatchingTrackers, atomMatchingTrackerMap, trackerToMetricMap, stopIndex)) {
+ return nullopt;
+ }
+
+ if (simplePredicate.has_stop_all() &&
+ !handleMetricWithAtomMatchingTrackers(simplePredicate.stop_all(), metricIndex,
+ metric.has_dimensions_in_what(),
+ allAtomMatchingTrackers, atomMatchingTrackerMap,
+ trackerToMetricMap, stopAllIndex)) {
+ return nullopt;
+ }
+
+ FieldMatcher internalDimensions = simplePredicate.dimensions();
+
+ int conditionIndex = -1;
+ if (metric.has_condition()) {
+ if (!handleMetricWithConditions(metric.condition(), metricIndex, conditionTrackerMap,
+ metric.links(), allConditionTrackers, conditionIndex,
+ conditionToMetricMap)) {
+ return nullopt;
+ }
+ } else if (metric.links_size() > 0) {
+ ALOGW("metrics has a MetricConditionLink but doesn't have a condition");
+ return nullopt;
+ }
+
+ std::vector<int> slicedStateAtoms;
+ unordered_map<int, unordered_map<int, int64_t>> stateGroupMap;
+ if (metric.slice_by_state_size() > 0) {
+ if (metric.aggregation_type() == DurationMetric::MAX_SPARSE) {
+ ALOGE("DurationMetric with aggregation type MAX_SPARSE cannot be sliced by state");
+ return nullopt;
+ }
+ if (!handleMetricWithStates(config, metric.slice_by_state(), stateAtomIdMap,
+ allStateGroupMaps, slicedStateAtoms, stateGroupMap)) {
+ return nullopt;
+ }
+ } else if (metric.state_link_size() > 0) {
+ ALOGW("DurationMetric has a MetricStateLink but doesn't have a sliced state");
+ return nullopt;
+ }
+
+ // Check that all metric state links are a subset of dimensions_in_what fields.
+ std::vector<Matcher> dimensionsInWhat;
+ translateFieldMatcher(metric.dimensions_in_what(), &dimensionsInWhat);
+ for (const auto& stateLink : metric.state_link()) {
+ if (!handleMetricWithStateLink(stateLink.fields_in_what(), dimensionsInWhat)) {
+ return nullopt;
+ }
+ }
+
+ unordered_map<int, shared_ptr<Activation>> eventActivationMap;
+ unordered_map<int, vector<shared_ptr<Activation>>> eventDeactivationMap;
+ if (!handleMetricActivation(config, metric.id(), metricIndex, metricToActivationMap,
+ atomMatchingTrackerMap, activationAtomTrackerToMetricMap,
+ deactivationAtomTrackerToMetricMap, metricsWithActivation,
+ eventActivationMap, eventDeactivationMap)) {
+ return nullopt;
+ }
+
+ uint64_t metricHash;
+ if (!getMetricProtoHash(config, metric, metric.id(), metricToActivationMap, metricHash)) {
+ return nullopt;
+ }
+
+ return {new DurationMetricProducer(
+ key, metric, conditionIndex, initialConditionCache, startIndex, stopIndex, stopAllIndex,
+ nesting, wizard, metricHash, internalDimensions, timeBaseNs, currentTimeNs,
+ eventActivationMap, eventDeactivationMap, slicedStateAtoms, stateGroupMap)};
+}
+
optional<sp<MetricProducer>> createEventMetricProducerAndUpdateMetadata(
const ConfigKey& key, const StatsdConfig& config, const int64_t timeBaseNs,
const EventMetric& metric, const int metricIndex,
@@ -438,7 +557,7 @@ optional<sp<MetricProducer>> createEventMetricProducerAndUpdateMetadata(
unordered_map<int, vector<int>>& deactivationAtomTrackerToMetricMap,
vector<int>& metricsWithActivation) {
if (!metric.has_id() || !metric.has_what()) {
- ALOGW("cannot find the metric name or what in config");
+ ALOGE("cannot find the metric name or what in config");
return nullopt;
}
int trackerIndex;
@@ -497,7 +616,7 @@ optional<sp<MetricProducer>> createGaugeMetricProducerAndUpdateMetadata(
unordered_map<int, vector<int>>& deactivationAtomTrackerToMetricMap,
vector<int>& metricsWithActivation) {
if (!metric.has_id() || !metric.has_what()) {
- ALOGW("cannot find metric id or \"what\" in GaugeMetric \"%lld\"", (long long)metric.id());
+ ALOGE("cannot find metric id or \"what\" in GaugeMetric \"%lld\"", (long long)metric.id());
return nullopt;
}
@@ -760,114 +879,17 @@ bool initMetrics(const ConfigKey& key, const StatsdConfig& config, const int64_t
const DurationMetric& metric = config.duration_metric(i);
metricMap.insert({metric.id(), metricIndex});
- auto what_it = conditionTrackerMap.find(metric.what());
- if (what_it == conditionTrackerMap.end()) {
- ALOGE("DurationMetric's \"what\" is invalid");
- return false;
- }
-
- const Predicate& durationWhat = config.predicate(what_it->second);
-
- if (durationWhat.contents_case() != Predicate::ContentsCase::kSimplePredicate) {
- ALOGE("DurationMetric's \"what\" must be a simple condition");
- return false;
- }
-
- const auto& simplePredicate = durationWhat.simple_predicate();
-
- bool nesting = simplePredicate.count_nesting();
-
- int trackerIndices[3] = {-1, -1, -1};
- if (!simplePredicate.has_start() ||
- !handleMetricWithAtomMatchingTrackers(simplePredicate.start(), metricIndex,
- metric.has_dimensions_in_what(),
- allAtomMatchingTrackers, atomMatchingTrackerMap,
- trackerToMetricMap, trackerIndices[0])) {
- ALOGE("Duration metrics must specify a valid the start event matcher");
- return false;
- }
-
- if (simplePredicate.has_stop() &&
- !handleMetricWithAtomMatchingTrackers(simplePredicate.stop(), metricIndex,
- metric.has_dimensions_in_what(),
- allAtomMatchingTrackers, atomMatchingTrackerMap,
- trackerToMetricMap, trackerIndices[1])) {
- return false;
- }
-
- if (simplePredicate.has_stop_all() &&
- !handleMetricWithAtomMatchingTrackers(simplePredicate.stop_all(), metricIndex,
- metric.has_dimensions_in_what(),
- allAtomMatchingTrackers, atomMatchingTrackerMap,
- trackerToMetricMap, trackerIndices[2])) {
- return false;
- }
-
- FieldMatcher internalDimensions = simplePredicate.dimensions();
-
- int conditionIndex = -1;
-
- if (metric.has_condition()) {
- bool good = handleMetricWithConditions(
- metric.condition(), metricIndex, conditionTrackerMap, metric.links(),
- allConditionTrackers, conditionIndex, conditionToMetricMap);
- if (!good) {
- return false;
- }
- } else {
- if (metric.links_size() > 0) {
- ALOGW("metrics has a MetricConditionLink but doesn't have a condition");
- return false;
- }
- }
-
- std::vector<int> slicedStateAtoms;
- unordered_map<int, unordered_map<int, int64_t>> stateGroupMap;
- if (metric.slice_by_state_size() > 0) {
- if (metric.aggregation_type() == DurationMetric::MAX_SPARSE) {
- ALOGE("DurationMetric with aggregation type MAX_SPARSE cannot be sliced by state");
- return false;
- }
- if (!handleMetricWithStates(config, metric.slice_by_state(), stateAtomIdMap,
- allStateGroupMaps, slicedStateAtoms, stateGroupMap)) {
- return false;
- }
- } else {
- if (metric.state_link_size() > 0) {
- ALOGW("DurationMetric has a MetricStateLink but doesn't have a sliced state");
- return false;
- }
- }
-
- // Check that all metric state links are a subset of dimensions_in_what fields.
- std::vector<Matcher> dimensionsInWhat;
- translateFieldMatcher(metric.dimensions_in_what(), &dimensionsInWhat);
- for (const auto& stateLink : metric.state_link()) {
- if (!handleMetricWithStateLink(stateLink.fields_in_what(), dimensionsInWhat)) {
- return false;
- }
- }
-
- unordered_map<int, shared_ptr<Activation>> eventActivationMap;
- unordered_map<int, vector<shared_ptr<Activation>>> eventDeactivationMap;
- bool success = handleMetricActivation(
- config, metric.id(), metricIndex, metricToActivationMap, atomMatchingTrackerMap,
+ optional<sp<MetricProducer>> producer = createDurationMetricProducerAndUpdateMetadata(
+ key, config, timeBaseTimeNs, currentTimeNs, metric, metricIndex,
+ allAtomMatchingTrackers, atomMatchingTrackerMap, allConditionTrackers,
+ conditionTrackerMap, initialConditionCache, wizard, stateAtomIdMap,
+ allStateGroupMaps, metricToActivationMap, trackerToMetricMap, conditionToMetricMap,
activationAtomTrackerToMetricMap, deactivationAtomTrackerToMetricMap,
- metricsWithActivation, eventActivationMap, eventDeactivationMap);
- if (!success) return false;
-
- uint64_t metricHash;
- if (!getMetricProtoHash(config, metric, metric.id(), metricToActivationMap, metricHash)) {
+ metricsWithActivation);
+ if (!producer) {
return false;
}
-
- sp<MetricProducer> durationMetric = new DurationMetricProducer(
- key, metric, conditionIndex, initialConditionCache, trackerIndices[0],
- trackerIndices[1], trackerIndices[2], nesting, wizard, metricHash,
- internalDimensions, timeBaseTimeNs, currentTimeNs, eventActivationMap,
- eventDeactivationMap, slicedStateAtoms, stateGroupMap);
-
- allMetricProducers.push_back(durationMetric);
+ allMetricProducers.push_back(producer.value());
}
// build EventMetricProducer
diff --git a/cmds/statsd/src/metrics/parsing_utils/metrics_manager_util.h b/cmds/statsd/src/metrics/parsing_utils/metrics_manager_util.h
index f909aff48faf..6d1e6dde7e89 100644
--- a/cmds/statsd/src/metrics/parsing_utils/metrics_manager_util.h
+++ b/cmds/statsd/src/metrics/parsing_utils/metrics_manager_util.h
@@ -112,6 +112,25 @@ optional<sp<MetricProducer>> createCountMetricProducerAndUpdateMetadata(
std::unordered_map<int, std::vector<int>>& deactivationAtomTrackerToMetricMap,
std::vector<int>& metricsWithActivation);
+// Creates a DurationMetricProducer and updates the vectors/maps used by MetricsManager with
+// the appropriate indices. Returns an sp to the producer, or nullopt if there was an error.
+optional<sp<MetricProducer>> createDurationMetricProducerAndUpdateMetadata(
+ const ConfigKey& key, const StatsdConfig& config, const int64_t timeBaseNs,
+ const int64_t currentTimeNs, const DurationMetric& metric, const int metricIndex,
+ const std::vector<sp<AtomMatchingTracker>>& allAtomMatchingTrackers,
+ const std::unordered_map<int64_t, int>& atomMatchingTrackerMap,
+ std::vector<sp<ConditionTracker>>& allConditionTrackers,
+ const std::unordered_map<int64_t, int>& conditionTrackerMap,
+ const std::vector<ConditionState>& initialConditionCache, const sp<ConditionWizard>& wizard,
+ const std::unordered_map<int64_t, int>& stateAtomIdMap,
+ const std::unordered_map<int64_t, std::unordered_map<int, int64_t>>& allStateGroupMaps,
+ const std::unordered_map<int64_t, int>& metricToActivationMap,
+ std::unordered_map<int, std::vector<int>>& trackerToMetricMap,
+ std::unordered_map<int, std::vector<int>>& conditionToMetricMap,
+ std::unordered_map<int, std::vector<int>>& activationAtomTrackerToMetricMap,
+ std::unordered_map<int, std::vector<int>>& deactivationAtomTrackerToMetricMap,
+ std::vector<int>& metricsWithActivation);
+
// Creates an EventMetricProducer and updates the vectors/maps used by MetricsManager with
// the appropriate indices. Returns an sp to the producer, or nullopt if there was an error.
optional<sp<MetricProducer>> createEventMetricProducerAndUpdateMetadata(
diff --git a/cmds/statsd/tests/metrics/parsing_utils/config_update_utils_test.cpp b/cmds/statsd/tests/metrics/parsing_utils/config_update_utils_test.cpp
index a20be15d9541..dc951be72fe1 100644
--- a/cmds/statsd/tests/metrics/parsing_utils/config_update_utils_test.cpp
+++ b/cmds/statsd/tests/metrics/parsing_utils/config_update_utils_test.cpp
@@ -27,6 +27,7 @@
#include "src/condition/CombinationConditionTracker.h"
#include "src/condition/SimpleConditionTracker.h"
#include "src/matchers/CombinationAtomMatchingTracker.h"
+#include "src/metrics/DurationMetricProducer.h"
#include "src/metrics/GaugeMetricProducer.h"
#include "src/metrics/parsing_utils/metrics_manager_util.h"
#include "tests/statsd_test_util.h"
@@ -2212,6 +2213,352 @@ TEST_F(ConfigUpdateTest, TestUpdateGaugeMetrics) {
EXPECT_EQ(oldMatcherWizard->getStrongCount(), 1);
}
+TEST_F(ConfigUpdateTest, TestUpdateDurationMetrics) {
+ StatsdConfig config;
+ // Add atom matchers/predicates/states. These are mostly needed for initStatsdConfig.
+ AtomMatcher matcher1 = CreateScreenTurnedOnAtomMatcher();
+ int64_t matcher1Id = matcher1.id();
+ *config.add_atom_matcher() = matcher1;
+
+ AtomMatcher matcher2 = CreateScreenTurnedOffAtomMatcher();
+ int64_t matcher2Id = matcher2.id();
+ *config.add_atom_matcher() = matcher2;
+
+ AtomMatcher matcher3 = CreateAcquireWakelockAtomMatcher();
+ int64_t matcher3Id = matcher3.id();
+ *config.add_atom_matcher() = matcher3;
+
+ AtomMatcher matcher4 = CreateReleaseWakelockAtomMatcher();
+ int64_t matcher4Id = matcher4.id();
+ *config.add_atom_matcher() = matcher4;
+
+ AtomMatcher matcher5 = CreateMoveToForegroundAtomMatcher();
+ int64_t matcher5Id = matcher5.id();
+ *config.add_atom_matcher() = matcher5;
+
+ AtomMatcher matcher6 = CreateMoveToBackgroundAtomMatcher();
+ int64_t matcher6Id = matcher6.id();
+ *config.add_atom_matcher() = matcher6;
+
+ AtomMatcher matcher7 = CreateBatteryStateNoneMatcher();
+ int64_t matcher7Id = matcher7.id();
+ *config.add_atom_matcher() = matcher7;
+
+ AtomMatcher matcher8 = CreateBatteryStateUsbMatcher();
+ int64_t matcher8Id = matcher8.id();
+ *config.add_atom_matcher() = matcher8;
+
+ Predicate predicate1 = CreateScreenIsOnPredicate();
+ int64_t predicate1Id = predicate1.id();
+ *config.add_predicate() = predicate1;
+
+ Predicate predicate2 = CreateScreenIsOffPredicate();
+ int64_t predicate2Id = predicate2.id();
+ *config.add_predicate() = predicate2;
+
+ Predicate predicate3 = CreateDeviceUnpluggedPredicate();
+ int64_t predicate3Id = predicate3.id();
+ *config.add_predicate() = predicate3;
+
+ Predicate predicate4 = CreateIsInBackgroundPredicate();
+ *predicate4.mutable_simple_predicate()->mutable_dimensions() =
+ CreateDimensions(util::ACTIVITY_FOREGROUND_STATE_CHANGED, {1});
+ int64_t predicate4Id = predicate4.id();
+ *config.add_predicate() = predicate4;
+
+ Predicate predicate5 = CreateHoldingWakelockPredicate();
+ *predicate5.mutable_simple_predicate()->mutable_dimensions() =
+ CreateAttributionUidDimensions(util::WAKELOCK_STATE_CHANGED, {Position::FIRST});
+ predicate5.mutable_simple_predicate()->set_stop_all(matcher7Id);
+ int64_t predicate5Id = predicate5.id();
+ *config.add_predicate() = predicate5;
+
+ State state1 = CreateScreenStateWithOnOffMap(0x123, 0x321);
+ int64_t state1Id = state1.id();
+ *config.add_state() = state1;
+
+ State state2 = CreateScreenState();
+ int64_t state2Id = state2.id();
+ *config.add_state() = state2;
+
+ // Add a few duration metrics.
+ // Will be preserved.
+ DurationMetric duration1 =
+ createDurationMetric("DURATION1", predicate5Id, predicate4Id, {state2Id});
+ *duration1.mutable_dimensions_in_what() =
+ CreateAttributionUidDimensions(util::WAKELOCK_STATE_CHANGED, {Position::FIRST});
+ MetricConditionLink* link = duration1.add_links();
+ link->set_condition(predicate4Id);
+ *link->mutable_fields_in_what() =
+ CreateAttributionUidDimensions(util::WAKELOCK_STATE_CHANGED, {Position::FIRST});
+ *link->mutable_fields_in_condition() =
+ CreateDimensions(util::ACTIVITY_FOREGROUND_STATE_CHANGED, {1} /*uid field*/);
+ int64_t duration1Id = duration1.id();
+ *config.add_duration_metric() = duration1;
+
+ // Will be replaced.
+ DurationMetric duration2 = createDurationMetric("DURATION2", predicate1Id, nullopt, {});
+ int64_t duration2Id = duration2.id();
+ *config.add_duration_metric() = duration2;
+
+ // Will be replaced.
+ DurationMetric duration3 = createDurationMetric("DURATION3", predicate3Id, nullopt, {state1Id});
+ int64_t duration3Id = duration3.id();
+ *config.add_duration_metric() = duration3;
+
+ // Will be replaced.
+ DurationMetric duration4 = createDurationMetric("DURATION4", predicate3Id, predicate2Id, {});
+ int64_t duration4Id = duration4.id();
+ *config.add_duration_metric() = duration4;
+
+ // Will be deleted.
+ DurationMetric duration5 = createDurationMetric("DURATION5", predicate2Id, nullopt, {});
+ int64_t duration5Id = duration5.id();
+ *config.add_duration_metric() = duration5;
+
+ EXPECT_TRUE(initConfig(config));
+
+ // Make some sliced conditions true.
+ int uid1 = 10;
+ int uid2 = 11;
+ vector<MatchingState> matchingStates(8, MatchingState::kNotMatched);
+ matchingStates[2] = kMatched;
+ vector<ConditionState> conditionCache(5, ConditionState::kNotEvaluated);
+ vector<bool> changedCache(5, false);
+ unique_ptr<LogEvent> event = CreateAcquireWakelockEvent(timeBaseNs + 3, {uid1}, {"tag"}, "wl1");
+ oldConditionTrackers[4]->evaluateCondition(*event.get(), matchingStates, oldConditionTrackers,
+ conditionCache, changedCache);
+ EXPECT_TRUE(oldConditionTrackers[4]->isSliced());
+ EXPECT_TRUE(changedCache[4]);
+ EXPECT_EQ(conditionCache[4], ConditionState::kTrue);
+ oldMetricProducers[0]->onMatchedLogEvent(2, *event.get());
+
+ fill(conditionCache.begin(), conditionCache.end(), ConditionState::kNotEvaluated);
+ fill(changedCache.begin(), changedCache.end(), false);
+ event = CreateAcquireWakelockEvent(timeBaseNs + 3, {uid2}, {"tag"}, "wl2");
+ oldConditionTrackers[4]->evaluateCondition(*event.get(), matchingStates, oldConditionTrackers,
+ conditionCache, changedCache);
+ EXPECT_TRUE(changedCache[4]);
+ EXPECT_EQ(conditionCache[4], ConditionState::kTrue);
+ oldMetricProducers[0]->onMatchedLogEvent(2, *event.get());
+
+ // Used later to ensure the condition wizard is replaced. Get it before doing the update.
+ // The duration trackers have a pointer to the wizard, and 2 trackers were created above.
+ sp<ConditionWizard> oldConditionWizard = oldMetricProducers[0]->mWizard;
+ EXPECT_EQ(oldConditionWizard->getStrongCount(), 8);
+
+ // Replace predicate1, predicate3, and state1. Causes duration2/3/4 to be replaced.
+ set<int64_t> replacedConditions({predicate1Id, predicate2Id});
+ set<int64_t> replacedStates({state1Id});
+
+ // New duration metric.
+ DurationMetric duration6 = createDurationMetric("DURATION6", predicate4Id, predicate5Id, {});
+ *duration6.mutable_dimensions_in_what() =
+ CreateDimensions(util::ACTIVITY_FOREGROUND_STATE_CHANGED, {1} /*uid field*/);
+ link = duration6.add_links();
+ link->set_condition(predicate5Id);
+ *link->mutable_fields_in_what() =
+ CreateDimensions(util::ACTIVITY_FOREGROUND_STATE_CHANGED, {1} /*uid field*/);
+ *link->mutable_fields_in_condition() =
+ CreateAttributionUidDimensions(util::WAKELOCK_STATE_CHANGED, {Position::FIRST});
+ int64_t duration6Id = duration6.id();
+
+ // Map the matchers and predicates in reverse order to force the indices to change.
+ const int matcher8Index = 0, matcher7Index = 1, matcher6Index = 2, matcher5Index = 3,
+ matcher4Index = 4, matcher3Index = 5, matcher2Index = 6, matcher1Index = 7;
+ std::unordered_map<int64_t, int> newAtomMatchingTrackerMap({{matcher8Id, matcher8Index},
+ {matcher7Id, matcher7Index},
+ {matcher6Id, matcher6Index},
+ {matcher5Id, matcher5Index},
+ {matcher4Id, matcher4Index},
+ {matcher3Id, matcher3Index},
+ {matcher2Id, matcher2Index},
+ {matcher1Id, matcher1Index}});
+ // Use the existing matchers. A bit hacky, but saves code and we don't rely on them.
+ vector<sp<AtomMatchingTracker>> newAtomMatchingTrackers(8);
+ reverse_copy(oldAtomMatchingTrackers.begin(), oldAtomMatchingTrackers.end(),
+ newAtomMatchingTrackers.begin());
+
+ const int predicate5Index = 0, predicate4Index = 1, predicate3Index = 2, predicate2Index = 3,
+ predicate1Index = 4;
+ std::unordered_map<int64_t, int> newConditionTrackerMap({
+ {predicate5Id, predicate5Index},
+ {predicate4Id, predicate4Index},
+ {predicate3Id, predicate3Index},
+ {predicate2Id, predicate2Index},
+ {predicate1Id, predicate1Index},
+ });
+ // Use the existing conditionTrackers and reinitialize them to get the initial condition cache.
+ vector<sp<ConditionTracker>> newConditionTrackers(5);
+ reverse_copy(oldConditionTrackers.begin(), oldConditionTrackers.end(),
+ newConditionTrackers.begin());
+ vector<Predicate> conditionProtos(5);
+ reverse_copy(config.predicate().begin(), config.predicate().end(), conditionProtos.begin());
+ for (int i = 0; i < newConditionTrackers.size(); i++) {
+ EXPECT_TRUE(newConditionTrackers[i]->onConfigUpdated(
+ conditionProtos, i, newConditionTrackers, newAtomMatchingTrackerMap,
+ newConditionTrackerMap));
+ }
+ vector<bool> cycleTracker(5, false);
+ fill(conditionCache.begin(), conditionCache.end(), ConditionState::kNotEvaluated);
+ for (int i = 0; i < newConditionTrackers.size(); i++) {
+ EXPECT_TRUE(newConditionTrackers[i]->init(conditionProtos, newConditionTrackers,
+ newConditionTrackerMap, cycleTracker,
+ conditionCache));
+ }
+ // Predicate5 should be true since 2 uids have wakelocks
+ EXPECT_EQ(conditionCache, vector({kTrue, kUnknown, kUnknown, kUnknown, kUnknown}));
+
+ StatsdConfig newConfig;
+ *newConfig.add_duration_metric() = duration6;
+ const int duration6Index = 0;
+ *newConfig.add_duration_metric() = duration3;
+ const int duration3Index = 1;
+ *newConfig.add_duration_metric() = duration1;
+ const int duration1Index = 2;
+ *newConfig.add_duration_metric() = duration4;
+ const int duration4Index = 3;
+ *newConfig.add_duration_metric() = duration2;
+ const int duration2Index = 4;
+
+ for (const Predicate& predicate : conditionProtos) {
+ *newConfig.add_predicate() = predicate;
+ }
+ *newConfig.add_state() = state1;
+ *newConfig.add_state() = state2;
+ unordered_map<int64_t, int> stateAtomIdMap;
+ unordered_map<int64_t, unordered_map<int, int64_t>> allStateGroupMaps;
+ map<int64_t, uint64_t> stateProtoHashes;
+ EXPECT_TRUE(initStates(newConfig, stateAtomIdMap, allStateGroupMaps, stateProtoHashes));
+
+ // Output data structures to validate.
+ unordered_map<int64_t, int> newMetricProducerMap;
+ vector<sp<MetricProducer>> newMetricProducers;
+ unordered_map<int, vector<int>> conditionToMetricMap;
+ unordered_map<int, vector<int>> trackerToMetricMap;
+ set<int64_t> noReportMetricIds;
+ unordered_map<int, vector<int>> activationAtomTrackerToMetricMap;
+ unordered_map<int, vector<int>> deactivationAtomTrackerToMetricMap;
+ vector<int> metricsWithActivation;
+ EXPECT_TRUE(updateMetrics(
+ key, newConfig, /*timeBaseNs=*/123, /*currentTimeNs=*/12345, new StatsPullerManager(),
+ oldAtomMatchingTrackerMap, newAtomMatchingTrackerMap, /*replacedMatchers=*/{},
+ newAtomMatchingTrackers, newConditionTrackerMap, replacedConditions,
+ newConditionTrackers, conditionCache, stateAtomIdMap, allStateGroupMaps, replacedStates,
+ oldMetricProducerMap, oldMetricProducers, newMetricProducerMap, newMetricProducers,
+ conditionToMetricMap, trackerToMetricMap, noReportMetricIds,
+ activationAtomTrackerToMetricMap, deactivationAtomTrackerToMetricMap,
+ metricsWithActivation));
+
+ unordered_map<int64_t, int> expectedMetricProducerMap = {
+ {duration1Id, duration1Index}, {duration2Id, duration2Index},
+ {duration3Id, duration3Index}, {duration4Id, duration4Index},
+ {duration6Id, duration6Index},
+ };
+ EXPECT_THAT(newMetricProducerMap, ContainerEq(expectedMetricProducerMap));
+
+ // Make sure preserved metrics are the same.
+ ASSERT_EQ(newMetricProducers.size(), 5);
+ EXPECT_EQ(oldMetricProducers[oldMetricProducerMap.at(duration1Id)],
+ newMetricProducers[newMetricProducerMap.at(duration1Id)]);
+
+ // Make sure replaced metrics are different.
+ EXPECT_NE(oldMetricProducers[oldMetricProducerMap.at(duration2Id)],
+ newMetricProducers[newMetricProducerMap.at(duration2Id)]);
+ EXPECT_NE(oldMetricProducers[oldMetricProducerMap.at(duration3Id)],
+ newMetricProducers[newMetricProducerMap.at(duration3Id)]);
+ EXPECT_NE(oldMetricProducers[oldMetricProducerMap.at(duration4Id)],
+ newMetricProducers[newMetricProducerMap.at(duration4Id)]);
+
+ // Verify the conditionToMetricMap. Note that the "what" is not in this map.
+ ASSERT_EQ(conditionToMetricMap.size(), 3);
+ const vector<int>& condition2Metrics = conditionToMetricMap[predicate2Index];
+ EXPECT_THAT(condition2Metrics, UnorderedElementsAre(duration4Index));
+ const vector<int>& condition4Metrics = conditionToMetricMap[predicate4Index];
+ EXPECT_THAT(condition4Metrics, UnorderedElementsAre(duration1Index));
+ const vector<int>& condition5Metrics = conditionToMetricMap[predicate5Index];
+ EXPECT_THAT(condition5Metrics, UnorderedElementsAre(duration6Index));
+
+ // Verify the trackerToMetricMap. The start/stop/stopall indices from the "what" should be here.
+ ASSERT_EQ(trackerToMetricMap.size(), 8);
+ const vector<int>& matcher1Metrics = trackerToMetricMap[matcher1Index];
+ EXPECT_THAT(matcher1Metrics, UnorderedElementsAre(duration2Index));
+ const vector<int>& matcher2Metrics = trackerToMetricMap[matcher2Index];
+ EXPECT_THAT(matcher2Metrics, UnorderedElementsAre(duration2Index));
+ const vector<int>& matcher3Metrics = trackerToMetricMap[matcher3Index];
+ EXPECT_THAT(matcher3Metrics, UnorderedElementsAre(duration1Index));
+ const vector<int>& matcher4Metrics = trackerToMetricMap[matcher4Index];
+ EXPECT_THAT(matcher4Metrics, UnorderedElementsAre(duration1Index));
+ const vector<int>& matcher5Metrics = trackerToMetricMap[matcher5Index];
+ EXPECT_THAT(matcher5Metrics, UnorderedElementsAre(duration6Index));
+ const vector<int>& matcher6Metrics = trackerToMetricMap[matcher6Index];
+ EXPECT_THAT(matcher6Metrics, UnorderedElementsAre(duration6Index));
+ const vector<int>& matcher7Metrics = trackerToMetricMap[matcher7Index];
+ EXPECT_THAT(matcher7Metrics,
+ UnorderedElementsAre(duration1Index, duration3Index, duration4Index));
+ const vector<int>& matcher8Metrics = trackerToMetricMap[matcher8Index];
+ EXPECT_THAT(matcher8Metrics, UnorderedElementsAre(duration3Index, duration4Index));
+
+ // Verify event activation/deactivation maps.
+ ASSERT_EQ(activationAtomTrackerToMetricMap.size(), 0);
+ ASSERT_EQ(deactivationAtomTrackerToMetricMap.size(), 0);
+ ASSERT_EQ(metricsWithActivation.size(), 0);
+
+ // Verify tracker indices/ids/conditions are correct.
+ DurationMetricProducer* durationProducer1 =
+ static_cast<DurationMetricProducer*>(newMetricProducers[duration1Index].get());
+ EXPECT_EQ(durationProducer1->getMetricId(), duration1Id);
+ EXPECT_EQ(durationProducer1->mConditionTrackerIndex, predicate4Index);
+ EXPECT_EQ(durationProducer1->mCondition, ConditionState::kUnknown);
+ EXPECT_EQ(durationProducer1->mStartIndex, matcher3Index);
+ EXPECT_EQ(durationProducer1->mStopIndex, matcher4Index);
+ EXPECT_EQ(durationProducer1->mStopAllIndex, matcher7Index);
+ EXPECT_EQ(durationProducer1->mCurrentSlicedDurationTrackerMap.size(), 2);
+ for (const auto& durationTrackerIt : durationProducer1->mCurrentSlicedDurationTrackerMap) {
+ EXPECT_EQ(durationTrackerIt.second->mConditionTrackerIndex, predicate4Index);
+ }
+ DurationMetricProducer* durationProducer2 =
+ static_cast<DurationMetricProducer*>(newMetricProducers[duration2Index].get());
+ EXPECT_EQ(durationProducer2->getMetricId(), duration2Id);
+ EXPECT_EQ(durationProducer2->mConditionTrackerIndex, -1);
+ EXPECT_EQ(durationProducer2->mCondition, ConditionState::kTrue);
+ EXPECT_EQ(durationProducer2->mStartIndex, matcher1Index);
+ EXPECT_EQ(durationProducer2->mStopIndex, matcher2Index);
+ EXPECT_EQ(durationProducer2->mStopAllIndex, -1);
+ DurationMetricProducer* durationProducer3 =
+ static_cast<DurationMetricProducer*>(newMetricProducers[duration3Index].get());
+ EXPECT_EQ(durationProducer3->getMetricId(), duration3Id);
+ EXPECT_EQ(durationProducer3->mConditionTrackerIndex, -1);
+ EXPECT_EQ(durationProducer3->mCondition, ConditionState::kTrue);
+ EXPECT_EQ(durationProducer3->mStartIndex, matcher7Index);
+ EXPECT_EQ(durationProducer3->mStopIndex, matcher8Index);
+ EXPECT_EQ(durationProducer3->mStopAllIndex, -1);
+ DurationMetricProducer* durationProducer4 =
+ static_cast<DurationMetricProducer*>(newMetricProducers[duration4Index].get());
+ EXPECT_EQ(durationProducer4->getMetricId(), duration4Id);
+ EXPECT_EQ(durationProducer4->mConditionTrackerIndex, predicate2Index);
+ EXPECT_EQ(durationProducer4->mCondition, ConditionState::kUnknown);
+ EXPECT_EQ(durationProducer4->mStartIndex, matcher7Index);
+ EXPECT_EQ(durationProducer4->mStopIndex, matcher8Index);
+ EXPECT_EQ(durationProducer4->mStopAllIndex, -1);
+ DurationMetricProducer* durationProducer6 =
+ static_cast<DurationMetricProducer*>(newMetricProducers[duration6Index].get());
+ EXPECT_EQ(durationProducer6->getMetricId(), duration6Id);
+ EXPECT_EQ(durationProducer6->mConditionTrackerIndex, predicate5Index);
+ // TODO(b/167491517): should this be unknown since the condition is sliced?
+ EXPECT_EQ(durationProducer6->mCondition, ConditionState::kTrue);
+ EXPECT_EQ(durationProducer6->mStartIndex, matcher6Index);
+ EXPECT_EQ(durationProducer6->mStopIndex, matcher5Index);
+ EXPECT_EQ(durationProducer6->mStopAllIndex, -1);
+
+ sp<ConditionWizard> newConditionWizard = newMetricProducers[0]->mWizard;
+ EXPECT_NE(newConditionWizard, oldConditionWizard);
+ EXPECT_EQ(newConditionWizard->getStrongCount(), 8);
+ oldMetricProducers.clear();
+ // Only reference to the old wizard should be the one in the test.
+ EXPECT_EQ(oldConditionWizard->getStrongCount(), 1);
+}
+
TEST_F(ConfigUpdateTest, TestUpdateMetricActivations) {
StatsdConfig config;
// Add atom matchers
@@ -2376,11 +2723,16 @@ TEST_F(ConfigUpdateTest, TestUpdateMetricsMultipleTypes) {
int64_t gaugeMetricId = gaugeMetric.id();
*config.add_gauge_metric() = gaugeMetric;
+ // Preserved.
+ DurationMetric durationMetric = createDurationMetric("DURATION1", predicate1Id, nullopt, {});
+ int64_t durationMetricId = durationMetric.id();
+ *config.add_duration_metric() = durationMetric;
+
EXPECT_TRUE(initConfig(config));
// Used later to ensure the condition wizard is replaced. Get it before doing the update.
sp<ConditionWizard> oldConditionWizard = oldMetricProducers[0]->mWizard;
- EXPECT_EQ(oldConditionWizard->getStrongCount(), 4);
+ EXPECT_EQ(oldConditionWizard->getStrongCount(), 5);
// Mark matcher 2 as replaced. Causes eventMetric to be replaced.
set<int64_t> replacedMatchers;
@@ -2414,10 +2766,15 @@ TEST_F(ConfigUpdateTest, TestUpdateMetricsMultipleTypes) {
StatsdConfig newConfig;
*newConfig.add_count_metric() = countMetric;
const int countMetricIndex = 0;
+ *newConfig.add_duration_metric() = durationMetric;
+ const int durationMetricIndex = 1;
*newConfig.add_event_metric() = eventMetric;
- const int eventMetricIndex = 1;
+ const int eventMetricIndex = 2;
*newConfig.add_gauge_metric() = gaugeMetric;
- const int gaugeMetricIndex = 2;
+ const int gaugeMetricIndex = 3;
+
+ // Add the predicate since duration metric needs it.
+ *newConfig.add_predicate() = predicate1;
// Output data structures to validate.
unordered_map<int64_t, int> newMetricProducerMap;
@@ -2440,15 +2797,18 @@ TEST_F(ConfigUpdateTest, TestUpdateMetricsMultipleTypes) {
unordered_map<int64_t, int> expectedMetricProducerMap = {
{countMetricId, countMetricIndex},
+ {durationMetricId, durationMetricIndex},
{eventMetricId, eventMetricIndex},
{gaugeMetricId, gaugeMetricIndex},
};
EXPECT_THAT(newMetricProducerMap, ContainerEq(expectedMetricProducerMap));
// Make sure preserved metrics are the same.
- ASSERT_EQ(newMetricProducers.size(), 3);
+ ASSERT_EQ(newMetricProducers.size(), 4);
EXPECT_EQ(oldMetricProducers[oldMetricProducerMap.at(countMetricId)],
newMetricProducers[newMetricProducerMap.at(countMetricId)]);
+ EXPECT_EQ(oldMetricProducers[oldMetricProducerMap.at(durationMetricId)],
+ newMetricProducers[newMetricProducerMap.at(durationMetricId)]);
// Make sure replaced metrics are different.
EXPECT_NE(oldMetricProducers[oldMetricProducerMap.at(eventMetricId)],
@@ -2464,9 +2824,9 @@ TEST_F(ConfigUpdateTest, TestUpdateMetricsMultipleTypes) {
// Verify the trackerToMetricMap.
ASSERT_EQ(trackerToMetricMap.size(), 3);
const vector<int>& matcher1Metrics = trackerToMetricMap[matcher1Index];
- EXPECT_THAT(matcher1Metrics, UnorderedElementsAre(countMetricIndex));
+ EXPECT_THAT(matcher1Metrics, UnorderedElementsAre(countMetricIndex, durationMetricIndex));
const vector<int>& matcher2Metrics = trackerToMetricMap[matcher2Index];
- EXPECT_THAT(matcher2Metrics, UnorderedElementsAre(eventMetricIndex));
+ EXPECT_THAT(matcher2Metrics, UnorderedElementsAre(eventMetricIndex, durationMetricIndex));
const vector<int>& matcher3Metrics = trackerToMetricMap[matcher3Index];
EXPECT_THAT(matcher3Metrics, UnorderedElementsAre(gaugeMetricIndex));
@@ -2479,6 +2839,9 @@ TEST_F(ConfigUpdateTest, TestUpdateMetricsMultipleTypes) {
EXPECT_EQ(newMetricProducers[countMetricIndex]->getMetricId(), countMetricId);
EXPECT_EQ(newMetricProducers[countMetricIndex]->mConditionTrackerIndex, predicate1Index);
EXPECT_EQ(newMetricProducers[countMetricIndex]->mCondition, ConditionState::kUnknown);
+ EXPECT_EQ(newMetricProducers[durationMetricIndex]->getMetricId(), durationMetricId);
+ EXPECT_EQ(newMetricProducers[durationMetricIndex]->mConditionTrackerIndex, -1);
+ EXPECT_EQ(newMetricProducers[durationMetricIndex]->mCondition, ConditionState::kTrue);
EXPECT_EQ(newMetricProducers[eventMetricIndex]->getMetricId(), eventMetricId);
EXPECT_EQ(newMetricProducers[eventMetricIndex]->mConditionTrackerIndex, -1);
EXPECT_EQ(newMetricProducers[eventMetricIndex]->mCondition, ConditionState::kTrue);
@@ -2488,7 +2851,7 @@ TEST_F(ConfigUpdateTest, TestUpdateMetricsMultipleTypes) {
sp<ConditionWizard> newConditionWizard = newMetricProducers[0]->mWizard;
EXPECT_NE(newConditionWizard, oldConditionWizard);
- EXPECT_EQ(newConditionWizard->getStrongCount(), 4);
+ EXPECT_EQ(newConditionWizard->getStrongCount(), 5);
oldMetricProducers.clear();
// Only reference to the old wizard should be the one in the test.
EXPECT_EQ(oldConditionWizard->getStrongCount(), 1);
diff --git a/config/boot-image-profile.txt b/config/boot-image-profile.txt
index f43bd2bd61b9..01272c7966ac 100644
--- a/config/boot-image-profile.txt
+++ b/config/boot-image-profile.txt
@@ -47131,8 +47131,8 @@ Landroid/view/IRemoteAnimationRunner;
Landroid/view/IRotationWatcher$Stub$Proxy;
Landroid/view/IRotationWatcher$Stub;
Landroid/view/IRotationWatcher;
-Landroid/view/IScrollCaptureController$Stub;
-Landroid/view/IScrollCaptureController;
+Landroid/view/IScrollCaptureCallbacks$Stub;
+Landroid/view/IScrollCaptureCallbacks;
Landroid/view/ISystemGestureExclusionListener$Stub$Proxy;
Landroid/view/ISystemGestureExclusionListener$Stub;
Landroid/view/ISystemGestureExclusionListener;
diff --git a/core/java/android/accessibilityservice/AccessibilityGestureEvent.java b/core/java/android/accessibilityservice/AccessibilityGestureEvent.java
index e3139eb798f7..d4713cb611c3 100644
--- a/core/java/android/accessibilityservice/AccessibilityGestureEvent.java
+++ b/core/java/android/accessibilityservice/AccessibilityGestureEvent.java
@@ -46,6 +46,7 @@ import static android.accessibilityservice.AccessibilityService.GESTURE_4_FINGER
import static android.accessibilityservice.AccessibilityService.GESTURE_4_FINGER_TRIPLE_TAP;
import static android.accessibilityservice.AccessibilityService.GESTURE_DOUBLE_TAP;
import static android.accessibilityservice.AccessibilityService.GESTURE_DOUBLE_TAP_AND_HOLD;
+import static android.accessibilityservice.AccessibilityService.GESTURE_PASSTHROUGH;
import static android.accessibilityservice.AccessibilityService.GESTURE_SWIPE_DOWN;
import static android.accessibilityservice.AccessibilityService.GESTURE_SWIPE_DOWN_AND_LEFT;
import static android.accessibilityservice.AccessibilityService.GESTURE_SWIPE_DOWN_AND_RIGHT;
@@ -62,15 +63,21 @@ import static android.accessibilityservice.AccessibilityService.GESTURE_SWIPE_UP
import static android.accessibilityservice.AccessibilityService.GESTURE_SWIPE_UP_AND_DOWN;
import static android.accessibilityservice.AccessibilityService.GESTURE_SWIPE_UP_AND_LEFT;
import static android.accessibilityservice.AccessibilityService.GESTURE_SWIPE_UP_AND_RIGHT;
+import static android.accessibilityservice.AccessibilityService.GESTURE_TOUCH_EXPLORATION;
+import static android.accessibilityservice.AccessibilityService.GESTURE_UNKNOWN;
import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.TestApi;
+import android.content.pm.ParceledListSlice;
import android.os.Parcel;
import android.os.Parcelable;
+import android.view.MotionEvent;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
+import java.util.ArrayList;
+import java.util.List;
/**
* This class describes the gesture event including gesture id and which display it happens
@@ -87,6 +94,8 @@ public final class AccessibilityGestureEvent implements Parcelable {
/** @hide */
@IntDef(prefix = { "GESTURE_" }, value = {
+ GESTURE_UNKNOWN,
+ GESTURE_TOUCH_EXPLORATION,
GESTURE_2_FINGER_SINGLE_TAP,
GESTURE_2_FINGER_SINGLE_TAP_AND_HOLD,
GESTURE_2_FINGER_DOUBLE_TAP,
@@ -139,17 +148,27 @@ public final class AccessibilityGestureEvent implements Parcelable {
@GestureId
private final int mGestureId;
private final int mDisplayId;
+ private List<MotionEvent> mMotionEvents = new ArrayList<>();
/** @hide */
- @TestApi
- public AccessibilityGestureEvent(int gestureId, int displayId) {
+ public AccessibilityGestureEvent(
+ int gestureId, int displayId, @NonNull List<MotionEvent> motionEvents) {
mGestureId = gestureId;
mDisplayId = displayId;
+ mMotionEvents.addAll(motionEvents);
+ }
+
+ /** @hide */
+ @TestApi
+ public AccessibilityGestureEvent(int gestureId, int displayId) {
+ this(gestureId, displayId, new ArrayList<MotionEvent>());
}
private AccessibilityGestureEvent(@NonNull Parcel parcel) {
mGestureId = parcel.readInt();
mDisplayId = parcel.readInt();
+ ParceledListSlice<MotionEvent> slice = parcel.readParcelable(getClass().getClassLoader());
+ mMotionEvents = slice.getList();
}
/**
@@ -172,6 +191,15 @@ public final class AccessibilityGestureEvent implements Parcelable {
return mGestureId;
}
+ /**
+ * Returns the motion events that lead to this gesture.
+ *
+ */
+ @NonNull
+ public List<MotionEvent> getMotionEvents() {
+ return mMotionEvents;
+ }
+
@NonNull
@Override
public String toString() {
@@ -179,12 +207,26 @@ public final class AccessibilityGestureEvent implements Parcelable {
stringBuilder.append("gestureId: ").append(eventTypeToString(mGestureId));
stringBuilder.append(", ");
stringBuilder.append("displayId: ").append(mDisplayId);
+ stringBuilder.append(", ");
+ stringBuilder.append("Motion Events: [");
+ for (int i = 0; i < mMotionEvents.size(); ++i) {
+ String action = MotionEvent.actionToString(mMotionEvents.get(i).getActionMasked());
+ stringBuilder.append(action);
+ if (i < (mMotionEvents.size() - 1)) {
+ stringBuilder.append(", ");
+ } else {
+ stringBuilder.append("]");
+ }
+ }
stringBuilder.append(']');
return stringBuilder.toString();
}
private static String eventTypeToString(int eventType) {
switch (eventType) {
+ case GESTURE_UNKNOWN: return "GESTURE_UNKNOWN";
+ case GESTURE_PASSTHROUGH: return "GESTURE_PASSTHROUGH";
+ case GESTURE_TOUCH_EXPLORATION: return "GESTURE_TOUCH_EXPLORATION";
case GESTURE_2_FINGER_SINGLE_TAP: return "GESTURE_2_FINGER_SINGLE_TAP";
case GESTURE_2_FINGER_SINGLE_TAP_AND_HOLD:
return "GESTURE_2_FINGER_SINGLE_TAP_AND_HOLD";
@@ -252,6 +294,7 @@ public final class AccessibilityGestureEvent implements Parcelable {
public void writeToParcel(@NonNull Parcel parcel, int flags) {
parcel.writeInt(mGestureId);
parcel.writeInt(mDisplayId);
+ parcel.writeParcelable(new ParceledListSlice<MotionEvent>(mMotionEvents), 0);
}
/**
diff --git a/core/java/android/accessibilityservice/AccessibilityService.java b/core/java/android/accessibilityservice/AccessibilityService.java
index 7c6d4484ee12..0ad9e446dfc7 100644
--- a/core/java/android/accessibilityservice/AccessibilityService.java
+++ b/core/java/android/accessibilityservice/AccessibilityService.java
@@ -235,6 +235,29 @@ import java.util.function.Consumer;
public abstract class AccessibilityService extends Service {
/**
+ * The user has performed a touch-exploration gesture on the touch screen without ever
+ * triggering gesture detection. This gesture is only dispatched when {@link
+ * AccessibilityServiceInfo#FLAG_SEND_MOTION_EVENTS} is set.
+ *
+ * @hide
+ */
+ public static final int GESTURE_TOUCH_EXPLORATION = -2;
+
+ /**
+ * The user has performed a passthrough gesture on the touch screen without ever triggering
+ * gesture detection. This gesture is only dispatched when {@link
+ * AccessibilityServiceInfo#FLAG_SEND_MOTION_EVENTS} is set.
+ * @hide
+ */
+ public static final int GESTURE_PASSTHROUGH = -1;
+
+ /**
+ * The user has performed an unrecognized gesture on the touch screen. This gesture is only
+ * dispatched when {@link AccessibilityServiceInfo#FLAG_SEND_MOTION_EVENTS} is set.
+ */
+ public static final int GESTURE_UNKNOWN = 0;
+
+ /**
* The user has performed a swipe up gesture on the touch screen.
*/
public static final int GESTURE_SWIPE_UP = 1;
diff --git a/core/java/android/accessibilityservice/AccessibilityServiceInfo.java b/core/java/android/accessibilityservice/AccessibilityServiceInfo.java
index 769d006cb2b6..f953da48c217 100644
--- a/core/java/android/accessibilityservice/AccessibilityServiceInfo.java
+++ b/core/java/android/accessibilityservice/AccessibilityServiceInfo.java
@@ -376,6 +376,20 @@ public class AccessibilityServiceInfo implements Parcelable {
*/
public static final int FLAG_REQUEST_2_FINGER_PASSTHROUGH = 0x0002000;
+ /**
+ * This flag requests that when when {@link #FLAG_REQUEST_TOUCH_EXPLORATION_MODE} is enabled, a
+ * service will receive the motion events for each successfully-detected gesture. The service
+ * will also receive an AccessibilityGestureEvent of type GESTURE_INVALID for each cancelled
+ * gesture along with its motion events. A service will receive a gesture of type
+ * GESTURE_PASSTHROUGH and accompanying motion events for every passthrough gesture that does
+ * not start gesture detection. This information can be used to collect instances of improper
+ * gesture detection behavior and relay that information to framework developers. If {@link
+ * #FLAG_REQUEST_TOUCH_EXPLORATION_MODE} is disabled this flag has no effect.
+ *
+ * @see #FLAG_REQUEST_TOUCH_EXPLORATION_MODE
+ */
+ public static final int FLAG_SEND_MOTION_EVENTS = 0x0004000;
+
/** {@hide} */
public static final int FLAG_FORCE_DIRECT_BOOT_AWARE = 0x00010000;
@@ -1276,6 +1290,8 @@ public class AccessibilityServiceInfo implements Parcelable {
return "FLAG_REQUEST_MULTI_FINGER_GESTURES";
case FLAG_REQUEST_2_FINGER_PASSTHROUGH:
return "FLAG_REQUEST_2_FINGER_PASSTHROUGH";
+ case FLAG_SEND_MOTION_EVENTS:
+ return "FLAG_SEND_MOTION_EVENTS";
case FLAG_REQUEST_ENHANCED_WEB_ACCESSIBILITY:
return "FLAG_REQUEST_ENHANCED_WEB_ACCESSIBILITY";
case FLAG_REPORT_VIEW_IDS:
diff --git a/core/java/android/app/ActivityManager.java b/core/java/android/app/ActivityManager.java
index cb98093a1a24..250f2f0b2dc9 100644
--- a/core/java/android/app/ActivityManager.java
+++ b/core/java/android/app/ActivityManager.java
@@ -3608,7 +3608,7 @@ public class ActivityManager {
* running its code, {@link RunningAppProcessInfo#IMPORTANCE_GONE} is returned.
* @hide
*/
- @SystemApi @TestApi
+ @SystemApi
@RequiresPermission(Manifest.permission.PACKAGE_USAGE_STATS)
public @RunningAppProcessInfo.Importance int getPackageImportance(String packageName) {
try {
@@ -3628,7 +3628,7 @@ public class ActivityManager {
* running its code, {@link RunningAppProcessInfo#IMPORTANCE_GONE} is returned.
* @hide
*/
- @SystemApi @TestApi
+ @SystemApi
@RequiresPermission(Manifest.permission.PACKAGE_USAGE_STATS)
public @RunningAppProcessInfo.Importance int getUidImportance(int uid) {
try {
@@ -3645,7 +3645,7 @@ public class ActivityManager {
* {@link #addOnUidImportanceListener}.
* @hide
*/
- @SystemApi @TestApi
+ @SystemApi
public interface OnUidImportanceListener {
/**
* The importance if a given uid has changed. Will be one of the importance
@@ -3676,7 +3676,7 @@ public class ActivityManager {
* {@link android.Manifest.permission#PACKAGE_USAGE_STATS}.
* @hide
*/
- @SystemApi @TestApi
+ @SystemApi
@RequiresPermission(Manifest.permission.PACKAGE_USAGE_STATS)
public void addOnUidImportanceListener(OnUidImportanceListener listener,
@RunningAppProcessInfo.Importance int importanceCutpoint) {
@@ -3705,7 +3705,7 @@ public class ActivityManager {
* @throws IllegalArgumentException If the listener is not registered.
* @hide
*/
- @SystemApi @TestApi
+ @SystemApi
@RequiresPermission(Manifest.permission.PACKAGE_USAGE_STATS)
public void removeOnUidImportanceListener(OnUidImportanceListener listener) {
synchronized (this) {
@@ -3847,7 +3847,7 @@ public class ActivityManager {
* @see #forceStopPackageAsUser(String, int)
* @hide
*/
- @SystemApi @TestApi
+ @SystemApi
@RequiresPermission(Manifest.permission.FORCE_STOP_PACKAGES)
public void forceStopPackage(String packageName) {
forceStopPackageAsUser(packageName, mContext.getUserId());
@@ -4186,7 +4186,6 @@ public class ActivityManager {
* @hide
*/
@SystemApi
- @TestApi
@RequiresPermission(android.Manifest.permission.MANAGE_USERS)
public boolean switchUser(@NonNull UserHandle user) {
if (user == null) {
@@ -4619,7 +4618,7 @@ public class ActivityManager {
*
* @hide
*/
- @SystemApi @TestApi
+ @SystemApi
@RequiresPermission(Manifest.permission.FORCE_STOP_PACKAGES)
public void killProcessesWhenImperceptible(@NonNull int[] pids, @NonNull String reason) {
try {
diff --git a/core/java/android/app/ActivityTaskManager.java b/core/java/android/app/ActivityTaskManager.java
index d0a0e30bad18..9edf81e8f651 100644
--- a/core/java/android/app/ActivityTaskManager.java
+++ b/core/java/android/app/ActivityTaskManager.java
@@ -406,19 +406,6 @@ public class ActivityTaskManager {
}
/**
- * Makes the display with the given id a single task instance display. I.e the display can only
- * contain one task.
- */
- @RequiresPermission(android.Manifest.permission.MANAGE_ACTIVITY_STACKS)
- public void setDisplayToSingleTaskInstance(int displayId) {
- try {
- getService().setDisplayToSingleTaskInstance(displayId);
- } catch (RemoteException e) {
- throw e.rethrowFromSystemServer();
- }
- }
-
- /**
* Requests that an activity should enter picture-in-picture mode if possible.
* @hide
*/
diff --git a/core/java/android/app/ActivityView.java b/core/java/android/app/ActivityView.java
index db95eae112b5..8c42a8a55bb1 100644
--- a/core/java/android/app/ActivityView.java
+++ b/core/java/android/app/ActivityView.java
@@ -85,8 +85,7 @@ public class ActivityView extends ViewGroup implements android.window.TaskEmbedd
}
public ActivityView(Context context, AttributeSet attrs) {
- this(context, attrs, 0 /* defStyle */, false /* singleTaskInstance */,
- false /* usePublicVirtualDisplay */,
+ this(context, attrs, 0 /* defStyle */, false /* usePublicVirtualDisplay */,
false /* disableSurfaceViewBackgroundLayer */, false /* useTrustedDisplay */);
}
@@ -97,22 +96,21 @@ public class ActivityView extends ViewGroup implements android.window.TaskEmbedd
*/
public ActivityView(
@NonNull Context context, @NonNull AttributeSet attrs, int defStyle,
- boolean singleTaskInstance, boolean usePublicVirtualDisplay) {
- this(context, attrs, defStyle, singleTaskInstance, usePublicVirtualDisplay,
- false /* disableSurfaceViewBackgroundLayer */,
- false /* useTrustedDisplay */);
+ boolean usePublicVirtualDisplay) {
+ this(context, attrs, defStyle, usePublicVirtualDisplay,
+ false /* disableSurfaceViewBackgroundLayer */, false /* useTrustedDisplay */);
}
private ActivityView(
@NonNull Context context, @NonNull AttributeSet attrs, int defStyle,
- boolean singleTaskInstance, boolean usePublicVirtualDisplay,
- boolean disableSurfaceViewBackgroundLayer, boolean useTrustedDisplay) {
+ boolean usePublicVirtualDisplay, boolean disableSurfaceViewBackgroundLayer,
+ boolean useTrustedDisplay) {
super(context, attrs, defStyle);
if (useTaskOrganizer()) {
mTaskEmbedder = new TaskOrganizerTaskEmbedder(context, this);
} else {
- mTaskEmbedder = new VirtualDisplayTaskEmbedder(context, this, singleTaskInstance,
- usePublicVirtualDisplay, useTrustedDisplay);
+ mTaskEmbedder = new VirtualDisplayTaskEmbedder(context, this, usePublicVirtualDisplay,
+ useTrustedDisplay);
}
mSurfaceView = new SurfaceView(context, null, 0, 0, disableSurfaceViewBackgroundLayer);
// Since ActivityView#getAlpha has been overridden, we should use parent class's alpha
@@ -641,7 +639,6 @@ public class ActivityView extends ViewGroup implements android.window.TaskEmbedd
private final Context mContext;
private AttributeSet mAttrs;
private int mDefStyle;
- private boolean mSingleInstance;
private boolean mUsePublicVirtualDisplay;
private boolean mDisableSurfaceViewBackgroundLayer;
private boolean mUseTrustedDisplay;
@@ -650,7 +647,6 @@ public class ActivityView extends ViewGroup implements android.window.TaskEmbedd
mContext = context;
mAttrs = null;
mDefStyle = 0;
- mSingleInstance = false;
mUsePublicVirtualDisplay = false;
mDisableSurfaceViewBackgroundLayer = false;
mUseTrustedDisplay = false;
@@ -676,13 +672,6 @@ public class ActivityView extends ViewGroup implements android.window.TaskEmbedd
return this;
}
- /** Sets to {@code true} to make the {@link ActivityView} single instance. */
- @NonNull
- public Builder setSingleInstance(boolean singleInstance) {
- mSingleInstance = singleInstance;
- return this;
- }
-
/**
* Sets to {@code true} to use public virtual display for the {@link ActivityView}.
* <p>
@@ -722,7 +711,7 @@ public class ActivityView extends ViewGroup implements android.window.TaskEmbedd
/** Creates an {@link ActivityView} */
@NonNull
public ActivityView build() {
- return new ActivityView(mContext, mAttrs, mDefStyle, mSingleInstance,
+ return new ActivityView(mContext, mAttrs, mDefStyle,
mUsePublicVirtualDisplay, mDisableSurfaceViewBackgroundLayer,
mUseTrustedDisplay);
}
diff --git a/core/java/android/app/AppOpsManager.java b/core/java/android/app/AppOpsManager.java
index c5bc3564ceab..f3b37891876d 100644
--- a/core/java/android/app/AppOpsManager.java
+++ b/core/java/android/app/AppOpsManager.java
@@ -461,7 +461,6 @@ public class AppOpsManager {
* state the more important the UID is for the user.
* @hide
*/
- @TestApi
@SystemApi
public static final int UID_STATE_PERSISTENT = 100;
@@ -470,7 +469,6 @@ public class AppOpsManager {
* state the more important the UID is for the user.
* @hide
*/
- @TestApi
@SystemApi
public static final int UID_STATE_TOP = 200;
@@ -482,7 +480,6 @@ public class AppOpsManager {
* @hide
* @deprecated
*/
- @TestApi
@SystemApi
@Deprecated
public static final int UID_STATE_FOREGROUND_SERVICE_LOCATION = 300;
@@ -492,7 +489,6 @@ public class AppOpsManager {
* state the more important the UID is for the user.
* @hide
*/
- @TestApi
@SystemApi
public static final int UID_STATE_FOREGROUND_SERVICE = 400;
@@ -501,7 +497,6 @@ public class AppOpsManager {
* state the more important the UID is for the user.
* @hide
*/
- @TestApi
@SystemApi
public static final int UID_STATE_FOREGROUND = 500;
@@ -517,7 +512,6 @@ public class AppOpsManager {
* state the more important the UID is for the user.
* @hide
*/
- @TestApi
@SystemApi
public static final int UID_STATE_BACKGROUND = 600;
@@ -526,7 +520,6 @@ public class AppOpsManager {
* state the more important the UID is for the user.
* @hide
*/
- @TestApi
@SystemApi
public static final int UID_STATE_CACHED = 700;
@@ -604,7 +597,6 @@ public class AppOpsManager {
*
* @hide
*/
- @TestApi
@SystemApi
public static final int OP_FLAG_SELF = 0x1;
@@ -615,7 +607,6 @@ public class AppOpsManager {
*
* @hide
*/
- @TestApi
@SystemApi
public static final int OP_FLAG_TRUSTED_PROXY = 0x2;
@@ -626,7 +617,6 @@ public class AppOpsManager {
*
* @hide
*/
- @TestApi
@SystemApi
public static final int OP_FLAG_UNTRUSTED_PROXY = 0x4;
@@ -637,7 +627,6 @@ public class AppOpsManager {
*
* @hide
*/
- @TestApi
@SystemApi
public static final int OP_FLAG_TRUSTED_PROXIED = 0x8;
@@ -648,7 +637,6 @@ public class AppOpsManager {
*
* @hide
*/
- @TestApi
@SystemApi
public static final int OP_FLAG_UNTRUSTED_PROXIED = 0x10;
@@ -660,7 +648,6 @@ public class AppOpsManager {
*
* @hide
*/
- @TestApi
@SystemApi
public static final int OP_FLAGS_ALL =
OP_FLAG_SELF
@@ -1185,7 +1172,7 @@ public class AppOpsManager {
public static final String OPSTR_GET_USAGE_STATS
= "android:get_usage_stats";
/** Activate a VPN connection without user intervention. @hide */
- @SystemApi @TestApi
+ @SystemApi
public static final String OPSTR_ACTIVATE_VPN
= "android:activate_vpn";
/** Allows an application to read the user's contacts data. */
@@ -1267,7 +1254,7 @@ public class AppOpsManager {
public static final String OPSTR_WRITE_SETTINGS
= "android:write_settings";
/** @hide Get device accounts. */
- @SystemApi @TestApi
+ @SystemApi
public static final String OPSTR_GET_ACCOUNTS
= "android:get_accounts";
public static final String OPSTR_READ_PHONE_NUMBERS
@@ -1276,7 +1263,7 @@ public class AppOpsManager {
public static final String OPSTR_PICTURE_IN_PICTURE
= "android:picture_in_picture";
/** @hide */
- @SystemApi @TestApi
+ @SystemApi
public static final String OPSTR_INSTANT_APP_START_FOREGROUND
= "android:instant_app_start_foreground";
/** Answer incoming phone calls */
@@ -1286,129 +1273,129 @@ public class AppOpsManager {
* Accept call handover
* @hide
*/
- @SystemApi @TestApi
+ @SystemApi
public static final String OPSTR_ACCEPT_HANDOVER
= "android:accept_handover";
/** @hide */
- @SystemApi @TestApi
+ @SystemApi
public static final String OPSTR_GPS = "android:gps";
/** @hide */
- @SystemApi @TestApi
+ @SystemApi
public static final String OPSTR_VIBRATE = "android:vibrate";
/** @hide */
- @SystemApi @TestApi
+ @SystemApi
public static final String OPSTR_WIFI_SCAN = "android:wifi_scan";
/** @hide */
- @SystemApi @TestApi
+ @SystemApi
public static final String OPSTR_POST_NOTIFICATION = "android:post_notification";
/** @hide */
- @SystemApi @TestApi
+ @SystemApi
public static final String OPSTR_NEIGHBORING_CELLS = "android:neighboring_cells";
/** @hide */
- @SystemApi @TestApi
+ @SystemApi
public static final String OPSTR_WRITE_SMS = "android:write_sms";
/** @hide */
- @SystemApi @TestApi
+ @SystemApi
public static final String OPSTR_RECEIVE_EMERGENCY_BROADCAST =
"android:receive_emergency_broadcast";
/** @hide */
- @SystemApi @TestApi
+ @SystemApi
public static final String OPSTR_READ_ICC_SMS = "android:read_icc_sms";
/** @hide */
- @SystemApi @TestApi
+ @SystemApi
public static final String OPSTR_WRITE_ICC_SMS = "android:write_icc_sms";
/** @hide */
- @SystemApi @TestApi
+ @SystemApi
public static final String OPSTR_ACCESS_NOTIFICATIONS = "android:access_notifications";
/** @hide */
- @SystemApi @TestApi
+ @SystemApi
public static final String OPSTR_PLAY_AUDIO = "android:play_audio";
/** @hide */
- @SystemApi @TestApi
+ @SystemApi
public static final String OPSTR_READ_CLIPBOARD = "android:read_clipboard";
/** @hide */
- @SystemApi @TestApi
+ @SystemApi
public static final String OPSTR_WRITE_CLIPBOARD = "android:write_clipboard";
/** @hide */
- @SystemApi @TestApi
+ @SystemApi
public static final String OPSTR_TAKE_MEDIA_BUTTONS = "android:take_media_buttons";
/** @hide */
- @SystemApi @TestApi
+ @SystemApi
public static final String OPSTR_TAKE_AUDIO_FOCUS = "android:take_audio_focus";
/** @hide */
- @SystemApi @TestApi
+ @SystemApi
public static final String OPSTR_AUDIO_MASTER_VOLUME = "android:audio_master_volume";
/** @hide */
- @SystemApi @TestApi
+ @SystemApi
public static final String OPSTR_AUDIO_VOICE_VOLUME = "android:audio_voice_volume";
/** @hide */
- @SystemApi @TestApi
+ @SystemApi
public static final String OPSTR_AUDIO_RING_VOLUME = "android:audio_ring_volume";
/** @hide */
- @SystemApi @TestApi
+ @SystemApi
public static final String OPSTR_AUDIO_MEDIA_VOLUME = "android:audio_media_volume";
/** @hide */
- @SystemApi @TestApi
+ @SystemApi
public static final String OPSTR_AUDIO_ALARM_VOLUME = "android:audio_alarm_volume";
/** @hide */
- @SystemApi @TestApi
+ @SystemApi
public static final String OPSTR_AUDIO_NOTIFICATION_VOLUME =
"android:audio_notification_volume";
/** @hide */
- @SystemApi @TestApi
+ @SystemApi
public static final String OPSTR_AUDIO_BLUETOOTH_VOLUME = "android:audio_bluetooth_volume";
/** @hide */
- @SystemApi @TestApi
+ @SystemApi
public static final String OPSTR_WAKE_LOCK = "android:wake_lock";
/** @hide */
- @SystemApi @TestApi
+ @SystemApi
public static final String OPSTR_MUTE_MICROPHONE = "android:mute_microphone";
/** @hide */
- @SystemApi @TestApi
+ @SystemApi
public static final String OPSTR_TOAST_WINDOW = "android:toast_window";
/** @hide */
- @SystemApi @TestApi
+ @SystemApi
public static final String OPSTR_PROJECT_MEDIA = "android:project_media";
/** @hide */
- @SystemApi @TestApi
+ @SystemApi
public static final String OPSTR_WRITE_WALLPAPER = "android:write_wallpaper";
/** @hide */
- @SystemApi @TestApi
+ @SystemApi
public static final String OPSTR_ASSIST_STRUCTURE = "android:assist_structure";
/** @hide */
- @SystemApi @TestApi
+ @SystemApi
public static final String OPSTR_ASSIST_SCREENSHOT = "android:assist_screenshot";
/** @hide */
- @SystemApi @TestApi
+ @SystemApi
public static final String OPSTR_TURN_SCREEN_ON = "android:turn_screen_on";
/** @hide */
- @SystemApi @TestApi
+ @SystemApi
public static final String OPSTR_RUN_IN_BACKGROUND = "android:run_in_background";
/** @hide */
- @SystemApi @TestApi
+ @SystemApi
public static final String OPSTR_AUDIO_ACCESSIBILITY_VOLUME =
"android:audio_accessibility_volume";
/** @hide */
- @SystemApi @TestApi
+ @SystemApi
public static final String OPSTR_REQUEST_INSTALL_PACKAGES = "android:request_install_packages";
/** @hide */
- @SystemApi @TestApi
+ @SystemApi
public static final String OPSTR_RUN_ANY_IN_BACKGROUND = "android:run_any_in_background";
/** @hide */
- @SystemApi @TestApi
+ @SystemApi
public static final String OPSTR_CHANGE_WIFI_STATE = "android:change_wifi_state";
/** @hide */
- @SystemApi @TestApi
+ @SystemApi
public static final String OPSTR_REQUEST_DELETE_PACKAGES = "android:request_delete_packages";
/** @hide */
- @SystemApi @TestApi
+ @SystemApi
public static final String OPSTR_BIND_ACCESSIBILITY_SERVICE =
"android:bind_accessibility_service";
/** @hide */
- @SystemApi @TestApi
+ @SystemApi
public static final String OPSTR_MANAGE_IPSEC_TUNNELS = "android:manage_ipsec_tunnels";
/** @hide */
- @SystemApi @TestApi
+ @SystemApi
public static final String OPSTR_START_FOREGROUND = "android:start_foreground";
/** @hide */
public static final String OPSTR_BLUETOOTH_SCAN = "android:bluetooth_scan";
@@ -1424,25 +1411,25 @@ public class AppOpsManager {
"android:sms_financial_transactions";
/** @hide Read media of audio type. */
- @SystemApi @TestApi
+ @SystemApi
public static final String OPSTR_READ_MEDIA_AUDIO = "android:read_media_audio";
/** @hide Write media of audio type. */
- @SystemApi @TestApi
+ @SystemApi
public static final String OPSTR_WRITE_MEDIA_AUDIO = "android:write_media_audio";
/** @hide Read media of video type. */
- @SystemApi @TestApi
+ @SystemApi
public static final String OPSTR_READ_MEDIA_VIDEO = "android:read_media_video";
/** @hide Write media of video type. */
- @SystemApi @TestApi
+ @SystemApi
public static final String OPSTR_WRITE_MEDIA_VIDEO = "android:write_media_video";
/** @hide Read media of image type. */
- @SystemApi @TestApi
+ @SystemApi
public static final String OPSTR_READ_MEDIA_IMAGES = "android:read_media_images";
/** @hide Write media of image type. */
- @SystemApi @TestApi
+ @SystemApi
public static final String OPSTR_WRITE_MEDIA_IMAGES = "android:write_media_images";
/** @hide Has a legacy (non-isolated) view of storage. */
- @SystemApi @TestApi
+ @SystemApi
public static final String OPSTR_LEGACY_STORAGE = "android:legacy_storage";
/** @hide Read location metadata from media */
public static final String OPSTR_ACCESS_MEDIA_LOCATION = "android:access_media_location";
@@ -1456,7 +1443,6 @@ public class AppOpsManager {
public static final String OPSTR_QUERY_ALL_PACKAGES = "android:query_all_packages";
/** @hide Access all external storage */
@SystemApi
- @TestApi
public static final String OPSTR_MANAGE_EXTERNAL_STORAGE =
"android:manage_external_storage";
@@ -2683,7 +2669,6 @@ public class AppOpsManager {
*
* @hide
*/
- @TestApi
@SystemApi
public static int opToDefaultMode(@NonNull String appOp) {
return opToDefaultMode(strOpToOp(appOp));
@@ -2775,7 +2760,6 @@ public class AppOpsManager {
* Class holding all of the operation information associated with an app.
* @hide
*/
- @TestApi
@SystemApi
public static final class PackageOps implements Parcelable {
private final String mPackageName;
@@ -2854,7 +2838,6 @@ public class AppOpsManager {
*
* @hide
*/
- @TestApi
@SystemApi
// @DataClass(genHiddenConstructor = true, genHiddenCopyConstructor = true)
// genHiddenCopyConstructor does not work for @hide @SystemApi classes
@@ -3222,7 +3205,6 @@ public class AppOpsManager {
*
* @hide
*/
- @TestApi
@SystemApi
@Immutable
// @DataClass(genHiddenConstructor = true) codegen verifier is broken
@@ -3796,7 +3778,6 @@ public class AppOpsManager {
*
* @hide
*/
- @TestApi
@Immutable
@SystemApi
// @DataClass(genHiddenConstructor = true) codegen verifier is broken
@@ -4474,7 +4455,6 @@ public class AppOpsManager {
* @hide
*/
@Immutable
- @TestApi
@SystemApi
public static final class HistoricalOpsRequest {
private final int mUid;
@@ -4505,7 +4485,6 @@ public class AppOpsManager {
*
* @hide
*/
- @TestApi
@SystemApi
public static final class Builder {
private int mUid = Process.INVALID_UID;
@@ -4643,7 +4622,6 @@ public class AppOpsManager {
*
* @hide
*/
- @TestApi
@SystemApi
public static final class HistoricalOps implements Parcelable {
private long mBeginTimeMillis;
@@ -5079,7 +5057,6 @@ public class AppOpsManager {
*
* @hide
*/
- @TestApi
@SystemApi
public static final class HistoricalUidOps implements Parcelable {
private final int mUid;
@@ -5333,7 +5310,6 @@ public class AppOpsManager {
*
* @hide
*/
- @TestApi
@SystemApi
public static final class HistoricalPackageOps implements Parcelable {
private final @NonNull String mPackageName;
@@ -5664,7 +5640,6 @@ public class AppOpsManager {
*
* @hide
*/
- @TestApi
@SystemApi
/* codegen verifier cannot deal with nested class parameters
@DataClass(genHiddenConstructor = true,
@@ -5975,7 +5950,6 @@ public class AppOpsManager {
*
* @hide
*/
- @TestApi
@SystemApi
public static final class HistoricalOp implements Parcelable {
private final int mOp;
@@ -6612,7 +6586,6 @@ public class AppOpsManager {
*
* @hide
*/
- @TestApi
@SystemApi
@RequiresPermission(android.Manifest.permission.GET_APP_OPS_STATS)
public @NonNull List<AppOpsManager.PackageOps> getOpsForPackage(int uid,
@@ -6647,7 +6620,6 @@ public class AppOpsManager {
*
* @hide
*/
- @TestApi
@SystemApi
@RequiresPermission(android.Manifest.permission.GET_APP_OPS_STATS)
public void getHistoricalOps(@NonNull HistoricalOpsRequest request,
@@ -6756,7 +6728,6 @@ public class AppOpsManager {
* @hide
*/
@SystemApi
- @TestApi
@RequiresPermission(android.Manifest.permission.MANAGE_APP_OPS_MODES)
public void setUidMode(@NonNull String appOp, int uid, @Mode int mode) {
try {
@@ -6810,7 +6781,6 @@ public class AppOpsManager {
* be changed.
* @hide
*/
- @TestApi
@SystemApi
@RequiresPermission(android.Manifest.permission.MANAGE_APP_OPS_MODES)
public void setMode(@NonNull String op, int uid, @Nullable String packageName,
@@ -8773,7 +8743,6 @@ public class AppOpsManager {
* @hide
*/
@SystemApi
- @TestApi
@RequiresPermission(Manifest.permission.GET_APP_OPS_STATS)
public @Nullable RuntimeAppOpAccessMessage collectRuntimeAppOpAccessMessage() {
try {
@@ -8788,7 +8757,6 @@ public class AppOpsManager {
* @hide
*/
@SystemApi
- @TestApi
public static String[] getOpStrs() {
return Arrays.copyOf(sOpToString, sOpToString.length);
}
diff --git a/core/java/android/app/IActivityTaskManager.aidl b/core/java/android/app/IActivityTaskManager.aidl
index 75302293088f..8a03fcc33d51 100644
--- a/core/java/android/app/IActivityTaskManager.aidl
+++ b/core/java/android/app/IActivityTaskManager.aidl
@@ -434,12 +434,6 @@ interface IActivityTaskManager {
void clearLaunchParamsForPackages(in List<String> packageNames);
/**
- * Makes the display with the given id a single task instance display. I.e the display can only
- * contain one task.
- */
- void setDisplayToSingleTaskInstance(int displayId);
-
- /**
* Restarts the activity by killing its process if it is visible. If the activity is not
* visible, the activity will not be restarted immediately and just keep the activity record in
* the stack. It also resets the current override configuration so the activity will use the
diff --git a/core/java/android/app/ITaskStackListener.aidl b/core/java/android/app/ITaskStackListener.aidl
index aec9f3e98960..dc7782a1ad3c 100644
--- a/core/java/android/app/ITaskStackListener.aidl
+++ b/core/java/android/app/ITaskStackListener.aidl
@@ -163,21 +163,6 @@ oneway interface ITaskStackListener {
*/
void onBackPressedOnTaskRoot(in ActivityManager.RunningTaskInfo taskInfo);
- /*
- * Called when contents are drawn for the first time on a display which can only contain one
- * task.
- *
- * @param displayId the id of the display on which contents are drawn.
- */
- void onSingleTaskDisplayDrawn(int displayId);
-
- /*
- * Called when the last task is removed from a display which can only contain one task.
- *
- * @param displayId the id of the display from which the window is removed.
- */
- void onSingleTaskDisplayEmpty(int displayId);
-
/**
* Called when a task is reparented to a stack on a different display.
*
diff --git a/core/java/android/app/Notification.java b/core/java/android/app/Notification.java
index 54380629e4ca..5e50b96a23d5 100644
--- a/core/java/android/app/Notification.java
+++ b/core/java/android/app/Notification.java
@@ -82,7 +82,6 @@ import android.util.Pair;
import android.util.SparseArray;
import android.util.proto.ProtoOutputStream;
import android.view.Gravity;
-import android.view.NotificationHeaderView;
import android.view.View;
import android.view.ViewGroup;
import android.view.contentcapture.ContentCaptureContext;
@@ -4825,7 +4824,7 @@ public class Notification implements Parcelable
private void resetNotificationHeader(RemoteViews contentView) {
// Small icon doesn't need to be reset, as it's always set. Resetting would prevent
// re-using the drawable when the notification is updated.
- contentView.setBoolean(R.id.notification_header, "setExpanded", false);
+ contentView.setBoolean(R.id.expand_button, "setExpanded", false);
contentView.setTextViewText(R.id.app_name_text, null);
contentView.setViewVisibility(R.id.chronometer, View.GONE);
contentView.setViewVisibility(R.id.header_text, View.GONE);
@@ -5569,7 +5568,7 @@ public class Notification implements Parcelable
*/
public static void makeHeaderExpanded(RemoteViews result) {
if (result != null) {
- result.setBoolean(R.id.notification_header, "setExpanded", true);
+ result.setBoolean(R.id.expand_button, "setExpanded", true);
}
}
@@ -5862,24 +5861,16 @@ public class Notification implements Parcelable
}
/**
- * Apply any necessariy colors to the small icon
+ * Apply any necessary colors to the small icon
*/
private void processSmallIconColor(Icon smallIcon, RemoteViews contentView,
StandardTemplateParams p) {
boolean colorable = !isLegacy() || getColorUtil().isGrayscaleIcon(mContext, smallIcon);
- int color;
- if (isColorized(p)) {
- color = getPrimaryTextColor(p);
- } else {
- color = resolveContrastColor(p);
- }
- if (colorable) {
- contentView.setDrawableTint(R.id.icon, false, color,
- PorterDuff.Mode.SRC_ATOP);
-
- }
+ int color = isColorized(p) ? getPrimaryTextColor(p) : resolveContrastColor(p);
+ contentView.setInt(R.id.icon, "setBackgroundColor",
+ resolveBackgroundColor(p));
contentView.setInt(R.id.icon, "setOriginalIconColor",
- colorable ? color : NotificationHeaderView.NO_COLOR);
+ colorable ? color : COLOR_INVALID);
}
/**
@@ -5892,8 +5883,8 @@ public class Notification implements Parcelable
if (largeIcon != null && isLegacy()
&& getColorUtil().isGrayscaleIcon(mContext, largeIcon)) {
// resolve color will fall back to the default when legacy
- contentView.setDrawableTint(R.id.icon, false, resolveContrastColor(p),
- PorterDuff.Mode.SRC_ATOP);
+ int color = resolveContrastColor(p);
+ contentView.setInt(R.id.icon, "setOriginalIconColor", color);
}
}
@@ -8457,9 +8448,7 @@ public class Notification implements Parcelable
Action action, StandardTemplateParams p) {
final boolean tombstone = (action.actionIntent == null);
container.setViewVisibility(buttonId, View.VISIBLE);
- if (buttonId != R.id.media_seamless) {
- container.setImageViewIcon(buttonId, action.getIcon());
- }
+ container.setImageViewIcon(buttonId, action.getIcon());
// If the action buttons should not be tinted, then just use the default
// notification color. Otherwise, just use the passed-in color.
@@ -8513,10 +8502,6 @@ public class Notification implements Parcelable
view.setViewVisibility(MEDIA_BUTTON_IDS[i], View.GONE);
}
}
- bindMediaActionButton(view, R.id.media_seamless, new Action(
- R.drawable.ic_media_seamless, mBuilder.mContext.getString(
- com.android.internal.R.string.ext_media_seamless_action), null), p);
- view.setViewVisibility(R.id.media_seamless, View.GONE);
handleImage(view);
// handle the content margin
int endMargin = R.dimen.notification_content_margin_end;
@@ -8553,10 +8538,6 @@ public class Notification implements Parcelable
big.setViewVisibility(MEDIA_BUTTON_IDS[i], View.GONE);
}
}
- bindMediaActionButton(big, R.id.media_seamless, new Action(R.drawable.ic_media_seamless,
- mBuilder.mContext.getString(
- com.android.internal.R.string.ext_media_seamless_action), null), p);
- big.setViewVisibility(R.id.media_seamless, View.GONE);
handleImage(big);
return big;
}
diff --git a/core/java/android/app/NotificationChannel.java b/core/java/android/app/NotificationChannel.java
index 1bfdaf57e7f4..a06ffbdb4301 100644
--- a/core/java/android/app/NotificationChannel.java
+++ b/core/java/android/app/NotificationChannel.java
@@ -134,7 +134,6 @@ public final class NotificationChannel implements Parcelable {
* @hide
*/
@SystemApi
- @TestApi
public static final int USER_LOCKED_SOUND = 0x00000020;
/**
@@ -391,7 +390,6 @@ public final class NotificationChannel implements Parcelable {
* @hide
*/
@SystemApi
- @TestApi
public void setBlockable(boolean blockable) {
mBlockableSystem = blockable;
}
@@ -1146,7 +1144,7 @@ public final class NotificationChannel implements Parcelable {
}
private static String longArrayToString(long[] values) {
- StringBuffer sb = new StringBuffer();
+ StringBuilder sb = new StringBuilder();
if (values != null && values.length > 0) {
for (int i = 0; i < values.length - 1; i++) {
sb.append(values[i]).append(DELIMITER);
diff --git a/core/java/android/app/NotificationManager.java b/core/java/android/app/NotificationManager.java
index aefaf781eb35..f3bd04cd132e 100644
--- a/core/java/android/app/NotificationManager.java
+++ b/core/java/android/app/NotificationManager.java
@@ -1430,7 +1430,6 @@ public class NotificationManager {
* @hide
*/
@SystemApi
- @TestApi
public boolean isNotificationAssistantAccessGranted(@NonNull ComponentName assistant) {
INotificationManager service = getService();
try {
@@ -1466,7 +1465,6 @@ public class NotificationManager {
* @hide
*/
@SystemApi
- @TestApi
public @NonNull @Adjustment.Keys List<String> getAllowedAssistantAdjustments() {
INotificationManager service = getService();
try {
@@ -1577,7 +1575,6 @@ public class NotificationManager {
* @hide
*/
@SystemApi
- @TestApi
@RequiresPermission(android.Manifest.permission.MANAGE_NOTIFICATION_LISTENERS)
public void setNotificationListenerAccessGranted(
@NonNull ComponentName listener, boolean granted) {
@@ -1611,7 +1608,6 @@ public class NotificationManager {
* @hide
*/
@SystemApi
- @TestApi
public void setNotificationAssistantAccessGranted(@Nullable ComponentName assistant,
boolean granted) {
INotificationManager service = getService();
@@ -1631,7 +1627,6 @@ public class NotificationManager {
* @hide
*/
@SystemApi
- @TestApi
@RequiresPermission(android.Manifest.permission.MANAGE_NOTIFICATION_LISTENERS)
public @NonNull List<ComponentName> getEnabledNotificationListeners() {
return getEnabledNotificationListeners(mContext.getUserId());
@@ -1649,7 +1644,6 @@ public class NotificationManager {
/** @hide */
@SystemApi
- @TestApi
public @Nullable ComponentName getAllowedNotificationAssistant() {
INotificationManager service = getService();
try {
diff --git a/core/java/android/app/RuntimeAppOpAccessMessage.java b/core/java/android/app/RuntimeAppOpAccessMessage.java
index a19f815c4298..db3ba4a8cc3f 100644
--- a/core/java/android/app/RuntimeAppOpAccessMessage.java
+++ b/core/java/android/app/RuntimeAppOpAccessMessage.java
@@ -20,7 +20,6 @@ import android.annotation.IntRange;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.SystemApi;
-import android.annotation.TestApi;
import android.os.Parcel;
import android.os.Parcelable;
@@ -32,7 +31,6 @@ import com.android.internal.util.DataClass;
* @hide
*/
@Immutable
-@TestApi
@SystemApi
/*@DataClass(genConstructor = false)
@DataClass.Suppress("getOpCode")*/
diff --git a/core/java/android/app/StatusBarManager.java b/core/java/android/app/StatusBarManager.java
index 99d21272236d..864db2722d53 100644
--- a/core/java/android/app/StatusBarManager.java
+++ b/core/java/android/app/StatusBarManager.java
@@ -374,7 +374,6 @@ public class StatusBarManager {
* @hide
*/
@SystemApi
- @TestApi
@RequiresPermission(android.Manifest.permission.STATUS_BAR)
public void setDisabledForSetup(boolean disabled) {
try {
@@ -423,7 +422,6 @@ public class StatusBarManager {
* @hide
*/
@SystemApi
- @TestApi
@RequiresPermission(android.Manifest.permission.STATUS_BAR)
@NonNull
public DisableInfo getDisableInfo() {
@@ -456,7 +454,6 @@ public class StatusBarManager {
* @hide
*/
@SystemApi
- @TestApi
public static final class DisableInfo {
private boolean mStatusBarExpansion;
@@ -489,7 +486,6 @@ public class StatusBarManager {
* @hide
*/
@SystemApi
- @TestApi
public boolean isStatusBarExpansionDisabled() {
return mStatusBarExpansion;
}
@@ -505,7 +501,6 @@ public class StatusBarManager {
* @hide
*/
@SystemApi
- @TestApi
public boolean isNavigateToHomeDisabled() {
return mNavigateHome;
}
@@ -521,7 +516,6 @@ public class StatusBarManager {
* @hide
*/
@SystemApi
- @TestApi
public boolean isNotificationPeekingDisabled() {
return mNotificationPeeking;
}
@@ -537,7 +531,6 @@ public class StatusBarManager {
* @hide
*/
@SystemApi
- @TestApi
public boolean isRecentsDisabled() {
return mRecents;
}
@@ -553,7 +546,6 @@ public class StatusBarManager {
* @hide
*/
@SystemApi
- @TestApi
public boolean isSearchDisabled() {
return mSearch;
}
@@ -611,7 +603,6 @@ public class StatusBarManager {
* @hide
*/
@SystemApi
- @TestApi
public boolean areAllComponentsEnabled() {
return !mStatusBarExpansion && !mNavigateHome && !mNotificationPeeking && !mRecents
&& !mSearch && !mSystemIcons && !mClock && !mNotificationIcons;
diff --git a/core/java/android/app/SystemServiceRegistry.java b/core/java/android/app/SystemServiceRegistry.java
index b020c7044a00..4b3bebe36c29 100644
--- a/core/java/android/app/SystemServiceRegistry.java
+++ b/core/java/android/app/SystemServiceRegistry.java
@@ -1377,8 +1377,8 @@ public final class SystemServiceRegistry {
/** Throws {@link IllegalStateException} if not during a static initialization. */
private static void ensureInitializing(String methodName) {
- Preconditions.checkState(sInitializing, "Internal error: " + methodName
- + " can only be called during class initialization.");
+ Preconditions.checkState(sInitializing, "Internal error: %s"
+ + " can only be called during class initialization.", methodName);
}
/**
* Creates an array which is used to cache per-Context service instances.
diff --git a/core/java/android/app/TaskStackListener.java b/core/java/android/app/TaskStackListener.java
index 17e5e09d76b1..e77d7ac6a4ad 100644
--- a/core/java/android/app/TaskStackListener.java
+++ b/core/java/android/app/TaskStackListener.java
@@ -173,14 +173,6 @@ public abstract class TaskStackListener extends ITaskStackListener.Stub {
}
@Override
- public void onSingleTaskDisplayDrawn(int displayId) throws RemoteException {
- }
-
- @Override
- public void onSingleTaskDisplayEmpty(int displayId) throws RemoteException {
- }
-
- @Override
public void onTaskDisplayChanged(int taskId, int newDisplayId) throws RemoteException {
}
diff --git a/core/java/android/app/UiModeManager.java b/core/java/android/app/UiModeManager.java
index 06d1b74abc86..e2fc5dbf10e2 100644
--- a/core/java/android/app/UiModeManager.java
+++ b/core/java/android/app/UiModeManager.java
@@ -314,7 +314,6 @@ public class UiModeManager {
* @hide
*/
@SystemApi
- @TestApi
@RequiresPermission(android.Manifest.permission.ENTER_CAR_MODE_PRIORITIZED)
public void enableCarMode(@IntRange(from = 0) int priority, @EnableCarMode int flags) {
if (mService != null) {
diff --git a/core/java/android/app/WallpaperManager.java b/core/java/android/app/WallpaperManager.java
index 0a80ccc13487..54f3209e17be 100644
--- a/core/java/android/app/WallpaperManager.java
+++ b/core/java/android/app/WallpaperManager.java
@@ -1766,7 +1766,6 @@ public class WallpaperManager {
*
* @hide
*/
- @TestApi
@SystemApi
@RequiresPermission(android.Manifest.permission.SET_WALLPAPER_COMPONENT)
public boolean setWallpaperComponent(ComponentName name) {
diff --git a/core/java/android/app/admin/DevicePolicyManager.java b/core/java/android/app/admin/DevicePolicyManager.java
index b74e18b099ce..054e8429ff86 100644
--- a/core/java/android/app/admin/DevicePolicyManager.java
+++ b/core/java/android/app/admin/DevicePolicyManager.java
@@ -1465,7 +1465,7 @@ public class DevicePolicyManager {
* @see #createAdminSupportIntent(String)
* @hide
*/
- @TestApi @SystemApi
+ @SystemApi
public static final String EXTRA_RESTRICTION = "android.app.extra.RESTRICTION";
/**
@@ -1830,6 +1830,15 @@ public class DevicePolicyManager {
public static final int STATE_USER_PROFILE_COMPLETE = 4;
/**
+ * Management setup on a managed profile.
+ * <p>This is used as an intermediate state after {@link #STATE_USER_PROFILE_COMPLETE} once the
+ * work profile has been created.
+ * @hide
+ */
+ @SystemApi
+ public static final int STATE_USER_PROFILE_FINALIZED = 5;
+
+ /**
* @hide
*/
@IntDef(prefix = { "STATE_USER_" }, value = {
@@ -1837,7 +1846,8 @@ public class DevicePolicyManager {
STATE_USER_SETUP_INCOMPLETE,
STATE_USER_SETUP_COMPLETE,
STATE_USER_SETUP_FINALIZED,
- STATE_USER_PROFILE_COMPLETE
+ STATE_USER_PROFILE_COMPLETE,
+ STATE_USER_PROFILE_FINALIZED
})
@Retention(RetentionPolicy.SOURCE)
public @interface UserProvisioningState {}
@@ -2688,13 +2698,11 @@ public class DevicePolicyManager {
* </ul>
*/
@SystemApi
- @TestApi
public static final String ACCOUNT_FEATURE_DEVICE_OR_PROFILE_OWNER_ALLOWED =
"android.account.DEVICE_OR_PROFILE_OWNER_ALLOWED";
/** @hide See {@link #ACCOUNT_FEATURE_DEVICE_OR_PROFILE_OWNER_ALLOWED} */
@SystemApi
- @TestApi
public static final String ACCOUNT_FEATURE_DEVICE_OR_PROFILE_OWNER_DISALLOWED =
"android.account.DEVICE_OR_PROFILE_OWNER_DISALLOWED";
@@ -6671,7 +6679,6 @@ public class DevicePolicyManager {
* @hide
*/
@SystemApi
- @TestApi
@SuppressLint("Doclava125")
public boolean isDeviceManaged() {
try {
@@ -10381,7 +10388,6 @@ public class DevicePolicyManager {
* @hide
*/
@SystemApi
- @TestApi
@SuppressLint("Doclava125")
public @Nullable CharSequence getDeviceOwnerOrganizationName() {
try {
diff --git a/core/java/android/app/assist/AssistStructure.java b/core/java/android/app/assist/AssistStructure.java
index b5234f8e2e17..c15504cc0843 100644
--- a/core/java/android/app/assist/AssistStructure.java
+++ b/core/java/android/app/assist/AssistStructure.java
@@ -3,7 +3,6 @@ package android.app.assist;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.SystemApi;
-import android.annotation.TestApi;
import android.app.Activity;
import android.content.ComponentName;
import android.content.Context;
@@ -722,7 +721,6 @@ public class AssistStructure implements Parcelable {
// COntent Capture.
/** @hide */
@SystemApi
- @TestApi
public ViewNode() {
}
diff --git a/core/java/android/app/backup/BackupManager.java b/core/java/android/app/backup/BackupManager.java
index 9b67587c4dcd..05313592faa5 100644
--- a/core/java/android/app/backup/BackupManager.java
+++ b/core/java/android/app/backup/BackupManager.java
@@ -21,7 +21,6 @@ import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.RequiresPermission;
import android.annotation.SystemApi;
-import android.annotation.TestApi;
import android.compat.annotation.UnsupportedAppUsage;
import android.content.ComponentName;
import android.content.Context;
@@ -919,7 +918,6 @@ public class BackupManager {
* @hide
*/
@SystemApi
- @TestApi
@RequiresPermission(android.Manifest.permission.BACKUP)
public Intent getConfigurationIntent(String transportName) {
checkServiceBinder();
@@ -941,7 +939,6 @@ public class BackupManager {
* @hide
*/
@SystemApi
- @TestApi
@RequiresPermission(android.Manifest.permission.BACKUP)
public String getDestinationString(String transportName) {
checkServiceBinder();
@@ -963,7 +960,6 @@ public class BackupManager {
* @hide
*/
@SystemApi
- @TestApi
@RequiresPermission(android.Manifest.permission.BACKUP)
public Intent getDataManagementIntent(String transportName) {
checkServiceBinder();
@@ -989,7 +985,6 @@ public class BackupManager {
*/
@Deprecated
@SystemApi
- @TestApi
@RequiresPermission(android.Manifest.permission.BACKUP)
@Nullable
public String getDataManagementLabel(@NonNull String transportName) {
@@ -1006,7 +1001,6 @@ public class BackupManager {
* @hide
*/
@SystemApi
- @TestApi
@RequiresPermission(android.Manifest.permission.BACKUP)
@Nullable
public CharSequence getDataManagementIntentLabel(@NonNull String transportName) {
diff --git a/core/java/android/app/prediction/AppPredictionContext.java b/core/java/android/app/prediction/AppPredictionContext.java
index d14238bb2672..99fa869cee93 100644
--- a/core/java/android/app/prediction/AppPredictionContext.java
+++ b/core/java/android/app/prediction/AppPredictionContext.java
@@ -19,7 +19,6 @@ import android.annotation.IntRange;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.SystemApi;
-import android.annotation.TestApi;
import android.content.Context;
import android.os.Bundle;
import android.os.Parcel;
@@ -32,7 +31,6 @@ import android.os.Parcelable;
* @hide
*/
@SystemApi
-@TestApi
public final class AppPredictionContext implements Parcelable {
private final int mPredictedTargetCount;
@@ -129,7 +127,6 @@ public final class AppPredictionContext implements Parcelable {
* @hide
*/
@SystemApi
- @TestApi
public static final class Builder {
@NonNull
@@ -147,7 +144,6 @@ public final class AppPredictionContext implements Parcelable {
* @hide
*/
@SystemApi
- @TestApi
public Builder(@NonNull Context context) {
mPackageName = context.getPackageName();
}
diff --git a/core/java/android/app/prediction/AppPredictionManager.java b/core/java/android/app/prediction/AppPredictionManager.java
index ca22721622b7..5da7aa97ea0f 100644
--- a/core/java/android/app/prediction/AppPredictionManager.java
+++ b/core/java/android/app/prediction/AppPredictionManager.java
@@ -17,7 +17,6 @@ package android.app.prediction;
import android.annotation.NonNull;
import android.annotation.SystemApi;
-import android.annotation.TestApi;
import android.content.Context;
import java.util.Objects;
@@ -28,7 +27,6 @@ import java.util.Objects;
* @hide
*/
@SystemApi
-@TestApi
public final class AppPredictionManager {
private final Context mContext;
diff --git a/core/java/android/app/prediction/AppPredictionSessionId.java b/core/java/android/app/prediction/AppPredictionSessionId.java
index 876bafdfb7d1..6277a7de258f 100644
--- a/core/java/android/app/prediction/AppPredictionSessionId.java
+++ b/core/java/android/app/prediction/AppPredictionSessionId.java
@@ -18,7 +18,6 @@ package android.app.prediction;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.SystemApi;
-import android.annotation.TestApi;
import android.os.Parcel;
import android.os.Parcelable;
@@ -30,7 +29,6 @@ import java.util.Objects;
* @hide
*/
@SystemApi
-@TestApi
public final class AppPredictionSessionId implements Parcelable {
private final String mId;
diff --git a/core/java/android/app/prediction/AppPredictor.java b/core/java/android/app/prediction/AppPredictor.java
index fa135b10ae1f..fd1b9e3bede2 100644
--- a/core/java/android/app/prediction/AppPredictor.java
+++ b/core/java/android/app/prediction/AppPredictor.java
@@ -70,7 +70,6 @@ import java.util.function.Consumer;
* @hide
*/
@SystemApi
-@TestApi
public final class AppPredictor {
private static final String TAG = AppPredictor.class.getSimpleName();
diff --git a/core/java/android/app/prediction/AppTarget.java b/core/java/android/app/prediction/AppTarget.java
index 14e32b8397a8..fef9e7020097 100644
--- a/core/java/android/app/prediction/AppTarget.java
+++ b/core/java/android/app/prediction/AppTarget.java
@@ -19,7 +19,6 @@ import android.annotation.IntRange;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.SystemApi;
-import android.annotation.TestApi;
import android.content.pm.ShortcutInfo;
import android.os.Parcel;
import android.os.Parcelable;
@@ -33,7 +32,6 @@ import java.util.Objects;
* @hide
*/
@SystemApi
-@TestApi
public final class AppTarget implements Parcelable {
private final AppTargetId mId;
@@ -190,7 +188,6 @@ public final class AppTarget implements Parcelable {
* @hide
*/
@SystemApi
- @TestApi
public static final class Builder {
@NonNull
@@ -221,7 +218,6 @@ public final class AppTarget implements Parcelable {
* @hide
*/
@SystemApi
- @TestApi
public Builder(@NonNull AppTargetId id, @NonNull String packageName,
@NonNull UserHandle user) {
mId = Objects.requireNonNull(id);
@@ -235,7 +231,6 @@ public final class AppTarget implements Parcelable {
* @hide
*/
@SystemApi
- @TestApi
public Builder(@NonNull AppTargetId id, @NonNull ShortcutInfo info) {
mId = Objects.requireNonNull(id);
mShortcutInfo = Objects.requireNonNull(info);
diff --git a/core/java/android/app/prediction/AppTargetEvent.java b/core/java/android/app/prediction/AppTargetEvent.java
index f519145c4aa8..963e750e4fd1 100644
--- a/core/java/android/app/prediction/AppTargetEvent.java
+++ b/core/java/android/app/prediction/AppTargetEvent.java
@@ -19,7 +19,6 @@ import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.SystemApi;
-import android.annotation.TestApi;
import android.os.Parcel;
import android.os.Parcelable;
@@ -32,7 +31,6 @@ import java.lang.annotation.RetentionPolicy;
* @hide
*/
@SystemApi
-@TestApi
public final class AppTargetEvent implements Parcelable {
/**
@@ -141,7 +139,6 @@ public final class AppTargetEvent implements Parcelable {
* @hide
*/
@SystemApi
- @TestApi
public static final class Builder {
private AppTarget mTarget;
private String mLocation;
diff --git a/core/java/android/app/prediction/AppTargetId.java b/core/java/android/app/prediction/AppTargetId.java
index 052fdc11ef21..048e12c5c48e 100644
--- a/core/java/android/app/prediction/AppTargetId.java
+++ b/core/java/android/app/prediction/AppTargetId.java
@@ -18,7 +18,6 @@ package android.app.prediction;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.SystemApi;
-import android.annotation.TestApi;
import android.os.Parcel;
import android.os.Parcelable;
@@ -28,7 +27,6 @@ import android.os.Parcelable;
* @hide
*/
@SystemApi
-@TestApi
public final class AppTargetId implements Parcelable {
@NonNull
@@ -40,7 +38,6 @@ public final class AppTargetId implements Parcelable {
* @hide
*/
@SystemApi
- @TestApi
public AppTargetId(@NonNull String id) {
mId = id;
}
diff --git a/core/java/android/app/role/OnRoleHoldersChangedListener.java b/core/java/android/app/role/OnRoleHoldersChangedListener.java
index d6f76794da20..5958debc86dd 100644
--- a/core/java/android/app/role/OnRoleHoldersChangedListener.java
+++ b/core/java/android/app/role/OnRoleHoldersChangedListener.java
@@ -18,7 +18,6 @@ package android.app.role;
import android.annotation.NonNull;
import android.annotation.SystemApi;
-import android.annotation.TestApi;
import android.os.UserHandle;
/**
@@ -27,7 +26,6 @@ import android.os.UserHandle;
* @hide
*/
@SystemApi
-@TestApi
public interface OnRoleHoldersChangedListener {
/**
diff --git a/core/java/android/app/role/RoleManager.java b/core/java/android/app/role/RoleManager.java
index 82159235ae28..408ce0f2ab1a 100644
--- a/core/java/android/app/role/RoleManager.java
+++ b/core/java/android/app/role/RoleManager.java
@@ -144,7 +144,6 @@ public final class RoleManager {
* @hide
*/
@SystemApi
- @TestApi
public static final int MANAGE_HOLDERS_FLAG_DONT_KILL_APP = 1;
/**
@@ -255,7 +254,6 @@ public final class RoleManager {
@NonNull
@RequiresPermission(Manifest.permission.MANAGE_ROLE_HOLDERS)
@SystemApi
- @TestApi
public List<String> getRoleHolders(@NonNull String roleName) {
return getRoleHoldersAsUser(roleName, Process.myUserHandle());
}
@@ -281,7 +279,6 @@ public final class RoleManager {
@NonNull
@RequiresPermission(Manifest.permission.MANAGE_ROLE_HOLDERS)
@SystemApi
- @TestApi
public List<String> getRoleHoldersAsUser(@NonNull String roleName, @NonNull UserHandle user) {
Preconditions.checkStringNotEmpty(roleName, "roleName cannot be null or empty");
Objects.requireNonNull(user, "user cannot be null");
@@ -315,7 +312,6 @@ public final class RoleManager {
*/
@RequiresPermission(Manifest.permission.MANAGE_ROLE_HOLDERS)
@SystemApi
- @TestApi
public void addRoleHolderAsUser(@NonNull String roleName, @NonNull String packageName,
@ManageHoldersFlags int flags, @NonNull UserHandle user,
@CallbackExecutor @NonNull Executor executor, @NonNull Consumer<Boolean> callback) {
@@ -354,7 +350,6 @@ public final class RoleManager {
*/
@RequiresPermission(Manifest.permission.MANAGE_ROLE_HOLDERS)
@SystemApi
- @TestApi
public void removeRoleHolderAsUser(@NonNull String roleName, @NonNull String packageName,
@ManageHoldersFlags int flags, @NonNull UserHandle user,
@CallbackExecutor @NonNull Executor executor, @NonNull Consumer<Boolean> callback) {
@@ -392,7 +387,6 @@ public final class RoleManager {
*/
@RequiresPermission(Manifest.permission.MANAGE_ROLE_HOLDERS)
@SystemApi
- @TestApi
public void clearRoleHoldersAsUser(@NonNull String roleName, @ManageHoldersFlags int flags,
@NonNull UserHandle user, @CallbackExecutor @NonNull Executor executor,
@NonNull Consumer<Boolean> callback) {
@@ -439,7 +433,6 @@ public final class RoleManager {
*/
@RequiresPermission(Manifest.permission.OBSERVE_ROLE_HOLDERS)
@SystemApi
- @TestApi
public void addOnRoleHoldersChangedListenerAsUser(@CallbackExecutor @NonNull Executor executor,
@NonNull OnRoleHoldersChangedListener listener, @NonNull UserHandle user) {
Objects.requireNonNull(executor, "executor cannot be null");
@@ -485,7 +478,6 @@ public final class RoleManager {
*/
@RequiresPermission(Manifest.permission.OBSERVE_ROLE_HOLDERS)
@SystemApi
- @TestApi
public void removeOnRoleHoldersChangedListenerAsUser(
@NonNull OnRoleHoldersChangedListener listener, @NonNull UserHandle user) {
Objects.requireNonNull(listener, "listener cannot be null");
@@ -527,7 +519,6 @@ public final class RoleManager {
*/
@RequiresPermission(PERMISSION_MANAGE_ROLES_FROM_CONTROLLER)
@SystemApi
- @TestApi
public void setRoleNamesFromController(@NonNull List<String> roleNames) {
Objects.requireNonNull(roleNames, "roleNames cannot be null");
try {
@@ -558,7 +549,6 @@ public final class RoleManager {
*/
@RequiresPermission(PERMISSION_MANAGE_ROLES_FROM_CONTROLLER)
@SystemApi
- @TestApi
public boolean addRoleHolderFromController(@NonNull String roleName,
@NonNull String packageName) {
Preconditions.checkStringNotEmpty(roleName, "roleName cannot be null or empty");
@@ -591,7 +581,6 @@ public final class RoleManager {
*/
@RequiresPermission(PERMISSION_MANAGE_ROLES_FROM_CONTROLLER)
@SystemApi
- @TestApi
public boolean removeRoleHolderFromController(@NonNull String roleName,
@NonNull String packageName) {
Preconditions.checkStringNotEmpty(roleName, "roleName cannot be null or empty");
@@ -614,7 +603,6 @@ public final class RoleManager {
@NonNull
@RequiresPermission(PERMISSION_MANAGE_ROLES_FROM_CONTROLLER)
@SystemApi
- @TestApi
public List<String> getHeldRolesFromController(@NonNull String packageName) {
Preconditions.checkStringNotEmpty(packageName, "packageName cannot be null or empty");
try {
diff --git a/core/java/android/app/servertransaction/ClientTransaction.java b/core/java/android/app/servertransaction/ClientTransaction.java
index 90890d58aaff..fbb37db52014 100644
--- a/core/java/android/app/servertransaction/ClientTransaction.java
+++ b/core/java/android/app/servertransaction/ClientTransaction.java
@@ -241,6 +241,8 @@ public class ClientTransaction implements Parcelable, ObjectPoolItem {
int result = 17;
result = 31 * result + Objects.hashCode(mActivityCallbacks);
result = 31 * result + Objects.hashCode(mLifecycleStateRequest);
+ result = 31 * result + Objects.hashCode(mClient);
+ result = 31 * result + Objects.hashCode(mActivityToken);
return result;
}
diff --git a/core/java/android/app/slice/SliceProvider.java b/core/java/android/app/slice/SliceProvider.java
index cef6ab094177..0589f4a3b2bb 100644
--- a/core/java/android/app/slice/SliceProvider.java
+++ b/core/java/android/app/slice/SliceProvider.java
@@ -519,7 +519,7 @@ public abstract class SliceProvider extends ContentProvider {
intent.setData(sliceUri.buildUpon().appendQueryParameter("package", callingPackage)
.build());
- return PendingIntent.getActivity(context, 0, intent, 0);
+ return PendingIntent.getActivity(context, 0, intent, PendingIntent.FLAG_IMMUTABLE);
}
/**
diff --git a/core/java/android/app/usage/CacheQuotaHint.java b/core/java/android/app/usage/CacheQuotaHint.java
index d5c72f286a32..0ccb058d11cf 100644
--- a/core/java/android/app/usage/CacheQuotaHint.java
+++ b/core/java/android/app/usage/CacheQuotaHint.java
@@ -19,7 +19,6 @@ package android.app.usage;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.SystemApi;
-import android.annotation.TestApi;
import android.os.Parcel;
import android.os.Parcelable;
@@ -33,7 +32,6 @@ import java.util.Objects;
* allows apps to understand how much cache to use.
* {@hide}
*/
-@TestApi
@SystemApi
public final class CacheQuotaHint implements Parcelable {
public static final long QUOTA_NOT_SET = -1;
diff --git a/core/java/android/bluetooth/BluetoothHeadset.java b/core/java/android/bluetooth/BluetoothHeadset.java
index 6ce05f984cca..e6d6e7ac5dda 100644
--- a/core/java/android/bluetooth/BluetoothHeadset.java
+++ b/core/java/android/bluetooth/BluetoothHeadset.java
@@ -79,7 +79,7 @@ public final class BluetoothHeadset implements BluetoothProfile {
/**
* Intent used to broadcast the change in the Audio Connection state of the
- * A2DP profile.
+ * HDP profile.
*
* <p>This intent will have 3 extras:
* <ul>
diff --git a/core/java/android/companion/CompanionDeviceManager.java b/core/java/android/companion/CompanionDeviceManager.java
index e94556b8d97b..c3c270e52eb6 100644
--- a/core/java/android/companion/CompanionDeviceManager.java
+++ b/core/java/android/companion/CompanionDeviceManager.java
@@ -21,7 +21,6 @@ import android.annotation.Nullable;
import android.annotation.RequiresPermission;
import android.annotation.SystemApi;
import android.annotation.SystemService;
-import android.annotation.TestApi;
import android.app.Activity;
import android.app.Application;
import android.app.PendingIntent;
@@ -285,7 +284,6 @@ public final class CompanionDeviceManager {
* @hide
*/
@SystemApi
- @TestApi
@RequiresPermission(android.Manifest.permission.MANAGE_COMPANION_DEVICES)
public boolean isDeviceAssociatedForWifiConnection(
@NonNull String packageName,
diff --git a/core/java/android/companion/ICompanionDeviceDiscoveryService.aidl b/core/java/android/companion/ICompanionDeviceDiscoveryService.aidl
index 5e3d46caae91..a630873c7f67 100644
--- a/core/java/android/companion/ICompanionDeviceDiscoveryService.aidl
+++ b/core/java/android/companion/ICompanionDeviceDiscoveryService.aidl
@@ -23,7 +23,7 @@ import com.android.internal.infra.AndroidFuture;
/** @hide */
-interface ICompanionDeviceDiscoveryService {
+oneway interface ICompanionDeviceDiscoveryService {
void startDiscovery(
in AssociationRequest request,
in String callingPackage,
diff --git a/core/java/android/content/ApexEnvironment.java b/core/java/android/content/ApexEnvironment.java
index 9f15a425d92b..b4cc3c2bb156 100644
--- a/core/java/android/content/ApexEnvironment.java
+++ b/core/java/android/content/ApexEnvironment.java
@@ -18,7 +18,6 @@ package android.content;
import android.annotation.NonNull;
import android.annotation.SystemApi;
-import android.annotation.TestApi;
import android.os.Environment;
import android.os.UserHandle;
@@ -31,7 +30,6 @@ import java.util.Objects;
* @hide
*/
@SystemApi
-@TestApi
public class ApexEnvironment {
private static final String APEX_DATA = "apexdata";
diff --git a/core/java/android/content/ContentProviderClient.java b/core/java/android/content/ContentProviderClient.java
index d0f5ec467458..5af7861e1a20 100644
--- a/core/java/android/content/ContentProviderClient.java
+++ b/core/java/android/content/ContentProviderClient.java
@@ -21,7 +21,6 @@ import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.RequiresPermission;
import android.annotation.SystemApi;
-import android.annotation.TestApi;
import android.compat.annotation.UnsupportedAppUsage;
import android.content.res.AssetFileDescriptor;
import android.database.CrossProcessCursorWrapper;
@@ -123,7 +122,6 @@ public class ContentProviderClient implements ContentInterface, AutoCloseable {
* @hide
*/
@SystemApi
- @TestApi
@RequiresPermission(android.Manifest.permission.REMOVE_TASKS)
public void setDetectNotResponding(@DurationMillisLong long timeoutMillis) {
synchronized (ContentProviderClient.class) {
diff --git a/core/java/android/content/ContentProviderOperation.java b/core/java/android/content/ContentProviderOperation.java
index 1fb426eb3cfc..30775b19ab00 100644
--- a/core/java/android/content/ContentProviderOperation.java
+++ b/core/java/android/content/ContentProviderOperation.java
@@ -533,21 +533,21 @@ public class ContentProviderOperation implements Parcelable {
@Override
public String toString() {
final StringBuilder sb = new StringBuilder("ContentProviderOperation(");
- sb.append("type=" + typeToString(mType) + " ");
+ sb.append("type=").append(typeToString(mType)).append(' ');
if (mUri != null) {
- sb.append("uri=" + mUri + " ");
+ sb.append("uri=").append(mUri).append(' ');
}
if (mValues != null) {
- sb.append("values=" + mValues + " ");
+ sb.append("values=").append(mValues).append(' ');
}
if (mSelection != null) {
- sb.append("selection=" + mSelection + " ");
+ sb.append("selection=").append(mSelection).append(' ');
}
if (mSelectionArgs != null) {
- sb.append("selectionArgs=" + mSelectionArgs + " ");
+ sb.append("selectionArgs=").append(mSelectionArgs).append(' ');
}
if (mExpectedCount != null) {
- sb.append("expectedCount=" + mExpectedCount + " ");
+ sb.append("expectedCount=").append(mExpectedCount).append(' ');
}
if (mYieldAllowed) {
sb.append("yieldAllowed ");
diff --git a/core/java/android/content/ContentProviderResult.java b/core/java/android/content/ContentProviderResult.java
index 4fb1ddb958d5..fdfe7eb33530 100644
--- a/core/java/android/content/ContentProviderResult.java
+++ b/core/java/android/content/ContentProviderResult.java
@@ -143,16 +143,16 @@ public class ContentProviderResult implements Parcelable {
public String toString() {
final StringBuilder sb = new StringBuilder("ContentProviderResult(");
if (uri != null) {
- sb.append("uri=" + uri + " ");
+ sb.append("uri=").append(uri).append(' ');
}
if (count != null) {
- sb.append("count=" + count + " ");
+ sb.append("count=").append(count).append(' ');
}
if (extras != null) {
- sb.append("extras=" + extras + " ");
+ sb.append("extras=").append(extras).append(' ');
}
if (exception != null) {
- sb.append("exception=" + exception + " ");
+ sb.append("exception=").append(exception).append(' ');
}
sb.deleteCharAt(sb.length() - 1);
sb.append(")");
diff --git a/core/java/android/content/ContentResolver.java b/core/java/android/content/ContentResolver.java
index c39f176ac0d1..fd7074c29891 100644
--- a/core/java/android/content/ContentResolver.java
+++ b/core/java/android/content/ContentResolver.java
@@ -4098,7 +4098,6 @@ public abstract class ContentResolver implements ContentInterface {
* @hide
*/
@SystemApi
- @TestApi
// We can't accept an already-opened FD here, since these methods are
// rewriting actual filesystem paths
@SuppressLint("StreamFiles")
@@ -4118,7 +4117,6 @@ public abstract class ContentResolver implements ContentInterface {
* @hide
*/
@SystemApi
- @TestApi
// We can't accept an already-opened FD here, since these methods are
// rewriting actual filesystem paths
@SuppressLint("StreamFiles")
diff --git a/core/java/android/content/Context.java b/core/java/android/content/Context.java
index c4157cfe09ad..42fe0e1c465d 100644
--- a/core/java/android/content/Context.java
+++ b/core/java/android/content/Context.java
@@ -382,6 +382,7 @@ public abstract class Context {
* {@link android.Manifest.permission#START_ACTIVITIES_FROM_BACKGROUND}.
* @hide
*/
+ @SystemApi
public static final int BIND_ALLOW_BACKGROUND_ACTIVITY_STARTS = 0x00100000;
/**
@@ -1848,7 +1849,6 @@ public abstract class Context {
*/
@RequiresPermission(android.Manifest.permission.INTERACT_ACROSS_USERS)
@SystemApi
- @TestApi
public void startActivityAsUser(@RequiresPermission @NonNull Intent intent,
@NonNull UserHandle user) {
throw new RuntimeException("Not implemented. Must override in a subclass.");
@@ -3981,7 +3981,6 @@ public abstract class Context {
* @hide
*/
@SystemApi
- @TestApi
@SuppressLint("ServiceName")
public static final String STATUS_BAR_SERVICE = "statusbar";
@@ -4193,7 +4192,6 @@ public abstract class Context {
* @hide
*/
@SystemApi
- @TestApi
public static final String ETHERNET_SERVICE = "ethernet";
/**
@@ -4516,7 +4514,6 @@ public abstract class Context {
* @see #getSystemService(String)
* @hide
*/
- @TestApi
@SystemApi
public static final String PERMISSION_SERVICE = "permission";
@@ -4547,7 +4544,7 @@ public abstract class Context {
* @see #getSystemService(String)
* @hide
*/
- @SystemApi @TestApi
+ @SystemApi
public static final String ROLLBACK_SERVICE = "rollback";
/**
@@ -5021,7 +5018,7 @@ public abstract class Context {
* @see android.os.BugreportManager
* @hide
*/
- @SystemApi @TestApi
+ @SystemApi
public static final String BUGREPORT_SERVICE = "bugreport";
/**
@@ -5183,7 +5180,6 @@ public abstract class Context {
* @hide
*/
@SystemApi
- @TestApi
public static final String APP_INTEGRITY_SERVICE = "app_integrity";
/**
@@ -5755,7 +5751,6 @@ public abstract class Context {
* @hide
*/
@SystemApi
- @TestApi
@NonNull
public Context createPackageContextAsUser(
@NonNull String packageName, @CreatePackageOptions int flags, @NonNull UserHandle user)
@@ -5774,7 +5769,6 @@ public abstract class Context {
* @hide
*/
@SystemApi
- @TestApi
@NonNull
public Context createContextAsUser(@NonNull UserHandle user, @CreatePackageOptions int flags) {
if (Build.IS_ENG) {
diff --git a/core/java/android/content/Intent.java b/core/java/android/content/Intent.java
index 5622ccab3c20..9216a0871870 100644
--- a/core/java/android/content/Intent.java
+++ b/core/java/android/content/Intent.java
@@ -28,7 +28,6 @@ import android.annotation.SdkConstant;
import android.annotation.SdkConstant.SdkConstantType;
import android.annotation.SuppressLint;
import android.annotation.SystemApi;
-import android.annotation.TestApi;
import android.app.AppGlobals;
import android.compat.annotation.UnsupportedAppUsage;
import android.content.pm.ActivityInfo;
@@ -620,7 +619,6 @@ import java.util.TimeZone;
* <li> {@link #EXTRA_PHONE_NUMBER}
* <li> {@link #EXTRA_REFERRER}
* <li> {@link #EXTRA_REMOTE_INTENT_TOKEN}
- * <li> {@link #EXTRA_REMOVED_BY_SYSTEM}
* <li> {@link #EXTRA_REPLACING}
* <li> {@link #EXTRA_SHORTCUT_ICON}
* <li> {@link #EXTRA_SHORTCUT_ICON_RESOURCE}
@@ -632,6 +630,7 @@ import java.util.TimeZone;
* <li> {@link #EXTRA_TEXT}
* <li> {@link #EXTRA_TITLE}
* <li> {@link #EXTRA_UID}
+ * <li> {@link #EXTRA_USER_INITIATED}
* </ul>
*
* <h3>Flags</h3>
@@ -1748,7 +1747,6 @@ public class Intent implements Parcelable, Cloneable {
* @hide
*/
@SystemApi
- @TestApi
public static final String EXTRA_ORIGINATING_UID
= "android.intent.extra.ORIGINATING_UID";
@@ -1979,7 +1977,6 @@ public class Intent implements Parcelable, Cloneable {
@RequiresPermission(android.Manifest.permission.MANAGE_ROLE_HOLDERS)
@SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
@SystemApi
- @TestApi
public static final String ACTION_MANAGE_DEFAULT_APP =
"android.intent.action.MANAGE_DEFAULT_APP";
@@ -1994,7 +1991,6 @@ public class Intent implements Parcelable, Cloneable {
* @hide
*/
@SystemApi
- @TestApi
public static final String EXTRA_ROLE_NAME = "android.intent.extra.ROLE_NAME";
/**
@@ -2465,8 +2461,8 @@ public class Intent implements Parcelable, Cloneable {
* application -- data and code -- is being removed.
* <li> {@link #EXTRA_REPLACING} is set to true if this will be followed
* by an {@link #ACTION_PACKAGE_ADDED} broadcast for the same package.
- * <li> {@link #EXTRA_REMOVED_BY_SYSTEM} containing boolean field to to signal that the
- * application was removed automatically without the user-initiated action.
+ * <li> {@link #EXTRA_USER_INITIATED} containing boolean field to signal that the application
+ * was removed with the user-initiated action.
* </ul>
*
* <p class="note">This is a protected intent that can only be sent
@@ -2541,7 +2537,7 @@ public class Intent implements Parcelable, Cloneable {
*
* @hide
*/
- @SystemApi @TestApi
+ @SystemApi
@SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
public static final String ACTION_ROLLBACK_COMMITTED =
"android.intent.action.ROLLBACK_COMMITTED";
@@ -2744,7 +2740,6 @@ public class Intent implements Parcelable, Cloneable {
* </ul>
*
* <p class="note">This is a protected intent that can only be sent by the system.
- * @hide
*/
@SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
public static final String ACTION_PACKAGE_STARTABLE = "android.intent.action.PACKAGE_STARTABLE";
@@ -2755,13 +2750,13 @@ public class Intent implements Parcelable, Cloneable {
* <ul>
* <li> {@link #EXTRA_UID} containing the integer uid assigned to the package. </li>
* <li> {@link #EXTRA_PACKAGE_NAME} containing the package name. </li>
- * <li> {@link #EXTRA_REASON} containing the integer indicating the reason for the state change,
+ * <li> {@link #EXTRA_UNSTARTABLE_REASON} containing the integer indicating the reason for
+ * the state change,
* @see PackageManager.UnstartableReason
* </li>
* </ul>
*
* <p class="note">This is a protected intent that can only be sent by the system.
- * @hide
*/
@SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
public static final String ACTION_PACKAGE_UNSTARTABLE =
@@ -2776,7 +2771,6 @@ public class Intent implements Parcelable, Cloneable {
* </ul>
*
* <p class="note">This is a protected intent that can only be sent by the system.
- * @hide
*/
@SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
public static final String ACTION_PACKAGE_FULLY_LOADED =
@@ -5561,11 +5555,9 @@ public class Intent implements Parcelable, Cloneable {
/**
* Used as a boolean extra field in {@link android.content.Intent#ACTION_PACKAGE_REMOVED}
- * intents to signal that the application was removed automatically without the user-initiated
- * action.
+ * intents to signal that the application was removed with the user-initiated action.
*/
- public static final String EXTRA_REMOVED_BY_SYSTEM =
- "android.intent.extra.REMOVED_BY_SYSTEM";
+ public static final String EXTRA_USER_INITIATED = "android.intent.extra.USER_INITIATED";
/**
* A String holding the phone number originally entered in
@@ -6015,6 +6007,13 @@ public class Intent implements Parcelable, Cloneable {
*/
public static final String EXTRA_LOCUS_ID = "android.intent.extra.LOCUS_ID";
+ /**
+ * Intent extra: the reason that the package associated with this intent has become unstartable.
+ *
+ * <p>Type: String
+ */
+ public static final String EXTRA_UNSTARTABLE_REASON = "android.intent.extra.UNSTARTABLE_REASON";
+
// ---------------------------------------------------------------------
// ---------------------------------------------------------------------
// Intent flags (see mFlags variable).
@@ -7446,6 +7445,7 @@ public class Intent implements Parcelable, Cloneable {
/** @hide */
@UnsupportedAppUsage
+ @SuppressWarnings("AndroidFrameworkEfficientCollections")
public static Intent parseCommandArgs(ShellCommand cmd, CommandOptionHandler optionHandler)
throws URISyntaxException {
Intent intent = new Intent();
diff --git a/core/java/android/content/SyncResult.java b/core/java/android/content/SyncResult.java
index 8280f8e637ba..7e68dcafd1b5 100644
--- a/core/java/android/content/SyncResult.java
+++ b/core/java/android/content/SyncResult.java
@@ -292,7 +292,7 @@ public final class SyncResult implements Parcelable {
* @return debugging string.
*/
public String toDebugString() {
- StringBuffer sb = new StringBuffer();
+ StringBuilder sb = new StringBuilder();
if (fullSyncRequested) {
sb.append("f1");
diff --git a/core/java/android/content/integrity/AppIntegrityManager.java b/core/java/android/content/integrity/AppIntegrityManager.java
index 4db4c7316433..1196064768e8 100644
--- a/core/java/android/content/integrity/AppIntegrityManager.java
+++ b/core/java/android/content/integrity/AppIntegrityManager.java
@@ -36,7 +36,6 @@ import java.util.List;
*
* @hide
*/
-@TestApi
@SystemApi
@SystemService(Context.APP_INTEGRITY_SERVICE)
public class AppIntegrityManager {
diff --git a/core/java/android/content/integrity/AtomicFormula.java b/core/java/android/content/integrity/AtomicFormula.java
index a64f39367e26..e3598004d277 100644
--- a/core/java/android/content/integrity/AtomicFormula.java
+++ b/core/java/android/content/integrity/AtomicFormula.java
@@ -129,7 +129,7 @@ public abstract class AtomicFormula extends IntegrityFormula {
private final @Key int mKey;
public AtomicFormula(@Key int key) {
- checkArgument(isValidKey(key), String.format("Unknown key: %d", key));
+ checkArgument(isValidKey(key), "Unknown key: %d", key);
mKey = key;
}
@@ -149,8 +149,7 @@ public abstract class AtomicFormula extends IntegrityFormula {
super(key);
checkArgument(
key == VERSION_CODE,
- String.format(
- "Key %s cannot be used with LongAtomicFormula", keyToString(key)));
+ "Key %s cannot be used with LongAtomicFormula", keyToString(key));
mValue = null;
mOperator = null;
}
@@ -168,10 +167,9 @@ public abstract class AtomicFormula extends IntegrityFormula {
super(key);
checkArgument(
key == VERSION_CODE,
- String.format(
- "Key %s cannot be used with LongAtomicFormula", keyToString(key)));
+ "Key %s cannot be used with LongAtomicFormula", keyToString(key));
checkArgument(
- isValidOperator(operator), String.format("Unknown operator: %d", operator));
+ isValidOperator(operator), "Unknown operator: %d", operator);
mOperator = operator;
mValue = value;
}
@@ -317,8 +315,7 @@ public abstract class AtomicFormula extends IntegrityFormula {
|| key == INSTALLER_CERTIFICATE
|| key == INSTALLER_NAME
|| key == STAMP_CERTIFICATE_HASH,
- String.format(
- "Key %s cannot be used with StringAtomicFormula", keyToString(key)));
+ "Key %s cannot be used with StringAtomicFormula", keyToString(key));
mValue = null;
mIsHashedValue = null;
}
@@ -339,8 +336,7 @@ public abstract class AtomicFormula extends IntegrityFormula {
|| key == INSTALLER_CERTIFICATE
|| key == INSTALLER_NAME
|| key == STAMP_CERTIFICATE_HASH,
- String.format(
- "Key %s cannot be used with StringAtomicFormula", keyToString(key)));
+ "Key %s cannot be used with StringAtomicFormula", keyToString(key));
mValue = value;
mIsHashedValue = isHashed;
}
@@ -365,8 +361,7 @@ public abstract class AtomicFormula extends IntegrityFormula {
|| key == INSTALLER_CERTIFICATE
|| key == INSTALLER_NAME
|| key == STAMP_CERTIFICATE_HASH,
- String.format(
- "Key %s cannot be used with StringAtomicFormula", keyToString(key)));
+ "Key %s cannot be used with StringAtomicFormula", keyToString(key));
mValue = hashValue(key, value);
mIsHashedValue =
(key == APP_CERTIFICATE
diff --git a/core/java/android/content/integrity/CompoundFormula.java b/core/java/android/content/integrity/CompoundFormula.java
index 160bec9a51b9..1ffabd03cc26 100644
--- a/core/java/android/content/integrity/CompoundFormula.java
+++ b/core/java/android/content/integrity/CompoundFormula.java
@@ -84,7 +84,7 @@ public final class CompoundFormula extends IntegrityFormula implements Parcelabl
*/
public CompoundFormula(@Connector int connector, List<IntegrityFormula> formulas) {
checkArgument(
- isValidConnector(connector), String.format("Unknown connector: %d", connector));
+ isValidConnector(connector), "Unknown connector: %d", connector);
validateFormulas(connector, formulas);
this.mConnector = connector;
this.mFormulas = Collections.unmodifiableList(formulas);
@@ -93,7 +93,7 @@ public final class CompoundFormula extends IntegrityFormula implements Parcelabl
CompoundFormula(Parcel in) {
mConnector = in.readInt();
int length = in.readInt();
- checkArgument(length >= 0, "Must have non-negative length. Got " + length);
+ checkArgument(length >= 0, "Must have non-negative length. Got %d", length);
mFormulas = new ArrayList<>(length);
for (int i = 0; i < length; i++) {
mFormulas.add(IntegrityFormula.readFromParcel(in));
@@ -196,16 +196,14 @@ public final class CompoundFormula extends IntegrityFormula implements Parcelabl
case OR:
checkArgument(
formulas.size() >= 2,
- String.format(
- "Connector %s must have at least 2 formulas",
- connectorToString(connector)));
+ "Connector %s must have at least 2 formulas",
+ connectorToString(connector));
break;
case NOT:
checkArgument(
formulas.size() == 1,
- String.format(
- "Connector %s must have 1 formula only",
- connectorToString(connector)));
+ "Connector %s must have 1 formula only",
+ connectorToString(connector));
break;
}
}
diff --git a/core/java/android/content/integrity/IntegrityFormula.java b/core/java/android/content/integrity/IntegrityFormula.java
index fc177721240c..d965ef5c71a8 100644
--- a/core/java/android/content/integrity/IntegrityFormula.java
+++ b/core/java/android/content/integrity/IntegrityFormula.java
@@ -19,7 +19,6 @@ package android.content.integrity;
import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.SystemApi;
-import android.annotation.TestApi;
import android.content.integrity.AtomicFormula.BooleanAtomicFormula;
import android.content.integrity.AtomicFormula.LongAtomicFormula;
import android.content.integrity.AtomicFormula.StringAtomicFormula;
@@ -38,7 +37,6 @@ import java.util.Arrays;
* @hide
*/
@SystemApi
-@TestApi
@VisibleForTesting
public abstract class IntegrityFormula {
diff --git a/core/java/android/content/integrity/IntegrityUtils.java b/core/java/android/content/integrity/IntegrityUtils.java
index c3f762469348..c184c6999aa9 100644
--- a/core/java/android/content/integrity/IntegrityUtils.java
+++ b/core/java/android/content/integrity/IntegrityUtils.java
@@ -36,7 +36,7 @@ public class IntegrityUtils {
public static byte[] getBytesFromHexDigest(String hexDigest) {
checkArgument(
hexDigest.length() % 2 == 0,
- "Invalid hex encoding " + hexDigest + ": must have even length");
+ "Invalid hex encoding %s: must have even length", hexDigest);
byte[] rawBytes = new byte[hexDigest.length() / 2];
for (int i = 0; i < rawBytes.length; i++) {
diff --git a/core/java/android/content/integrity/Rule.java b/core/java/android/content/integrity/Rule.java
index 8f6d73f6f028..34eb1e7a4857 100644
--- a/core/java/android/content/integrity/Rule.java
+++ b/core/java/android/content/integrity/Rule.java
@@ -22,7 +22,6 @@ import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.SystemApi;
-import android.annotation.TestApi;
import android.os.Parcel;
import android.os.Parcelable;
@@ -39,7 +38,6 @@ import java.util.Objects;
*
* @hide
*/
-@TestApi
@SystemApi
@VisibleForTesting
public final class Rule implements Parcelable {
@@ -66,7 +64,7 @@ public final class Rule implements Parcelable {
private final @Effect int mEffect;
public Rule(@NonNull IntegrityFormula formula, @Effect int effect) {
- checkArgument(isValidEffect(effect), String.format("Unknown effect: %d", effect));
+ checkArgument(isValidEffect(effect), "Unknown effect: %d", effect);
this.mFormula = Objects.requireNonNull(formula);
this.mEffect = effect;
}
diff --git a/core/java/android/content/integrity/RuleSet.java b/core/java/android/content/integrity/RuleSet.java
index e121ff8bbcaa..b423b54a7d92 100644
--- a/core/java/android/content/integrity/RuleSet.java
+++ b/core/java/android/content/integrity/RuleSet.java
@@ -18,7 +18,6 @@ package android.content.integrity;
import android.annotation.NonNull;
import android.annotation.SystemApi;
-import android.annotation.TestApi;
import java.util.ArrayList;
import java.util.Collections;
@@ -30,7 +29,6 @@ import java.util.Objects;
*
* @hide
*/
-@TestApi
@SystemApi
public class RuleSet {
private final String mVersion;
diff --git a/core/java/android/content/pm/ApplicationInfo.java b/core/java/android/content/pm/ApplicationInfo.java
index d5f2c12e8462..8f4fc261df37 100644
--- a/core/java/android/content/pm/ApplicationInfo.java
+++ b/core/java/android/content/pm/ApplicationInfo.java
@@ -1141,7 +1141,6 @@ public class ApplicationInfo extends PackageItemInfo implements Parcelable {
* @hide
*/
@SystemApi
- @TestApi
public int targetSandboxVersion;
/**
diff --git a/core/java/android/content/pm/PackageInstaller.java b/core/java/android/content/pm/PackageInstaller.java
index f03425b9e117..e2f85282948a 100644
--- a/core/java/android/content/pm/PackageInstaller.java
+++ b/core/java/android/content/pm/PackageInstaller.java
@@ -1722,7 +1722,6 @@ public class PackageInstaller {
*
* @hide
*/
- @TestApi
@SystemApi
@RequiresPermission(android.Manifest.permission.INSTALL_GRANT_RUNTIME_PERMISSIONS)
public void setGrantedRuntimePermissions(String[] permissions) {
@@ -1794,7 +1793,7 @@ public class PackageInstaller {
* @see SessionParams#setEnableRollback(boolean, int)
* @hide
*/
- @SystemApi @TestApi
+ @SystemApi
public void setEnableRollback(boolean enable) {
if (enable) {
installFlags |= PackageManager.INSTALL_ENABLE_ROLLBACK;
@@ -1818,7 +1817,7 @@ public class PackageInstaller {
* @param dataPolicy the rollback data policy for this session
* @hide
*/
- @SystemApi @TestApi
+ @SystemApi
public void setEnableRollback(boolean enable,
@PackageManager.RollbackDataPolicy int dataPolicy) {
if (enable) {
@@ -1841,7 +1840,7 @@ public class PackageInstaller {
}
/** {@hide} */
- @SystemApi @TestApi
+ @SystemApi
public void setRequestDowngrade(boolean requestDowngrade) {
if (requestDowngrade) {
installFlags |= PackageManager.INSTALL_REQUEST_DOWNGRADE;
@@ -1880,7 +1879,6 @@ public class PackageInstaller {
/** {@hide} */
@SystemApi
- @TestApi
public void setInstallAsInstantApp(boolean isInstantApp) {
if (isInstantApp) {
installFlags |= PackageManager.INSTALL_INSTANT_APP;
@@ -1965,7 +1963,7 @@ public class PackageInstaller {
*
* {@hide}
*/
- @SystemApi @TestApi
+ @SystemApi
@RequiresPermission(Manifest.permission.INSTALL_PACKAGES)
public void setStaged() {
this.isStaged = true;
@@ -1976,7 +1974,7 @@ public class PackageInstaller {
*
* {@hide}
*/
- @SystemApi @TestApi
+ @SystemApi
@RequiresPermission(Manifest.permission.INSTALL_PACKAGES)
public void setInstallAsApex() {
installFlags |= PackageManager.INSTALL_APEX;
@@ -2480,7 +2478,6 @@ public class PackageInstaller {
*
* @hide
*/
- @TestApi
@SystemApi
public @NonNull Set<String> getWhitelistedRestrictedPermissions() {
if ((installFlags & PackageManager.INSTALL_ALL_WHITELIST_RESTRICTED_PERMISSIONS) != 0) {
@@ -2504,7 +2501,6 @@ public class PackageInstaller {
*
* @hide
*/
- @TestApi
@SystemApi
public int getAutoRevokePermissionsMode() {
return autoRevokePermissionsMode;
@@ -2633,7 +2629,7 @@ public class PackageInstaller {
*
* @hide
*/
- @SystemApi @TestApi
+ @SystemApi
@PackageManager.RollbackDataPolicy
public int getRollbackDataPolicy() {
return rollbackDataPolicy;
diff --git a/core/java/android/content/pm/PackageManager.java b/core/java/android/content/pm/PackageManager.java
index 72499d54cfed..e54a53efec59 100644
--- a/core/java/android/content/pm/PackageManager.java
+++ b/core/java/android/content/pm/PackageManager.java
@@ -120,7 +120,6 @@ public abstract class PackageManager {
* @hide
*/
@SystemApi
- @TestApi
public interface OnPermissionsChangedListener {
/**
@@ -302,7 +301,10 @@ public abstract class PackageManager {
/**
* {@link PackageInfo} flag: return information about the
* intent filters supported by the activity.
+ *
+ * @deprecated The platform does not support getting {@link IntentFilter}s for the package.
*/
+ @Deprecated
public static final int GET_INTENT_FILTERS = 0x00000020;
/**
@@ -479,7 +481,6 @@ public abstract class PackageManager {
* @hide
*/
@SystemApi
- @TestApi
public static final int MATCH_FACTORY_ONLY = 0x00200000;
/**
@@ -611,7 +612,6 @@ public abstract class PackageManager {
* @hide
*/
@SystemApi
- @TestApi
public static final int MODULE_APEX_NAME = 0x00000001;
/** @hide */
@@ -1577,6 +1577,26 @@ public abstract class PackageManager {
*/
public static final int INSTALL_PARSE_FAILED_SKIPPED = -125;
+ /**
+ * Installation failed return code: this is passed in the
+ * {@link PackageInstaller#EXTRA_LEGACY_STATUS} if the system failed to install the package
+ * because it is attempting to define a permission group that is already defined by some
+ * existing package.
+ *
+ * @hide
+ */
+ public static final int INSTALL_FAILED_DUPLICATE_PERMISSION_GROUP = -126;
+
+ /**
+ * Installation failed return code: this is passed in the
+ * {@link PackageInstaller#EXTRA_LEGACY_STATUS} if the system failed to install the package
+ * because it is attempting to define a permission in a group that does not exists or that is
+ * defined by an packages with an incompatible certificate.
+ *
+ * @hide
+ */
+ public static final int INSTALL_FAILED_BAD_PERMISSION_GROUP = -127;
+
/** @hide */
@IntDef(flag = true, prefix = { "DELETE_" }, value = {
DELETE_KEEP_DATA,
@@ -3319,7 +3339,6 @@ public abstract class PackageManager {
* @hide
*/
@SystemApi
- @TestApi
public static final int FLAG_PERMISSION_USER_SET = 1 << 0;
/**
@@ -3330,7 +3349,6 @@ public abstract class PackageManager {
* @hide
*/
@SystemApi
- @TestApi
public static final int FLAG_PERMISSION_USER_FIXED = 1 << 1;
/**
@@ -3341,7 +3359,6 @@ public abstract class PackageManager {
* @hide
*/
@SystemApi
- @TestApi
public static final int FLAG_PERMISSION_POLICY_FIXED = 1 << 2;
/**
@@ -3358,7 +3375,6 @@ public abstract class PackageManager {
*/
@Deprecated
@SystemApi
- @TestApi
public static final int FLAG_PERMISSION_REVOKE_ON_UPGRADE = 1 << 3;
/**
@@ -3368,7 +3384,6 @@ public abstract class PackageManager {
* @hide
*/
@SystemApi
- @TestApi
public static final int FLAG_PERMISSION_SYSTEM_FIXED = 1 << 4;
/**
@@ -3380,7 +3395,6 @@ public abstract class PackageManager {
* @hide
*/
@SystemApi
- @TestApi
public static final int FLAG_PERMISSION_GRANTED_BY_DEFAULT = 1 << 5;
/**
@@ -3390,7 +3404,6 @@ public abstract class PackageManager {
* @hide
*/
@SystemApi
- @TestApi
public static final int FLAG_PERMISSION_REVIEW_REQUIRED = 1 << 6;
/**
@@ -3428,7 +3441,6 @@ public abstract class PackageManager {
*
* @hide
*/
- @TestApi
@SystemApi
public static final int FLAG_PERMISSION_RESTRICTION_INSTALLER_EXEMPT = 1 << 11;
@@ -3440,7 +3452,6 @@ public abstract class PackageManager {
*
* @hide
*/
- @TestApi
@SystemApi
public static final int FLAG_PERMISSION_RESTRICTION_SYSTEM_EXEMPT = 1 << 12;
@@ -3453,7 +3464,6 @@ public abstract class PackageManager {
*
* @hide
*/
- @TestApi
@SystemApi
public static final int FLAG_PERMISSION_RESTRICTION_UPGRADE_EXEMPT = 1 << 13;
@@ -3466,7 +3476,6 @@ public abstract class PackageManager {
*
* @hide
*/
- @TestApi
@SystemApi
public static final int FLAG_PERMISSION_APPLY_RESTRICTION = 1 << 14;
@@ -3476,7 +3485,6 @@ public abstract class PackageManager {
* @hide
*/
@SystemApi
- @TestApi
public static final int FLAG_PERMISSION_GRANTED_BY_ROLE = 1 << 15;
/**
@@ -3488,7 +3496,6 @@ public abstract class PackageManager {
* @hide
*/
@SystemApi
- @TestApi
public static final int FLAG_PERMISSION_REVOKED_COMPAT = FLAG_PERMISSION_REVOKE_ON_UPGRADE;
/**
@@ -3498,7 +3505,6 @@ public abstract class PackageManager {
* @hide
*/
@SystemApi
- @TestApi
public static final int FLAG_PERMISSION_ONE_TIME = 1 << 16;
/**
@@ -3516,7 +3522,6 @@ public abstract class PackageManager {
*
* @hide
*/
- @TestApi
@SystemApi
public static final int FLAG_PERMISSION_RESTRICTION_ROLE_EXEMPT = 1 << 18;
@@ -3790,8 +3795,8 @@ public abstract class PackageManager {
* @hide
*/
@IntDef({UNSTARTABLE_REASON_UNKNOWN,
- UNSTARTABLE_REASON_DATALOADER_TRANSPORT,
- UNSTARTABLE_REASON_DATALOADER_STORAGE
+ UNSTARTABLE_REASON_CONNECTION_ERROR,
+ UNSTARTABLE_REASON_INSUFFICIENT_STORAGE
})
@Retention(RetentionPolicy.SOURCE)
public @interface UnstartableReason {}
@@ -3800,23 +3805,20 @@ public abstract class PackageManager {
* Unstartable state with no root cause specified. E.g., data loader seeing missing pages but
* unclear about the cause. This corresponds to a generic alert window shown to the user when
* the user attempts to launch the app.
- * @hide
*/
public static final int UNSTARTABLE_REASON_UNKNOWN = 0;
/**
- * Unstartable state after hint from dataloader of issues with the transport layer.
- * This corresponds to an alert window shown to the user indicating network errors.
- * @hide
+ * Unstartable state due to connection issues that interrupt package loading.
+ * This corresponds to an alert window shown to the user indicating connection errors.
*/
- public static final int UNSTARTABLE_REASON_DATALOADER_TRANSPORT = 1;
+ public static final int UNSTARTABLE_REASON_CONNECTION_ERROR = 1;
/**
* Unstartable state after encountering storage limitations.
* This corresponds to an alert window indicating limited storage.
- * @hide
*/
- public static final int UNSTARTABLE_REASON_DATALOADER_STORAGE = 2;
+ public static final int UNSTARTABLE_REASON_INSUFFICIENT_STORAGE = 2;
/** {@hide} */
public int getUserId() {
@@ -4086,7 +4088,7 @@ public abstract class PackageManager {
*
* @hide
*/
- @TestApi @SystemApi
+ @SystemApi
public abstract boolean arePermissionsIndividuallyControlled();
/**
@@ -4337,7 +4339,6 @@ public abstract class PackageManager {
* @hide
*/
@NonNull
- @TestApi
@SystemApi
@RequiresPermission(android.Manifest.permission.INTERACT_ACROSS_USERS_FULL)
public abstract List<PackageInfo> getInstalledPackagesAsUser(@PackageInfoFlags int flags,
@@ -4498,7 +4499,6 @@ public abstract class PackageManager {
*
* @hide
*/
- @TestApi
@SystemApi
@RequiresPermission(android.Manifest.permission.GRANT_RUNTIME_PERMISSIONS)
public abstract void grantRuntimePermission(@NonNull String packageName,
@@ -4525,7 +4525,6 @@ public abstract class PackageManager {
*
* @hide
*/
- @TestApi
@SystemApi
@RequiresPermission(android.Manifest.permission.REVOKE_RUNTIME_PERMISSIONS)
public abstract void revokeRuntimePermission(@NonNull String packageName,
@@ -4553,7 +4552,6 @@ public abstract class PackageManager {
*
* @hide
*/
- @TestApi
@SystemApi
@RequiresPermission(android.Manifest.permission.REVOKE_RUNTIME_PERMISSIONS)
public void revokeRuntimePermission(@NonNull String packageName,
@@ -4572,7 +4570,6 @@ public abstract class PackageManager {
* @hide
*/
@SystemApi
- @TestApi
@RequiresPermission(anyOf = {
android.Manifest.permission.GRANT_RUNTIME_PERMISSIONS,
android.Manifest.permission.REVOKE_RUNTIME_PERMISSIONS,
@@ -4595,7 +4592,6 @@ public abstract class PackageManager {
* @hide
*/
@SystemApi
- @TestApi
@RequiresPermission(anyOf = {
android.Manifest.permission.GRANT_RUNTIME_PERMISSIONS,
android.Manifest.permission.REVOKE_RUNTIME_PERMISSIONS
@@ -6443,7 +6439,6 @@ public abstract class PackageManager {
* @hide
*/
@Nullable
- @TestApi
@SystemApi
@RequiresPermission(Manifest.permission.INTERACT_ACROSS_USERS_FULL)
public abstract String getDefaultBrowserPackageNameAsUser(@UserIdInt int userId);
@@ -7097,7 +7092,6 @@ public abstract class PackageManager {
* @hide
*/
@SystemApi
- @TestApi
@RequiresPermission(Manifest.permission.OBSERVE_GRANT_REVOKE_PERMISSIONS)
public abstract void addOnPermissionsChangeListener(
@NonNull OnPermissionsChangedListener listener);
@@ -7110,7 +7104,6 @@ public abstract class PackageManager {
* @hide
*/
@SystemApi
- @TestApi
@RequiresPermission(Manifest.permission.OBSERVE_GRANT_REVOKE_PERMISSIONS)
public abstract void removeOnPermissionsChangeListener(
@NonNull OnPermissionsChangedListener listener);
@@ -8129,7 +8122,6 @@ public abstract class PackageManager {
* @hide
*/
@SystemApi
- @TestApi
@Nullable
public String getIncidentReportApproverPackageName() {
throw new UnsupportedOperationException(
diff --git a/core/java/android/content/pm/PermissionInfo.java b/core/java/android/content/pm/PermissionInfo.java
index 5d4c843d2eab..0f9e8e59ec94 100644
--- a/core/java/android/content/pm/PermissionInfo.java
+++ b/core/java/android/content/pm/PermissionInfo.java
@@ -160,7 +160,6 @@ public class PermissionInfo extends PackageItemInfo implements Parcelable {
* @hide
*/
@SystemApi
- @TestApi
public static final int PROTECTION_FLAG_OEM = 0x4000;
/**
@@ -181,7 +180,6 @@ public class PermissionInfo extends PackageItemInfo implements Parcelable {
* @hide
*/
@SystemApi
- @TestApi
public static final int PROTECTION_FLAG_SYSTEM_TEXT_CLASSIFIER = 0x10000;
/**
@@ -192,7 +190,6 @@ public class PermissionInfo extends PackageItemInfo implements Parcelable {
* @hide
*/
@SystemApi
- @TestApi
public static final int PROTECTION_FLAG_WELLBEING = 0x20000;
/**
@@ -202,7 +199,6 @@ public class PermissionInfo extends PackageItemInfo implements Parcelable {
* @hide
*/
@SystemApi
- @TestApi
public static final int PROTECTION_FLAG_DOCUMENTER = 0x40000;
/**
@@ -212,7 +208,6 @@ public class PermissionInfo extends PackageItemInfo implements Parcelable {
* @hide
*/
@SystemApi
- @TestApi
public static final int PROTECTION_FLAG_CONFIGURATOR = 0x80000;
/**
@@ -223,7 +218,6 @@ public class PermissionInfo extends PackageItemInfo implements Parcelable {
* @hide
*/
@SystemApi
- @TestApi
public static final int PROTECTION_FLAG_INCIDENT_REPORT_APPROVER = 0x100000;
/**
@@ -234,7 +228,6 @@ public class PermissionInfo extends PackageItemInfo implements Parcelable {
* @hide
*/
@SystemApi
- @TestApi
public static final int PROTECTION_FLAG_APP_PREDICTOR = 0x200000;
/**
@@ -245,7 +238,6 @@ public class PermissionInfo extends PackageItemInfo implements Parcelable {
* @hide
*/
@SystemApi
- @TestApi
public static final int PROTECTION_FLAG_COMPANION = 0x800000;
/**
@@ -256,7 +248,6 @@ public class PermissionInfo extends PackageItemInfo implements Parcelable {
* @hide
*/
@SystemApi
- @TestApi
public static final int PROTECTION_FLAG_RETAIL_DEMO = 0x1000000;
/** @hide */
@@ -340,7 +331,6 @@ public class PermissionInfo extends PackageItemInfo implements Parcelable {
* value of {@link android.R.attr#permissionFlags}.
* @hide
*/
- @TestApi
@SystemApi
public static final int FLAG_REMOVED = 1<<1;
@@ -436,7 +426,6 @@ public class PermissionInfo extends PackageItemInfo implements Parcelable {
* @hide
*/
@SystemApi
- @TestApi
public final @Nullable String backgroundPermission;
/**
@@ -464,82 +453,85 @@ public class PermissionInfo extends PackageItemInfo implements Parcelable {
/** @hide */
@UnsupportedAppUsage
public static @NonNull String protectionToString(int level) {
- String protLevel = "????";
+ final StringBuilder protLevel = new StringBuilder();
switch (level & PROTECTION_MASK_BASE) {
case PermissionInfo.PROTECTION_DANGEROUS:
- protLevel = "dangerous";
+ protLevel.append("dangerous");
break;
case PermissionInfo.PROTECTION_NORMAL:
- protLevel = "normal";
+ protLevel.append("normal");
break;
case PermissionInfo.PROTECTION_SIGNATURE:
- protLevel = "signature";
+ protLevel.append("signature");
break;
case PermissionInfo.PROTECTION_SIGNATURE_OR_SYSTEM:
- protLevel = "signatureOrSystem";
+ protLevel.append("signatureOrSystem");
+ break;
+ default:
+ protLevel.append("????");
break;
}
if ((level & PermissionInfo.PROTECTION_FLAG_PRIVILEGED) != 0) {
- protLevel += "|privileged";
+ protLevel.append("|privileged");
}
if ((level & PermissionInfo.PROTECTION_FLAG_DEVELOPMENT) != 0) {
- protLevel += "|development";
+ protLevel.append("|development");
}
if ((level & PermissionInfo.PROTECTION_FLAG_APPOP) != 0) {
- protLevel += "|appop";
+ protLevel.append("|appop");
}
if ((level & PermissionInfo.PROTECTION_FLAG_PRE23) != 0) {
- protLevel += "|pre23";
+ protLevel.append("|pre23");
}
if ((level & PermissionInfo.PROTECTION_FLAG_INSTALLER) != 0) {
- protLevel += "|installer";
+ protLevel.append("|installer");
}
if ((level & PermissionInfo.PROTECTION_FLAG_VERIFIER) != 0) {
- protLevel += "|verifier";
+ protLevel.append("|verifier");
}
if ((level & PermissionInfo.PROTECTION_FLAG_PREINSTALLED) != 0) {
- protLevel += "|preinstalled";
+ protLevel.append("|preinstalled");
}
if ((level & PermissionInfo.PROTECTION_FLAG_SETUP) != 0) {
- protLevel += "|setup";
+ protLevel.append("|setup");
}
if ((level & PermissionInfo.PROTECTION_FLAG_INSTANT) != 0) {
- protLevel += "|instant";
+ protLevel.append("|instant");
}
if ((level & PermissionInfo.PROTECTION_FLAG_RUNTIME_ONLY) != 0) {
- protLevel += "|runtime";
+ protLevel.append("|runtime");
}
if ((level & PermissionInfo.PROTECTION_FLAG_OEM) != 0) {
- protLevel += "|oem";
+ protLevel.append("|oem");
}
if ((level & PermissionInfo.PROTECTION_FLAG_VENDOR_PRIVILEGED) != 0) {
- protLevel += "|vendorPrivileged";
+ protLevel.append("|vendorPrivileged");
}
if ((level & PermissionInfo.PROTECTION_FLAG_SYSTEM_TEXT_CLASSIFIER) != 0) {
- protLevel += "|textClassifier";
+ protLevel.append("|textClassifier");
}
if ((level & PermissionInfo.PROTECTION_FLAG_WELLBEING) != 0) {
- protLevel += "|wellbeing";
+ protLevel.append("|wellbeing");
}
if ((level & PermissionInfo.PROTECTION_FLAG_DOCUMENTER) != 0) {
- protLevel += "|documenter";
+ protLevel.append("|documenter");
}
if ((level & PROTECTION_FLAG_CONFIGURATOR) != 0) {
- protLevel += "|configurator";
+ protLevel.append("|configurator");
}
if ((level & PermissionInfo.PROTECTION_FLAG_INCIDENT_REPORT_APPROVER) != 0) {
- protLevel += "|incidentReportApprover";
+ protLevel.append("|incidentReportApprover");
}
if ((level & PermissionInfo.PROTECTION_FLAG_APP_PREDICTOR) != 0) {
- protLevel += "|appPredictor";
+ protLevel.append("|appPredictor");
}
if ((level & PermissionInfo.PROTECTION_FLAG_COMPANION) != 0) {
- protLevel += "|companion";
+ protLevel.append("|companion");
}
if ((level & PermissionInfo.PROTECTION_FLAG_RETAIL_DEMO) != 0) {
- protLevel += "|retailDemo";
+ protLevel.append("|retailDemo");
}
- return protLevel;
+ return protLevel.toString();
}
/**
diff --git a/core/java/android/content/res/CompatibilityInfo.java b/core/java/android/content/res/CompatibilityInfo.java
index ccb8cdd71278..f8ed27a6646b 100644
--- a/core/java/android/content/res/CompatibilityInfo.java
+++ b/core/java/android/content/res/CompatibilityInfo.java
@@ -28,6 +28,7 @@ import android.os.Build.VERSION_CODES;
import android.os.Parcel;
import android.os.Parcelable;
import android.util.DisplayMetrics;
+import android.view.InsetsState;
import android.view.MotionEvent;
import android.view.WindowManager;
import android.view.WindowManager.LayoutParams;
@@ -330,15 +331,7 @@ public class CompatibilityInfo implements Parcelable {
}
/**
- * Translate the screen rect to the application frame.
- */
- @UnsupportedAppUsage
- public void translateRectInScreenToAppWinFrame(Rect rect) {
- rect.scale(applicationInvertedScale);
- }
-
- /**
- * Translate the region in window to screen.
+ * Translate the region in window to screen.
*/
@UnsupportedAppUsage
public void translateRegionInWindowToScreen(Region transparentRegion) {
@@ -388,7 +381,14 @@ public class CompatibilityInfo implements Parcelable {
public void translateWindowLayout(WindowManager.LayoutParams params) {
params.scale(applicationScale);
}
-
+
+ /**
+ * Translate a length in application's window to screen.
+ */
+ public float translateLengthInAppWindowToScreen(float length) {
+ return length * applicationScale;
+ }
+
/**
* Translate a Rect in application's window to screen.
*/
@@ -396,7 +396,7 @@ public class CompatibilityInfo implements Parcelable {
public void translateRectInAppWindowToScreen(Rect rect) {
rect.scale(applicationScale);
}
-
+
/**
* Translate a Rect in screen coordinates into the app window's coordinates.
*/
@@ -406,6 +406,13 @@ public class CompatibilityInfo implements Parcelable {
}
/**
+ * Translate an InsetsState in screen coordinates into the app window's coordinates.
+ */
+ public void translateInsetsStateInScreenToAppWindow(InsetsState state) {
+ state.scale(applicationInvertedScale);
+ }
+
+ /**
* Translate a Point in screen coordinates into the app window's coordinates.
*/
public void translatePointInScreenToAppWindow(PointF point) {
diff --git a/core/java/android/content/rollback/PackageRollbackInfo.java b/core/java/android/content/rollback/PackageRollbackInfo.java
index 642a76b453c9..0140280cd3d5 100644
--- a/core/java/android/content/rollback/PackageRollbackInfo.java
+++ b/core/java/android/content/rollback/PackageRollbackInfo.java
@@ -18,7 +18,6 @@ package android.content.rollback;
import android.annotation.NonNull;
import android.annotation.SystemApi;
-import android.annotation.TestApi;
import android.content.pm.PackageManager;
import android.content.pm.VersionedPackage;
import android.os.Parcel;
@@ -32,7 +31,7 @@ import java.util.List;
*
* @hide
*/
-@SystemApi @TestApi
+@SystemApi
public final class PackageRollbackInfo implements Parcelable {
private final VersionedPackage mVersionRolledBackFrom;
diff --git a/core/java/android/content/rollback/RollbackInfo.java b/core/java/android/content/rollback/RollbackInfo.java
index c09cfd54866c..a363718a8b1d 100644
--- a/core/java/android/content/rollback/RollbackInfo.java
+++ b/core/java/android/content/rollback/RollbackInfo.java
@@ -18,7 +18,6 @@ package android.content.rollback;
import android.annotation.NonNull;
import android.annotation.SystemApi;
-import android.annotation.TestApi;
import android.content.pm.VersionedPackage;
import android.os.Parcel;
import android.os.Parcelable;
@@ -31,7 +30,7 @@ import java.util.List;
*
* @hide
*/
-@SystemApi @TestApi
+@SystemApi
public final class RollbackInfo implements Parcelable {
/**
diff --git a/core/java/android/content/rollback/RollbackManager.java b/core/java/android/content/rollback/RollbackManager.java
index 7ebeb212b64a..3636222f558c 100644
--- a/core/java/android/content/rollback/RollbackManager.java
+++ b/core/java/android/content/rollback/RollbackManager.java
@@ -24,7 +24,6 @@ import android.annotation.SystemService;
import android.annotation.TestApi;
import android.content.Context;
import android.content.IntentSender;
-import android.content.pm.PackageInstaller;
import android.content.pm.ParceledListSlice;
import android.content.pm.VersionedPackage;
import android.os.RemoteException;
@@ -43,7 +42,7 @@ import java.util.List;
* @see PackageInstaller.SessionParams#setEnableRollback(boolean)
* @hide
*/
-@SystemApi @TestApi
+@SystemApi
@SystemService(Context.ROLLBACK_SERVICE)
public final class RollbackManager {
private final String mCallerPackageName;
diff --git a/core/java/android/database/CursorWindow.java b/core/java/android/database/CursorWindow.java
index ac0593869d5a..edb7b715e944 100644
--- a/core/java/android/database/CursorWindow.java
+++ b/core/java/android/database/CursorWindow.java
@@ -792,10 +792,10 @@ public class CursorWindow extends SQLiteClosable implements Parcelable {
if (pid == myPid) {
buff.append("this proc=");
} else {
- buff.append("pid " + pid + "=");
+ buff.append("pid ").append(pid).append('=');
}
int num = pidCounts.get(pid);
- buff.append(num + ")");
+ buff.append(num).append(')');
total += num;
}
// limit the returned string size to 1000
diff --git a/core/java/android/database/DatabaseUtils.java b/core/java/android/database/DatabaseUtils.java
index b978ae559390..6c8a8500e4e3 100644
--- a/core/java/android/database/DatabaseUtils.java
+++ b/core/java/android/database/DatabaseUtils.java
@@ -672,7 +672,7 @@ public class DatabaseUtils {
* @param sb the StringBuilder to print to
*/
public static void dumpCursor(Cursor cursor, StringBuilder sb) {
- sb.append(">>>>> Dumping cursor " + cursor + "\n");
+ sb.append(">>>>> Dumping cursor ").append(cursor).append('\n');
if (cursor != null) {
int startPos = cursor.getPosition();
@@ -739,7 +739,7 @@ public class DatabaseUtils {
*/
public static void dumpCurrentRow(Cursor cursor, StringBuilder sb) {
String[] cols = cursor.getColumnNames();
- sb.append("" + cursor.getPosition() + " {\n");
+ sb.append(cursor.getPosition()).append(" {\n");
int length = cols.length;
for (int i = 0; i < length; i++) {
String value;
@@ -750,7 +750,7 @@ public class DatabaseUtils {
// representable by a string, e.g. it is a BLOB.
value = "<unprintable>";
}
- sb.append(" " + cols[i] + '=' + value + "\n");
+ sb.append(" ").append(cols[i]).append('=').append(value).append('\n');
}
sb.append("}\n");
}
diff --git a/core/java/android/database/sqlite/SQLiteConnection.java b/core/java/android/database/sqlite/SQLiteConnection.java
index 2f67f6ddc082..865940e796c8 100644
--- a/core/java/android/database/sqlite/SQLiteConnection.java
+++ b/core/java/android/database/sqlite/SQLiteConnection.java
@@ -226,7 +226,8 @@ public final class SQLiteConnection implements CancellationSignal.OnCancelListen
NoPreloadHolder.DEBUG_SQL_STATEMENTS, NoPreloadHolder.DEBUG_SQL_TIME,
mConfiguration.lookasideSlotSize, mConfiguration.lookasideSlotCount);
} catch (SQLiteCantOpenDatabaseException e) {
- String message = String.format("Cannot open database '%s'", file);
+ final StringBuilder message = new StringBuilder("Cannot open database '")
+ .append(file).append('\'');
try {
// Try to diagnose for common reasons. If something fails in here, that's fine;
@@ -236,20 +237,21 @@ public final class SQLiteConnection implements CancellationSignal.OnCancelListen
final Path dir = path.getParent();
if (!Files.isDirectory(dir)) {
- message += ": Directory " + dir + " doesn't exist";
+ message.append(": Directory ").append(dir).append(" doesn't exist");
} else if (!Files.exists(path)) {
- message += ": File " + path + " doesn't exist";
+ message.append(": File ").append(path).append(" doesn't exist");
} else if (!Files.isReadable(path)) {
- message += ": File " + path + " is not readable";
+ message.append(": File ").append(path).append(" is not readable");
} else if (Files.isDirectory(path)) {
- message += ": Path " + path + " is a directory";
+ message.append(": Path ").append(path).append(" is a directory");
} else {
- message += ": Unknown reason";
+ message.append(": Unknown reason");
}
} catch (Throwable th) {
- message += ": Unknown reason; cannot examine filesystem: " + th.getMessage();
+ message.append(": Unknown reason; cannot examine filesystem: ")
+ .append(th.getMessage());
}
- throw new SQLiteCantOpenDatabaseException(message, e);
+ throw new SQLiteCantOpenDatabaseException(message.toString(), e);
} finally {
mRecentOperations.endOperation(cookie);
}
@@ -1293,11 +1295,11 @@ public final class SQLiteConnection implements CancellationSignal.OnCancelListen
} catch (SQLiteException ex) {
// Ignore.
}
- String label = " (attached) " + name;
+ StringBuilder label = new StringBuilder(" (attached) ").append(name);
if (!path.isEmpty()) {
- label += ": " + path;
+ label.append(": ").append(path);
}
- dbStatsList.add(new DbStats(label, pageCount, pageSize, 0, 0, 0, 0));
+ dbStatsList.add(new DbStats(label.toString(), pageCount, pageSize, 0, 0, 0, 0));
}
} catch (SQLiteException ex) {
// Ignore.
@@ -1319,9 +1321,11 @@ public final class SQLiteConnection implements CancellationSignal.OnCancelListen
private DbStats getMainDbStatsUnsafe(int lookaside, long pageCount, long pageSize) {
// The prepared statement cache is thread-safe so we can access its statistics
// even if we do not own the database connection.
- String label = mConfiguration.path;
- if (!mIsPrimaryConnection) {
- label += " (" + mConnectionId + ")";
+ String label;
+ if (mIsPrimaryConnection) {
+ label = mConfiguration.path;
+ } else {
+ label = mConfiguration.path + " (" + mConnectionId + ")";
}
return new DbStats(label, pageCount, pageSize, lookaside,
mPreparedStatementCache.hitCount(),
diff --git a/core/java/android/database/sqlite/SQLiteCursor.java b/core/java/android/database/sqlite/SQLiteCursor.java
index 4559e918acc5..3bfbe7e7b93b 100644
--- a/core/java/android/database/sqlite/SQLiteCursor.java
+++ b/core/java/android/database/sqlite/SQLiteCursor.java
@@ -147,7 +147,7 @@ public class SQLiteCursor extends AbstractWindowedCursor {
clearOrCreateWindow(getDatabase().getPath());
try {
Preconditions.checkArgumentNonnegative(requiredPos,
- "requiredPos cannot be negative, but was " + requiredPos);
+ "requiredPos cannot be negative");
if (mCount == NO_COUNT) {
mCount = mQuery.fillWindow(mWindow, requiredPos, requiredPos, true);
diff --git a/core/java/android/database/sqlite/SQLiteDatabase.java b/core/java/android/database/sqlite/SQLiteDatabase.java
index 0efd883e8b55..a2cbdd3829ff 100644
--- a/core/java/android/database/sqlite/SQLiteDatabase.java
+++ b/core/java/android/database/sqlite/SQLiteDatabase.java
@@ -1692,7 +1692,7 @@ public final class SQLiteDatabase extends SQLiteClosable {
sql.append((i > 0) ? ",?" : "?");
}
} else {
- sql.append(nullColumnHack + ") VALUES (NULL");
+ sql.append(nullColumnHack).append(") VALUES (NULL");
}
sql.append(')');
@@ -2674,7 +2674,7 @@ public final class SQLiteDatabase extends SQLiteClosable {
"lookasideSlotSize cannot be negative");
Preconditions.checkArgument(
(slotSize > 0 && slotCount > 0) || (slotCount == 0 && slotSize == 0),
- "Invalid configuration: " + slotSize + ", " + slotCount);
+ "Invalid configuration: %d, %d", slotSize, slotCount);
mLookasideSlotSize = slotSize;
mLookasideSlotCount = slotCount;
diff --git a/core/java/android/hardware/Sensor.java b/core/java/android/hardware/Sensor.java
index a6e8c1395701..0f3cdfca70f5 100644
--- a/core/java/android/hardware/Sensor.java
+++ b/core/java/android/hardware/Sensor.java
@@ -616,7 +616,7 @@ public final class Sensor {
public static final String STRING_TYPE_MOTION_DETECT = "android.sensor.motion_detect";
/**
- * A constant describing a motion detect sensor.
+ * A constant describing a heart beat sensor.
*
* See {@link android.hardware.SensorEvent#values SensorEvent.values} for more details.
*
diff --git a/core/java/android/hardware/SensorEvent.java b/core/java/android/hardware/SensorEvent.java
index 9906331be497..236fab0275cf 100644
--- a/core/java/android/hardware/SensorEvent.java
+++ b/core/java/android/hardware/SensorEvent.java
@@ -550,7 +550,7 @@ public class SensorEvent {
* <h4>{@link android.hardware.Sensor#TYPE_HEART_BEAT
* Sensor.TYPE_HEART_BEAT}:</h4>
*
- * A sensor of this type returns an event everytime a hear beat peak is
+ * A sensor of this type returns an event everytime a heart beat peak is
* detected.
*
* Peak here ideally corresponds to the positive peak in the QRS complex of
diff --git a/core/java/android/hardware/biometrics/BiometricConstants.java b/core/java/android/hardware/biometrics/BiometricConstants.java
index 3040932f69dd..bed9a0640693 100644
--- a/core/java/android/hardware/biometrics/BiometricConstants.java
+++ b/core/java/android/hardware/biometrics/BiometricConstants.java
@@ -172,8 +172,7 @@ public interface BiometricConstants {
BIOMETRIC_ERROR_NEGATIVE_BUTTON,
BIOMETRIC_ERROR_NO_DEVICE_CREDENTIAL,
BIOMETRIC_ERROR_SECURITY_UPDATE_REQUIRED,
- BIOMETRIC_PAUSED_REJECTED,
- BIOMETRIC_ERROR_VENDOR_BASE})
+ BIOMETRIC_PAUSED_REJECTED})
@Retention(RetentionPolicy.SOURCE)
@interface Errors {}
@@ -182,6 +181,19 @@ public interface BiometricConstants {
//
/**
+ * @hide
+ */
+ @IntDef({BIOMETRIC_ACQUIRED_GOOD,
+ BIOMETRIC_ACQUIRED_PARTIAL,
+ BIOMETRIC_ACQUIRED_INSUFFICIENT,
+ BIOMETRIC_ACQUIRED_IMAGER_DIRTY,
+ BIOMETRIC_ACQUIRED_TOO_SLOW,
+ BIOMETRIC_ACQUIRED_TOO_FAST,
+ BIOMETRIC_ACQUIRED_VENDOR})
+ @Retention(RetentionPolicy.SOURCE)
+ @interface Acquired {}
+
+ /**
* The image acquired was good.
*/
int BIOMETRIC_ACQUIRED_GOOD = 0;
diff --git a/core/java/android/hardware/biometrics/BiometricFingerprintConstants.java b/core/java/android/hardware/biometrics/BiometricFingerprintConstants.java
index 46e8cc036809..c7b554b3aafc 100644
--- a/core/java/android/hardware/biometrics/BiometricFingerprintConstants.java
+++ b/core/java/android/hardware/biometrics/BiometricFingerprintConstants.java
@@ -16,11 +16,15 @@
package android.hardware.biometrics;
+import android.annotation.IntDef;
import android.app.KeyguardManager;
import android.compat.annotation.UnsupportedAppUsage;
import android.hardware.biometrics.BiometricManager.Authenticators;
import android.hardware.fingerprint.FingerprintManager;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+
/**
* Interface containing all of the fingerprint-specific constants.
*
@@ -36,6 +40,27 @@ public interface BiometricFingerprintConstants {
//
/**
+ * @hide
+ */
+ @IntDef({FINGERPRINT_ERROR_HW_UNAVAILABLE,
+ FINGERPRINT_ERROR_UNABLE_TO_PROCESS,
+ FINGERPRINT_ERROR_TIMEOUT,
+ FINGERPRINT_ERROR_NO_SPACE,
+ FINGERPRINT_ERROR_CANCELED,
+ FINGERPRINT_ERROR_UNABLE_TO_REMOVE,
+ FINGERPRINT_ERROR_LOCKOUT,
+ FINGERPRINT_ERROR_VENDOR,
+ FINGERPRINT_ERROR_LOCKOUT_PERMANENT,
+ FINGERPRINT_ERROR_USER_CANCELED,
+ FINGERPRINT_ERROR_NO_FINGERPRINTS,
+ FINGERPRINT_ERROR_HW_NOT_PRESENT,
+ FINGERPRINT_ERROR_NEGATIVE_BUTTON,
+ BIOMETRIC_ERROR_NO_DEVICE_CREDENTIAL,
+ BIOMETRIC_ERROR_SECURITY_UPDATE_REQUIRED})
+ @Retention(RetentionPolicy.SOURCE)
+ @interface FingerprintError {}
+
+ /**
* The hardware is unavailable. Try again later.
*/
int FINGERPRINT_ERROR_HW_UNAVAILABLE = 1;
@@ -150,6 +175,20 @@ public interface BiometricFingerprintConstants {
//
/**
+ * @hide
+ */
+ @IntDef({FINGERPRINT_ACQUIRED_GOOD,
+ FINGERPRINT_ACQUIRED_PARTIAL,
+ FINGERPRINT_ACQUIRED_INSUFFICIENT,
+ FINGERPRINT_ACQUIRED_IMAGER_DIRTY,
+ FINGERPRINT_ACQUIRED_TOO_SLOW,
+ FINGERPRINT_ACQUIRED_TOO_FAST,
+ FINGERPRINT_ACQUIRED_VENDOR,
+ FINGERPRINT_ACQUIRED_START})
+ @Retention(RetentionPolicy.SOURCE)
+ @interface FingerprintAcquired {}
+
+ /**
* The image acquired was good.
*/
int FINGERPRINT_ACQUIRED_GOOD = 0;
diff --git a/core/java/android/hardware/biometrics/BiometricTestSession.java b/core/java/android/hardware/biometrics/BiometricTestSession.java
index 4c7aa27968fe..802655b0d364 100644
--- a/core/java/android/hardware/biometrics/BiometricTestSession.java
+++ b/core/java/android/hardware/biometrics/BiometricTestSession.java
@@ -22,6 +22,7 @@ import android.annotation.NonNull;
import android.annotation.RequiresPermission;
import android.annotation.TestApi;
import android.content.Context;
+import android.hardware.fingerprint.FingerprintManager;
import android.os.RemoteException;
import android.util.ArraySet;
@@ -128,11 +129,14 @@ public class BiometricTestSession implements AutoCloseable {
* Simulates an acquired message from the HAL.
*
* @param userId User that this command applies to.
+ * @param acquireInfo See
+ * {@link BiometricPrompt.AuthenticationCallback#onAuthenticationAcquired(int)} and
+ * {@link FingerprintManager.AuthenticationCallback#onAuthenticationAcquired(int)}
*/
@RequiresPermission(TEST_BIOMETRIC)
- public void notifyAcquired(int userId) {
+ public void notifyAcquired(int userId, int acquireInfo) {
try {
- mTestSession.notifyAcquired(userId);
+ mTestSession.notifyAcquired(userId, acquireInfo);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
@@ -142,11 +146,14 @@ public class BiometricTestSession implements AutoCloseable {
* Simulates an error message from the HAL.
*
* @param userId User that this command applies to.
+ * @param errorCode See
+ * {@link BiometricPrompt.AuthenticationCallback#onAuthenticationError(int, CharSequence)} and
+ * {@link FingerprintManager.AuthenticationCallback#onAuthenticationError(int, CharSequence)}
*/
@RequiresPermission(TEST_BIOMETRIC)
- public void notifyError(int userId) {
+ public void notifyError(int userId, int errorCode) {
try {
- mTestSession.notifyError(userId);
+ mTestSession.notifyError(userId, errorCode);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
diff --git a/core/java/android/hardware/biometrics/ITestSession.aidl b/core/java/android/hardware/biometrics/ITestSession.aidl
index 5677f6517ae5..6112f17949d7 100644
--- a/core/java/android/hardware/biometrics/ITestSession.aidl
+++ b/core/java/android/hardware/biometrics/ITestSession.aidl
@@ -42,10 +42,10 @@ interface ITestSession {
void rejectAuthentication(int userId);
// Simulates an acquired message from the HAL.
- void notifyAcquired(int userId);
+ void notifyAcquired(int userId, int acquireInfo);
// Simulates an error message from the HAL.
- void notifyError(int userId);
+ void notifyError(int userId, int errorCode);
// Matches the framework's cached enrollments against the HAL's enrollments. Any enrollment
// that isn't known by both sides are deleted. This should generally be used when the test
diff --git a/core/java/android/hardware/camera2/CameraDevice.java b/core/java/android/hardware/camera2/CameraDevice.java
index decf05396c1f..cd137078818c 100644
--- a/core/java/android/hardware/camera2/CameraDevice.java
+++ b/core/java/android/hardware/camera2/CameraDevice.java
@@ -20,7 +20,6 @@ import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.SystemApi;
-import android.annotation.TestApi;
import android.hardware.camera2.params.InputConfiguration;
import android.hardware.camera2.params.OutputConfiguration;
import android.hardware.camera2.params.SessionConfiguration;
@@ -358,7 +357,6 @@ public abstract class CameraDevice implements AutoCloseable {
* @hide
*/
@SystemApi
- @TestApi
public static final int SESSION_OPERATION_MODE_NORMAL =
0; // ICameraDeviceUser.NORMAL_MODE;
@@ -369,7 +367,6 @@ public abstract class CameraDevice implements AutoCloseable {
* @hide
*/
@SystemApi
- @TestApi
public static final int SESSION_OPERATION_MODE_CONSTRAINED_HIGH_SPEED =
1; // ICameraDeviceUser.CONSTRAINED_HIGH_SPEED_MODE;
@@ -380,7 +377,6 @@ public abstract class CameraDevice implements AutoCloseable {
* @hide
*/
@SystemApi
- @TestApi
public static final int SESSION_OPERATION_MODE_VENDOR_START =
0x8000; // ICameraDeviceUser.VENDOR_MODE_START;
@@ -423,7 +419,6 @@ public abstract class CameraDevice implements AutoCloseable {
* @hide
*/
@SystemApi
- @TestApi
@Deprecated
public abstract void createCustomCaptureSession(
InputConfiguration inputConfig,
diff --git a/core/java/android/hardware/camera2/params/ColorSpaceTransform.java b/core/java/android/hardware/camera2/params/ColorSpaceTransform.java
index 1e1c4b171e2e..5b3a6d726422 100644
--- a/core/java/android/hardware/camera2/params/ColorSpaceTransform.java
+++ b/core/java/android/hardware/camera2/params/ColorSpaceTransform.java
@@ -78,7 +78,7 @@ public final class ColorSpaceTransform {
mElements = new int[COUNT_INT];
for (int i = 0; i < elements.length; ++i) {
- checkNotNull(elements, "element[" + i + "] must not be null");
+ checkNotNull(elements, "element[%d] must not be null", i);
mElements[i * RATIONAL_SIZE + OFFSET_NUMERATOR] = elements[i].getNumerator();
mElements[i * RATIONAL_SIZE + OFFSET_DENOMINATOR] = elements[i].getDenominator();
}
@@ -116,7 +116,7 @@ public final class ColorSpaceTransform {
}
for (int i = 0; i < elements.length; ++i) {
- checkNotNull(elements, "element " + i + " must not be null");
+ checkNotNull(elements, "element %d must not be null", i);
}
mElements = Arrays.copyOf(elements, elements.length);
diff --git a/core/java/android/hardware/display/AmbientBrightnessDayStats.java b/core/java/android/hardware/display/AmbientBrightnessDayStats.java
index 26fd2654239f..8aff911ea42c 100644
--- a/core/java/android/hardware/display/AmbientBrightnessDayStats.java
+++ b/core/java/android/hardware/display/AmbientBrightnessDayStats.java
@@ -19,7 +19,6 @@ package android.hardware.display;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.SystemApi;
-import android.annotation.TestApi;
import android.os.Parcel;
import android.os.Parcelable;
@@ -36,7 +35,6 @@ import java.util.Objects;
* @hide
*/
@SystemApi
-@TestApi
public final class AmbientBrightnessDayStats implements Parcelable {
/** The localdate for which brightness stats are being tracked */
diff --git a/core/java/android/hardware/display/BrightnessChangeEvent.java b/core/java/android/hardware/display/BrightnessChangeEvent.java
index a6a44bea816b..e2d836c59099 100644
--- a/core/java/android/hardware/display/BrightnessChangeEvent.java
+++ b/core/java/android/hardware/display/BrightnessChangeEvent.java
@@ -19,7 +19,6 @@ package android.hardware.display;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.SystemApi;
-import android.annotation.TestApi;
import android.os.Parcel;
import android.os.Parcelable;
@@ -32,7 +31,6 @@ import java.util.Objects;
* @hide
*/
@SystemApi
-@TestApi
public final class BrightnessChangeEvent implements Parcelable {
/** Brightness in nits */
public final float brightness;
diff --git a/core/java/android/hardware/display/BrightnessConfiguration.java b/core/java/android/hardware/display/BrightnessConfiguration.java
index 6412a0ce7219..d9c1063cd39d 100644
--- a/core/java/android/hardware/display/BrightnessConfiguration.java
+++ b/core/java/android/hardware/display/BrightnessConfiguration.java
@@ -20,7 +20,6 @@ import android.annotation.FloatRange;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.SystemApi;
-import android.annotation.TestApi;
import android.content.pm.ApplicationInfo;
import android.os.Parcel;
import android.os.Parcelable;
@@ -44,7 +43,6 @@ import java.util.Objects;
/** @hide */
@SystemApi
-@TestApi
public final class BrightnessConfiguration implements Parcelable {
private static final String TAG_BRIGHTNESS_CURVE = "brightness-curve";
private static final String TAG_BRIGHTNESS_POINT = "brightness-point";
diff --git a/core/java/android/hardware/display/BrightnessCorrection.java b/core/java/android/hardware/display/BrightnessCorrection.java
index 0879787077aa..bbfc45edb89a 100644
--- a/core/java/android/hardware/display/BrightnessCorrection.java
+++ b/core/java/android/hardware/display/BrightnessCorrection.java
@@ -20,7 +20,6 @@ import android.annotation.FloatRange;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.SystemApi;
-import android.annotation.TestApi;
import android.os.Parcel;
import android.os.Parcelable;
import android.util.MathUtils;
@@ -44,7 +43,6 @@ import java.io.IOException;
* @hide
*/
@SystemApi
-@TestApi
public final class BrightnessCorrection implements Parcelable {
private static final int SCALE_AND_TRANSLATE_LOG = 1;
diff --git a/core/java/android/hardware/display/DisplayManager.java b/core/java/android/hardware/display/DisplayManager.java
index fc14b89d83f7..68b9d5227746 100644
--- a/core/java/android/hardware/display/DisplayManager.java
+++ b/core/java/android/hardware/display/DisplayManager.java
@@ -699,7 +699,6 @@ public final class DisplayManager {
* @hide
*/
@SystemApi
- @TestApi
public Point getStableDisplaySize() {
return mGlobal.getStableDisplaySize();
}
@@ -709,7 +708,6 @@ public final class DisplayManager {
* @hide until we make it a system api.
*/
@SystemApi
- @TestApi
@RequiresPermission(Manifest.permission.BRIGHTNESS_SLIDER_USAGE)
public List<BrightnessChangeEvent> getBrightnessEvents() {
return mGlobal.getBrightnessEvents(mContext.getOpPackageName());
@@ -721,7 +719,6 @@ public final class DisplayManager {
* @hide until we make it a system api
*/
@SystemApi
- @TestApi
@RequiresPermission(Manifest.permission.ACCESS_AMBIENT_LIGHT_STATS)
public List<AmbientBrightnessDayStats> getAmbientBrightnessStats() {
return mGlobal.getAmbientBrightnessStats();
@@ -733,7 +730,6 @@ public final class DisplayManager {
* @hide
*/
@SystemApi
- @TestApi
@RequiresPermission(Manifest.permission.CONFIGURE_DISPLAY_BRIGHTNESS)
public void setBrightnessConfiguration(BrightnessConfiguration c) {
setBrightnessConfigurationForUser(c, mContext.getUserId(), mContext.getPackageName());
@@ -758,7 +754,6 @@ public final class DisplayManager {
* @hide
*/
@SystemApi
- @TestApi
@RequiresPermission(Manifest.permission.CONFIGURE_DISPLAY_BRIGHTNESS)
public BrightnessConfiguration getBrightnessConfiguration() {
return getBrightnessConfigurationForUser(mContext.getUserId());
@@ -784,7 +779,6 @@ public final class DisplayManager {
* @hide
*/
@SystemApi
- @TestApi
@RequiresPermission(Manifest.permission.CONFIGURE_DISPLAY_BRIGHTNESS)
@Nullable
public BrightnessConfiguration getDefaultBrightnessConfiguration() {
diff --git a/core/java/android/hardware/display/DisplayManagerInternal.java b/core/java/android/hardware/display/DisplayManagerInternal.java
index a86c5cbd2451..defcab7c3035 100644
--- a/core/java/android/hardware/display/DisplayManagerInternal.java
+++ b/core/java/android/hardware/display/DisplayManagerInternal.java
@@ -267,12 +267,6 @@ public abstract class DisplayManagerInternal {
public abstract void ignoreProximitySensorUntilChanged();
/**
- * Sets the folded state of the device.
- * TODO: b/168208522 - Remove in favor of DisplayStatePolicy when that is available.
- */
- public abstract void setDeviceFolded(boolean isFolded);
-
- /**
* Describes the requested power state of the display.
*
* This object is intended to describe the general characteristics of the
diff --git a/core/java/android/hardware/hdmi/HdmiControlManager.java b/core/java/android/hardware/hdmi/HdmiControlManager.java
index e5e73200c8ef..5b186c78df54 100644
--- a/core/java/android/hardware/hdmi/HdmiControlManager.java
+++ b/core/java/android/hardware/hdmi/HdmiControlManager.java
@@ -28,7 +28,6 @@ import android.annotation.StringDef;
import android.annotation.SuppressLint;
import android.annotation.SystemApi;
import android.annotation.SystemService;
-import android.annotation.TestApi;
import android.content.Context;
import android.content.pm.PackageManager;
import android.os.Binder;
@@ -60,7 +59,6 @@ import java.util.concurrent.Executor;
* @hide
*/
@SystemApi
-@TestApi
@SystemService(Context.HDMI_CONTROL_SERVICE)
@RequiresFeature(PackageManager.FEATURE_HDMI_CEC)
public final class HdmiControlManager {
diff --git a/core/java/android/hardware/hdmi/HdmiDeviceInfo.java b/core/java/android/hardware/hdmi/HdmiDeviceInfo.java
index 55b07268d201..3fd20f12381e 100644
--- a/core/java/android/hardware/hdmi/HdmiDeviceInfo.java
+++ b/core/java/android/hardware/hdmi/HdmiDeviceInfo.java
@@ -463,7 +463,7 @@ public class HdmiDeviceInfo implements Parcelable {
@NonNull
@Override
public String toString() {
- StringBuffer s = new StringBuffer();
+ StringBuilder s = new StringBuilder();
switch (mHdmiDeviceType) {
case HDMI_DEVICE_TYPE_CEC:
s.append("CEC: ");
diff --git a/core/java/android/hardware/hdmi/HdmiPortInfo.java b/core/java/android/hardware/hdmi/HdmiPortInfo.java
index 52c3628f358b..e4b311a64c31 100644
--- a/core/java/android/hardware/hdmi/HdmiPortInfo.java
+++ b/core/java/android/hardware/hdmi/HdmiPortInfo.java
@@ -18,7 +18,6 @@ package android.hardware.hdmi;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.SystemApi;
-import android.annotation.TestApi;
import android.os.Parcel;
import android.os.Parcelable;
@@ -29,7 +28,6 @@ import android.os.Parcelable;
* @hide
*/
@SystemApi
-@TestApi
public final class HdmiPortInfo implements Parcelable {
/** HDMI port type: Input */
public static final int PORT_INPUT = 0;
@@ -171,7 +169,7 @@ public final class HdmiPortInfo implements Parcelable {
@NonNull
@Override
public String toString() {
- StringBuffer s = new StringBuffer();
+ StringBuilder s = new StringBuilder();
s.append("port_id: ").append(mId).append(", ");
s.append("type: ").append((mType == PORT_INPUT) ? "HDMI_IN" : "HDMI_OUT").append(", ");
s.append("address: ").append(String.format("0x%04x", mAddress)).append(", ");
diff --git a/core/java/android/hardware/hdmi/HdmiSwitchClient.java b/core/java/android/hardware/hdmi/HdmiSwitchClient.java
index 4685e1e04618..cbfbe3940e47 100644
--- a/core/java/android/hardware/hdmi/HdmiSwitchClient.java
+++ b/core/java/android/hardware/hdmi/HdmiSwitchClient.java
@@ -18,7 +18,6 @@ package android.hardware.hdmi;
import android.annotation.CallbackExecutor;
import android.annotation.NonNull;
import android.annotation.SystemApi;
-import android.annotation.TestApi;
import android.hardware.hdmi.HdmiControlManager.ControlCallbackResult;
import android.os.Binder;
import android.os.RemoteException;
@@ -39,7 +38,6 @@ import java.util.concurrent.Executor;
* @hide
*/
@SystemApi
-@TestApi
public class HdmiSwitchClient extends HdmiClient {
private static final String TAG = "HdmiSwitchClient";
diff --git a/core/java/android/hardware/lights/Light.java b/core/java/android/hardware/lights/Light.java
index 1c95fb632548..da270182052d 100644
--- a/core/java/android/hardware/lights/Light.java
+++ b/core/java/android/hardware/lights/Light.java
@@ -19,7 +19,6 @@ package android.hardware.lights;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.SystemApi;
-import android.annotation.TestApi;
import android.os.Parcel;
import android.os.Parcelable;
@@ -29,7 +28,6 @@ import android.os.Parcelable;
* @hide
*/
@SystemApi
-@TestApi
public final class Light implements Parcelable {
private final int mId;
private final int mOrdinal;
diff --git a/core/java/android/hardware/lights/LightState.java b/core/java/android/hardware/lights/LightState.java
index e55aa702f15c..cd39e6df91a9 100644
--- a/core/java/android/hardware/lights/LightState.java
+++ b/core/java/android/hardware/lights/LightState.java
@@ -19,7 +19,6 @@ package android.hardware.lights;
import android.annotation.ColorInt;
import android.annotation.NonNull;
import android.annotation.SystemApi;
-import android.annotation.TestApi;
import android.os.Parcel;
import android.os.Parcelable;
@@ -36,7 +35,6 @@ import android.os.Parcelable;
* @hide
*/
@SystemApi
-@TestApi
public final class LightState implements Parcelable {
private final int mColor;
diff --git a/core/java/android/hardware/lights/LightsManager.java b/core/java/android/hardware/lights/LightsManager.java
index 8cd231224472..33e5fcaf2abb 100644
--- a/core/java/android/hardware/lights/LightsManager.java
+++ b/core/java/android/hardware/lights/LightsManager.java
@@ -45,7 +45,6 @@ import java.util.List;
* @hide
*/
@SystemApi
-@TestApi
@SystemService(Context.LIGHTS_SERVICE)
public final class LightsManager {
private static final String TAG = "LightsManager";
diff --git a/core/java/android/hardware/lights/LightsRequest.java b/core/java/android/hardware/lights/LightsRequest.java
index 5c4fc6707e96..a318992c35ee 100644
--- a/core/java/android/hardware/lights/LightsRequest.java
+++ b/core/java/android/hardware/lights/LightsRequest.java
@@ -18,7 +18,6 @@ package android.hardware.lights;
import android.annotation.NonNull;
import android.annotation.SystemApi;
-import android.annotation.TestApi;
import android.util.SparseArray;
import com.android.internal.util.Preconditions;
@@ -29,7 +28,6 @@ import com.android.internal.util.Preconditions;
* @hide
*/
@SystemApi
-@TestApi
public final class LightsRequest {
/** Visible to {@link LightsManager.Session}. */
diff --git a/core/java/android/hardware/soundtrigger/SoundTrigger.java b/core/java/android/hardware/soundtrigger/SoundTrigger.java
index ecdbf4cdf9ec..e58403fe387d 100644
--- a/core/java/android/hardware/soundtrigger/SoundTrigger.java
+++ b/core/java/android/hardware/soundtrigger/SoundTrigger.java
@@ -67,7 +67,6 @@ import java.util.UUID;
*
* @hide
*/
-@TestApi
@SystemApi
public class SoundTrigger {
private static final String TAG = "SoundTrigger";
diff --git a/core/java/android/metrics/LogMaker.java b/core/java/android/metrics/LogMaker.java
index d8a2082f4eae..a19eb5668d55 100644
--- a/core/java/android/metrics/LogMaker.java
+++ b/core/java/android/metrics/LogMaker.java
@@ -16,7 +16,6 @@
package android.metrics;
import android.annotation.SystemApi;
-import android.annotation.TestApi;
import android.content.ComponentName;
import android.util.Log;
import android.util.SparseArray;
@@ -32,7 +31,6 @@ import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
* @hide
*/
@SystemApi
-@TestApi
public class LogMaker {
private static final String TAG = "LogBuilder";
diff --git a/core/java/android/metrics/MetricsReader.java b/core/java/android/metrics/MetricsReader.java
index 27f9a5dbf51c..5f356ca00d88 100644
--- a/core/java/android/metrics/MetricsReader.java
+++ b/core/java/android/metrics/MetricsReader.java
@@ -16,7 +16,6 @@
package android.metrics;
import android.annotation.SystemApi;
-import android.annotation.TestApi;
import android.util.EventLog;
import com.android.internal.annotations.VisibleForTesting;
@@ -36,7 +35,6 @@ import java.util.concurrent.TimeUnit;
* @hide
*/
@SystemApi
-@TestApi
public class MetricsReader {
private Queue<LogMaker> mPendingQueue = new LinkedList<>();
private Queue<LogMaker> mSeenQueue = new LinkedList<>();
diff --git a/core/java/android/net/CaptivePortal.java b/core/java/android/net/CaptivePortal.java
index 8afeb3033cdb..c2586fa0c825 100644
--- a/core/java/android/net/CaptivePortal.java
+++ b/core/java/android/net/CaptivePortal.java
@@ -19,7 +19,6 @@ import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.RequiresPermission;
import android.annotation.SystemApi;
-import android.annotation.TestApi;
import android.os.IBinder;
import android.os.Parcel;
import android.os.Parcelable;
@@ -42,7 +41,6 @@ public class CaptivePortal implements Parcelable {
* @hide
*/
@SystemApi
- @TestApi
public static final int APP_RETURN_DISMISSED = 0;
/**
* Response code from the captive portal application, indicating that the user did not login and
@@ -52,7 +50,6 @@ public class CaptivePortal implements Parcelable {
* @hide
*/
@SystemApi
- @TestApi
public static final int APP_RETURN_UNWANTED = 1;
/**
* Response code from the captive portal application, indicating that the user does not wish to
@@ -62,7 +59,6 @@ public class CaptivePortal implements Parcelable {
* @hide
*/
@SystemApi
- @TestApi
public static final int APP_RETURN_WANTED_AS_IS = 2;
/** Event offset of request codes from captive portal application. */
private static final int APP_REQUEST_BASE = 100;
@@ -74,7 +70,6 @@ public class CaptivePortal implements Parcelable {
* @hide
*/
@SystemApi
- @TestApi
public static final int APP_REQUEST_REEVALUATION_REQUIRED = APP_REQUEST_BASE + 0;
private final IBinder mBinder;
@@ -154,7 +149,6 @@ public class CaptivePortal implements Parcelable {
* @hide
*/
@SystemApi
- @TestApi
public void useNetwork() {
try {
ICaptivePortal.Stub.asInterface(mBinder).appResponse(APP_RETURN_WANTED_AS_IS);
@@ -167,7 +161,6 @@ public class CaptivePortal implements Parcelable {
* @hide
*/
@SystemApi
- @TestApi
@RequiresPermission(android.Manifest.permission.NETWORK_STACK)
public void reevaluateNetwork() {
try {
@@ -183,7 +176,6 @@ public class CaptivePortal implements Parcelable {
* @hide
*/
@SystemApi
- @TestApi
public void logEvent(@EventId int eventId, @NonNull String packageName) {
try {
ICaptivePortal.Stub.asInterface(mBinder).logEvent(eventId, packageName);
diff --git a/core/java/android/net/CaptivePortalData.java b/core/java/android/net/CaptivePortalData.java
index 09f47625a8e4..59e62a675abc 100644
--- a/core/java/android/net/CaptivePortalData.java
+++ b/core/java/android/net/CaptivePortalData.java
@@ -19,7 +19,6 @@ package android.net;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.SystemApi;
-import android.annotation.TestApi;
import android.os.Parcel;
import android.os.Parcelable;
@@ -30,7 +29,6 @@ import java.util.Objects;
* @hide
*/
@SystemApi
-@TestApi
public final class CaptivePortalData implements Parcelable {
private final long mRefreshTimeMillis;
@Nullable
diff --git a/core/java/android/net/ConnectivityManager.java b/core/java/android/net/ConnectivityManager.java
index b2eba6318730..1012f47f8c0a 100644
--- a/core/java/android/net/ConnectivityManager.java
+++ b/core/java/android/net/ConnectivityManager.java
@@ -269,7 +269,6 @@ public class ConnectivityManager {
* {@hide}
*/
@SystemApi
- @TestApi
public static final String EXTRA_CAPTIVE_PORTAL_PROBE_SPEC =
"android.net.extra.CAPTIVE_PORTAL_PROBE_SPEC";
@@ -278,7 +277,6 @@ public class ConnectivityManager {
* {@hide}
*/
@SystemApi
- @TestApi
public static final String EXTRA_CAPTIVE_PORTAL_USER_AGENT =
"android.net.extra.CAPTIVE_PORTAL_USER_AGENT";
@@ -4413,7 +4411,6 @@ public class ConnectivityManager {
* @hide
*/
@SystemApi
- @TestApi
@RequiresPermission(NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK)
public void startCaptivePortalApp(@NonNull Network network, @NonNull Bundle appExtras) {
try {
diff --git a/core/java/android/net/EthernetManager.java b/core/java/android/net/EthernetManager.java
index d975017f9c8e..5860e20ad3b4 100644
--- a/core/java/android/net/EthernetManager.java
+++ b/core/java/android/net/EthernetManager.java
@@ -37,7 +37,6 @@ import java.util.concurrent.Executor;
* @hide
*/
@SystemApi
-@TestApi
@SystemService(Context.ETHERNET_SERVICE)
public class EthernetManager {
private static final String TAG = "EthernetManager";
diff --git a/core/java/android/net/IpPrefix.java b/core/java/android/net/IpPrefix.java
index 06f5f270d189..bcb65fab8571 100644
--- a/core/java/android/net/IpPrefix.java
+++ b/core/java/android/net/IpPrefix.java
@@ -20,7 +20,6 @@ import android.annotation.IntRange;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.SystemApi;
-import android.annotation.TestApi;
import android.os.Parcel;
import android.os.Parcelable;
import android.util.Pair;
@@ -89,7 +88,6 @@ public final class IpPrefix implements Parcelable {
* @hide
*/
@SystemApi
- @TestApi
public IpPrefix(@NonNull InetAddress address, @IntRange(from = 0, to = 128) int prefixLength) {
// We don't reuse the (byte[], int) constructor because it calls clone() on the byte array,
// which is unnecessary because getAddress() already returns a clone.
@@ -108,7 +106,6 @@ public final class IpPrefix implements Parcelable {
* @hide
*/
@SystemApi
- @TestApi
public IpPrefix(@NonNull String prefix) {
// We don't reuse the (InetAddress, int) constructor because "error: call to this must be
// first statement in constructor". We could factor out setting the member variables to an
diff --git a/core/java/android/net/IpSecAlgorithm.java b/core/java/android/net/IpSecAlgorithm.java
index a4f7b7454bd9..e89451e4f4ef 100644
--- a/core/java/android/net/IpSecAlgorithm.java
+++ b/core/java/android/net/IpSecAlgorithm.java
@@ -201,14 +201,16 @@ public final class IpSecAlgorithm implements Parcelable {
@VisibleForTesting
public static final Map<String, Integer> ALGO_TO_REQUIRED_FIRST_SDK = new HashMap<>();
+ private static final int SDK_VERSION_ZERO = 0;
+
static {
- ALGO_TO_REQUIRED_FIRST_SDK.put(CRYPT_AES_CBC, Build.VERSION_CODES.P);
- ALGO_TO_REQUIRED_FIRST_SDK.put(AUTH_HMAC_MD5, Build.VERSION_CODES.P);
- ALGO_TO_REQUIRED_FIRST_SDK.put(AUTH_HMAC_SHA1, Build.VERSION_CODES.P);
- ALGO_TO_REQUIRED_FIRST_SDK.put(AUTH_HMAC_SHA256, Build.VERSION_CODES.P);
- ALGO_TO_REQUIRED_FIRST_SDK.put(AUTH_HMAC_SHA384, Build.VERSION_CODES.P);
- ALGO_TO_REQUIRED_FIRST_SDK.put(AUTH_HMAC_SHA512, Build.VERSION_CODES.P);
- ALGO_TO_REQUIRED_FIRST_SDK.put(AUTH_CRYPT_AES_GCM, Build.VERSION_CODES.P);
+ ALGO_TO_REQUIRED_FIRST_SDK.put(CRYPT_AES_CBC, SDK_VERSION_ZERO);
+ ALGO_TO_REQUIRED_FIRST_SDK.put(AUTH_HMAC_MD5, SDK_VERSION_ZERO);
+ ALGO_TO_REQUIRED_FIRST_SDK.put(AUTH_HMAC_SHA1, SDK_VERSION_ZERO);
+ ALGO_TO_REQUIRED_FIRST_SDK.put(AUTH_HMAC_SHA256, SDK_VERSION_ZERO);
+ ALGO_TO_REQUIRED_FIRST_SDK.put(AUTH_HMAC_SHA384, SDK_VERSION_ZERO);
+ ALGO_TO_REQUIRED_FIRST_SDK.put(AUTH_HMAC_SHA512, SDK_VERSION_ZERO);
+ ALGO_TO_REQUIRED_FIRST_SDK.put(AUTH_CRYPT_AES_GCM, SDK_VERSION_ZERO);
// STOPSHIP: b/170424293 Use Build.VERSION_CODES.S when it is defined
ALGO_TO_REQUIRED_FIRST_SDK.put(CRYPT_AES_CTR, Build.VERSION_CODES.R + 1);
diff --git a/core/java/android/net/LinkAddress.java b/core/java/android/net/LinkAddress.java
index 772c685856c7..d1bdaa078cdc 100644
--- a/core/java/android/net/LinkAddress.java
+++ b/core/java/android/net/LinkAddress.java
@@ -30,7 +30,6 @@ import android.annotation.IntRange;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.SystemApi;
-import android.annotation.TestApi;
import android.compat.annotation.UnsupportedAppUsage;
import android.os.Build;
import android.os.Parcel;
@@ -158,7 +157,6 @@ public class LinkAddress implements Parcelable {
* @return true if the address is IPv6.
* @hide
*/
- @TestApi
@SystemApi
public boolean isIpv6() {
return address instanceof Inet6Address;
@@ -180,7 +178,6 @@ public class LinkAddress implements Parcelable {
* @return true if the address is IPv4 or is a mapped IPv4 address.
* @hide
*/
- @TestApi
@SystemApi
public boolean isIpv4() {
return address instanceof Inet4Address;
@@ -243,7 +240,6 @@ public class LinkAddress implements Parcelable {
* @hide
*/
@SystemApi
- @TestApi
public LinkAddress(@NonNull InetAddress address, @IntRange(from = 0, to = 128) int prefixLength,
int flags, int scope) {
init(address, prefixLength, flags, scope, LIFETIME_UNKNOWN, LIFETIME_UNKNOWN);
@@ -275,7 +271,6 @@ public class LinkAddress implements Parcelable {
* @hide
*/
@SystemApi
- @TestApi
public LinkAddress(@NonNull InetAddress address, @IntRange(from = 0, to = 128) int prefixLength,
int flags, int scope, long deprecationTime, long expirationTime) {
init(address, prefixLength, flags, scope, deprecationTime, expirationTime);
@@ -289,7 +284,6 @@ public class LinkAddress implements Parcelable {
* @hide
*/
@SystemApi
- @TestApi
public LinkAddress(@NonNull InetAddress address,
@IntRange(from = 0, to = 128) int prefixLength) {
this(address, prefixLength, 0, 0);
@@ -314,7 +308,6 @@ public class LinkAddress implements Parcelable {
* @hide
*/
@SystemApi
- @TestApi
public LinkAddress(@NonNull String address) {
this(address, 0, 0);
this.scope = scopeForUnicastAddress(this.address);
@@ -329,7 +322,6 @@ public class LinkAddress implements Parcelable {
* @hide
*/
@SystemApi
- @TestApi
public LinkAddress(@NonNull String address, int flags, int scope) {
// This may throw an IllegalArgumentException; catching it is the caller's responsibility.
// TODO: consider rejecting mapped IPv4 addresses such as "::ffff:192.0.2.5/24".
@@ -389,7 +381,6 @@ public class LinkAddress implements Parcelable {
* otherwise.
* @hide
*/
- @TestApi
@SystemApi
public boolean isSameAddressAs(@Nullable LinkAddress other) {
if (other == null) {
@@ -469,7 +460,6 @@ public class LinkAddress implements Parcelable {
* @hide
*/
@SystemApi
- @TestApi
public long getDeprecationTime() {
return deprecationTime;
}
@@ -485,7 +475,6 @@ public class LinkAddress implements Parcelable {
* @hide
*/
@SystemApi
- @TestApi
public long getExpirationTime() {
return expirationTime;
}
@@ -496,7 +485,6 @@ public class LinkAddress implements Parcelable {
*
* @hide
*/
- @TestApi
@SystemApi
public boolean isGlobalPreferred() {
/**
diff --git a/core/java/android/net/LinkProperties.java b/core/java/android/net/LinkProperties.java
index 555d7103f697..25a76f43553a 100644
--- a/core/java/android/net/LinkProperties.java
+++ b/core/java/android/net/LinkProperties.java
@@ -19,10 +19,8 @@ package android.net;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.SystemApi;
-import android.annotation.TestApi;
import android.compat.annotation.UnsupportedAppUsage;
import android.net.util.LinkPropertiesUtils;
-import android.net.util.LinkPropertiesUtils.CompareResult;
import android.os.Build;
import android.os.Parcel;
import android.os.Parcelable;
@@ -162,7 +160,6 @@ public final class LinkProperties implements Parcelable {
* @hide
*/
@SystemApi
- @TestApi
public LinkProperties(@Nullable LinkProperties source) {
this(source, false /* parcelSensitiveFields */);
}
@@ -178,7 +175,6 @@ public final class LinkProperties implements Parcelable {
* @hide
*/
@SystemApi
- @TestApi
public LinkProperties(@Nullable LinkProperties source, boolean parcelSensitiveFields) {
mParcelSensitiveFields = parcelSensitiveFields;
if (source == null) return;
@@ -293,7 +289,6 @@ public final class LinkProperties implements Parcelable {
* @hide
*/
@SystemApi
- @TestApi
public boolean addLinkAddress(@NonNull LinkAddress address) {
if (address == null) {
return false;
@@ -322,7 +317,6 @@ public final class LinkProperties implements Parcelable {
* @hide
*/
@SystemApi
- @TestApi
public boolean removeLinkAddress(@NonNull LinkAddress toRemove) {
int i = findLinkAddressIndex(toRemove);
if (i >= 0) {
@@ -376,7 +370,6 @@ public final class LinkProperties implements Parcelable {
* @return true if the DNS server was added, false if it was already present.
* @hide
*/
- @TestApi
@SystemApi
public boolean addDnsServer(@NonNull InetAddress dnsServer) {
if (dnsServer != null && !mDnses.contains(dnsServer)) {
@@ -393,7 +386,6 @@ public final class LinkProperties implements Parcelable {
* @return true if the DNS server was removed, false if it did not exist.
* @hide
*/
- @TestApi
@SystemApi
public boolean removeDnsServer(@NonNull InetAddress dnsServer) {
return mDnses.remove(dnsServer);
@@ -428,7 +420,6 @@ public final class LinkProperties implements Parcelable {
* @param usePrivateDns The private DNS state.
* @hide
*/
- @TestApi
@SystemApi
public void setUsePrivateDns(boolean usePrivateDns) {
mUsePrivateDns = usePrivateDns;
@@ -455,7 +446,6 @@ public final class LinkProperties implements Parcelable {
* @param privateDnsServerName The private DNS server name.
* @hide
*/
- @TestApi
@SystemApi
public void setPrivateDnsServerName(@Nullable String privateDnsServerName) {
mPrivateDnsServerName = privateDnsServerName;
@@ -534,7 +524,6 @@ public final class LinkProperties implements Parcelable {
* object.
* @hide
*/
- @TestApi
@SystemApi
public void setValidatedPrivateDnsServers(@NonNull Collection<InetAddress> dnsServers) {
mValidatedPrivateDnses.clear();
@@ -551,7 +540,6 @@ public final class LinkProperties implements Parcelable {
* DNS servers on this link.
* @hide
*/
- @TestApi
@SystemApi
public @NonNull List<InetAddress> getValidatedPrivateDnsServers() {
return Collections.unmodifiableList(mValidatedPrivateDnses);
@@ -592,7 +580,6 @@ public final class LinkProperties implements Parcelable {
* @hide
*/
@SystemApi
- @TestApi
public void setPcscfServers(@NonNull Collection<InetAddress> pcscfServers) {
mPcscfs.clear();
for (InetAddress pcscfServer: pcscfServers) {
@@ -608,7 +595,6 @@ public final class LinkProperties implements Parcelable {
* @hide
*/
@SystemApi
- @TestApi
public @NonNull List<InetAddress> getPcscfServers() {
return Collections.unmodifiableList(mPcscfs);
}
@@ -662,7 +648,6 @@ public final class LinkProperties implements Parcelable {
*
* @hide
*/
- @TestApi
@SystemApi
public void setTcpBufferSizes(@Nullable String tcpBufferSizes) {
mTcpBufferSizes = tcpBufferSizes;
@@ -675,7 +660,6 @@ public final class LinkProperties implements Parcelable {
*
* @hide
*/
- @TestApi
@SystemApi
public @Nullable String getTcpBufferSizes() {
return mTcpBufferSizes;
@@ -744,7 +728,6 @@ public final class LinkProperties implements Parcelable {
*
* @hide
*/
- @TestApi
@SystemApi
public boolean removeRoute(@NonNull RouteInfo route) {
return Objects.equals(mIfaceName, route.getInterface()) && mRoutes.remove(route);
@@ -1021,7 +1004,6 @@ public final class LinkProperties implements Parcelable {
* @return {@code true} if there is an IPv4 address, {@code false} otherwise.
* @hide
*/
- @TestApi
@SystemApi
public boolean hasIpv4Address() {
for (LinkAddress address : mLinkAddresses) {
@@ -1062,7 +1044,6 @@ public final class LinkProperties implements Parcelable {
* @return {@code true} if there is a global preferred IPv6 address, {@code false} otherwise.
* @hide
*/
- @TestApi
@SystemApi
public boolean hasGlobalIpv6Address() {
for (LinkAddress address : mLinkAddresses) {
@@ -1149,7 +1130,6 @@ public final class LinkProperties implements Parcelable {
* @return {@code true} if there is an IPv6 default route, {@code false} otherwise.
* @hide
*/
- @TestApi
@SystemApi
public boolean hasIpv6DefaultRoute() {
for (RouteInfo r : mRoutes) {
@@ -1265,7 +1245,6 @@ public final class LinkProperties implements Parcelable {
* @return {@code true} if the link is provisioned, {@code false} otherwise.
* @hide
*/
- @TestApi
@SystemApi
public boolean isIpv4Provisioned() {
return (hasIpv4Address()
@@ -1280,7 +1259,6 @@ public final class LinkProperties implements Parcelable {
* @return {@code true} if the link is provisioned, {@code false} otherwise.
* @hide
*/
- @TestApi
@SystemApi
public boolean isIpv6Provisioned() {
return (hasGlobalIpv6Address()
@@ -1308,7 +1286,6 @@ public final class LinkProperties implements Parcelable {
* @return {@code true} if the link is provisioned, {@code false} otherwise.
* @hide
*/
- @TestApi
@SystemApi
public boolean isProvisioned() {
return (isIpv4Provisioned() || isIpv6Provisioned());
@@ -1321,7 +1298,6 @@ public final class LinkProperties implements Parcelable {
* {@code false} otherwise.
* @hide
*/
- @TestApi
@SystemApi
public boolean isReachable(@NonNull InetAddress ip) {
final List<RouteInfo> allRoutes = getAllRoutes();
@@ -1578,7 +1554,6 @@ public final class LinkProperties implements Parcelable {
* @hide
*/
@SystemApi
- @TestApi
public void setCaptivePortalApiUrl(@Nullable Uri url) {
mCaptivePortalApiUrl = url;
}
@@ -1593,7 +1568,6 @@ public final class LinkProperties implements Parcelable {
* @hide
*/
@SystemApi
- @TestApi
@Nullable
public Uri getCaptivePortalApiUrl() {
return mCaptivePortalApiUrl;
@@ -1604,7 +1578,6 @@ public final class LinkProperties implements Parcelable {
* @hide
*/
@SystemApi
- @TestApi
public void setCaptivePortalData(@Nullable CaptivePortalData data) {
mCaptivePortalData = data;
}
@@ -1618,7 +1591,6 @@ public final class LinkProperties implements Parcelable {
* @hide
*/
@SystemApi
- @TestApi
@Nullable
public CaptivePortalData getCaptivePortalData() {
return mCaptivePortalData;
@@ -1669,78 +1641,6 @@ public final class LinkProperties implements Parcelable {
}
/**
- * Compares the DNS addresses in this LinkProperties with another
- * LinkProperties, examining only DNS addresses on the base link.
- *
- * @param target a LinkProperties with the new list of dns addresses
- * @return the differences between the DNS addresses.
- * @hide
- */
- public @NonNull CompareResult<InetAddress> compareDnses(@Nullable LinkProperties target) {
- /*
- * Duplicate the InetAddresses into removed, we will be removing
- * dns address which are common between mDnses and target
- * leaving the addresses that are different. And dns address which
- * are in target but not in mDnses are placed in the
- * addedAddresses.
- */
- return new CompareResult<>(mDnses, target != null ? target.getDnsServers() : null);
- }
-
- /**
- * Compares the validated private DNS addresses in this LinkProperties with another
- * LinkProperties.
- *
- * @param target a LinkProperties with the new list of validated private dns addresses
- * @return the differences between the DNS addresses.
- * @hide
- */
- public @NonNull CompareResult<InetAddress> compareValidatedPrivateDnses(
- @Nullable LinkProperties target) {
- return new CompareResult<>(mValidatedPrivateDnses,
- target != null ? target.getValidatedPrivateDnsServers() : null);
- }
-
- /**
- * Compares all routes in this LinkProperties with another LinkProperties,
- * examining both the the base link and all stacked links.
- *
- * @param target a LinkProperties with the new list of routes
- * @return the differences between the routes.
- * @hide
- */
- public @NonNull CompareResult<RouteInfo> compareAllRoutes(@Nullable LinkProperties target) {
- /*
- * Duplicate the RouteInfos into removed, we will be removing
- * routes which are common between mRoutes and target
- * leaving the routes that are different. And route address which
- * are in target but not in mRoutes are placed in added.
- */
- return new CompareResult<>(getAllRoutes(), target != null ? target.getAllRoutes() : null);
- }
-
- /**
- * Compares all interface names in this LinkProperties with another
- * LinkProperties, examining both the the base link and all stacked links.
- *
- * @param target a LinkProperties with the new list of interface names
- * @return the differences between the interface names.
- * @hide
- */
- public @NonNull CompareResult<String> compareAllInterfaceNames(
- @Nullable LinkProperties target) {
- /*
- * Duplicate the interface names into removed, we will be removing
- * interface names which are common between this and target
- * leaving the interface names that are different. And interface names which
- * are in target but not in this are placed in added.
- */
- return new CompareResult<>(getAllInterfaceNames(),
- target != null ? target.getAllInterfaceNames() : null);
- }
-
-
- /**
* Generate hashcode based on significant fields
*
* Equal objects must produce the same hash code, while unequal objects
diff --git a/core/java/android/net/Network.java b/core/java/android/net/Network.java
index 10ee72e48ecc..3e4f73555e58 100644
--- a/core/java/android/net/Network.java
+++ b/core/java/android/net/Network.java
@@ -19,7 +19,6 @@ package android.net;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.SystemApi;
-import android.annotation.TestApi;
import android.compat.annotation.UnsupportedAppUsage;
import android.os.Parcel;
import android.os.Parcelable;
@@ -128,7 +127,6 @@ public class Network implements Parcelable {
* @hide
*/
@SystemApi
- @TestApi
public Network(@NonNull Network that) {
this(that.netId, that.mPrivateDnsBypass);
}
@@ -165,7 +163,6 @@ public class Network implements Parcelable {
*
* @hide
*/
- @TestApi
@SystemApi
public @NonNull Network getPrivateDnsBypassingCopy() {
return new Network(netId, true);
@@ -176,7 +173,6 @@ public class Network implements Parcelable {
*
* @hide
*/
- @TestApi
@SystemApi
public int getNetId() {
return netId;
diff --git a/core/java/android/net/NetworkCapabilities.java b/core/java/android/net/NetworkCapabilities.java
index 004f84422b44..be33f4edb5d1 100644
--- a/core/java/android/net/NetworkCapabilities.java
+++ b/core/java/android/net/NetworkCapabilities.java
@@ -850,7 +850,6 @@ public final class NetworkCapabilities implements Parcelable {
* @return an array of transport type values for this instance.
* @hide
*/
- @TestApi
@SystemApi
@NonNull public @Transport int[] getTransportTypes() {
return BitUtils.unpackBits(mTransportTypes);
@@ -1025,7 +1024,6 @@ public final class NetworkCapabilities implements Parcelable {
*/
@NonNull
@SystemApi
- @TestApi
public int[] getAdministratorUids() {
return Arrays.copyOf(mAdministratorUids, mAdministratorUids.length);
}
@@ -1506,7 +1504,6 @@ public final class NetworkCapabilities implements Parcelable {
* @hide
*/
@SystemApi
- @TestApi
public @Nullable String getSsid() {
return mSSID;
}
@@ -1590,7 +1587,6 @@ public final class NetworkCapabilities implements Parcelable {
*
* @hide
*/
- @TestApi
@SystemApi
public boolean satisfiedByNetworkCapabilities(@Nullable NetworkCapabilities nc) {
return satisfiedByNetworkCapabilities(nc, false);
@@ -2136,7 +2132,6 @@ public final class NetworkCapabilities implements Parcelable {
* @hide
*/
@SystemApi
- @TestApi
public static final class Builder {
private final NetworkCapabilities mCaps;
diff --git a/core/java/android/net/NetworkStack.java b/core/java/android/net/NetworkStack.java
index 86f3dfd412f6..79f9e6ef2a97 100644
--- a/core/java/android/net/NetworkStack.java
+++ b/core/java/android/net/NetworkStack.java
@@ -33,7 +33,6 @@ import java.util.Arrays;
* @hide
*/
@SystemApi
-@TestApi
public class NetworkStack {
/**
* Permission granted only to the NetworkStack APK, defined in NetworkStackStub with signature
@@ -41,7 +40,6 @@ public class NetworkStack {
* @hide
*/
@SystemApi
- @TestApi
public static final String PERMISSION_MAINLINE_NETWORK_STACK =
"android.permission.MAINLINE_NETWORK_STACK";
@@ -54,7 +52,6 @@ public class NetworkStack {
*/
@Nullable
@SystemApi
- @TestApi
public static IBinder getService() {
final IBinder mockService = sMockService;
if (mockService != null) return mockService;
diff --git a/core/java/android/net/RouteInfo.java b/core/java/android/net/RouteInfo.java
index d9568756bbac..93ad41f7c524 100644
--- a/core/java/android/net/RouteInfo.java
+++ b/core/java/android/net/RouteInfo.java
@@ -20,7 +20,6 @@ import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.SystemApi;
-import android.annotation.TestApi;
import android.compat.annotation.UnsupportedAppUsage;
import android.net.util.NetUtils;
import android.os.Build;
@@ -87,17 +86,14 @@ public final class RouteInfo implements Parcelable {
/** Unicast route. @hide */
@SystemApi
- @TestApi
public static final int RTN_UNICAST = 1;
/** Unreachable route. @hide */
@SystemApi
- @TestApi
public static final int RTN_UNREACHABLE = 7;
/** Throw route. @hide */
@SystemApi
- @TestApi
public static final int RTN_THROW = 9;
/**
@@ -135,7 +131,6 @@ public final class RouteInfo implements Parcelable {
* @hide
*/
@SystemApi
- @TestApi
public RouteInfo(@Nullable IpPrefix destination, @Nullable InetAddress gateway,
@Nullable String iface, @RouteType int type) {
this(destination, gateway, iface, type, 0);
@@ -397,7 +392,6 @@ public final class RouteInfo implements Parcelable {
*
* @hide
*/
- @TestApi
@SystemApi
@RouteType
public int getType() {
diff --git a/core/java/android/net/StaticIpConfiguration.java b/core/java/android/net/StaticIpConfiguration.java
index a973455baa04..f56d656f07ed 100644
--- a/core/java/android/net/StaticIpConfiguration.java
+++ b/core/java/android/net/StaticIpConfiguration.java
@@ -19,7 +19,6 @@ package android.net;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.SystemApi;
-import android.annotation.TestApi;
import android.compat.annotation.UnsupportedAppUsage;
import android.os.Parcel;
import android.os.Parcelable;
@@ -52,7 +51,6 @@ import java.util.Objects;
* @hide
*/
@SystemApi
-@TestApi
public final class StaticIpConfiguration implements Parcelable {
/** @hide */
@UnsupportedAppUsage
diff --git a/core/java/android/net/apf/ApfCapabilities.java b/core/java/android/net/apf/ApfCapabilities.java
index 92c543294ae1..bf5b26e278f9 100644
--- a/core/java/android/net/apf/ApfCapabilities.java
+++ b/core/java/android/net/apf/ApfCapabilities.java
@@ -19,7 +19,6 @@ package android.net.apf;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.SystemApi;
-import android.annotation.TestApi;
import android.content.res.Resources;
import android.os.Parcel;
import android.os.Parcelable;
@@ -36,7 +35,6 @@ import com.android.internal.R;
* @hide
*/
@SystemApi
-@TestApi
public final class ApfCapabilities implements Parcelable {
/**
* Version of APF instruction set supported for packet filtering. 0 indicates no support for
diff --git a/core/java/android/net/metrics/ApfProgramEvent.java b/core/java/android/net/metrics/ApfProgramEvent.java
index f93907a37f3f..c50bae90488b 100644
--- a/core/java/android/net/metrics/ApfProgramEvent.java
+++ b/core/java/android/net/metrics/ApfProgramEvent.java
@@ -20,7 +20,6 @@ import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.SystemApi;
-import android.annotation.TestApi;
import android.compat.annotation.UnsupportedAppUsage;
import android.os.Parcel;
import android.os.Parcelable;
@@ -40,7 +39,6 @@ import java.util.List;
* the APF program in place with a new APF program.
* {@hide}
*/
-@TestApi
@SystemApi
public final class ApfProgramEvent implements IpConnectivityLog.Event {
diff --git a/core/java/android/net/metrics/ApfStats.java b/core/java/android/net/metrics/ApfStats.java
index b221cb97b28f..2a601b273ef4 100644
--- a/core/java/android/net/metrics/ApfStats.java
+++ b/core/java/android/net/metrics/ApfStats.java
@@ -19,7 +19,6 @@ package android.net.metrics;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.SystemApi;
-import android.annotation.TestApi;
import android.compat.annotation.UnsupportedAppUsage;
import android.os.Parcel;
import android.os.Parcelable;
@@ -29,7 +28,6 @@ import android.os.Parcelable;
* {@hide}
*/
@SystemApi
-@TestApi
public final class ApfStats implements IpConnectivityLog.Event {
/**
@@ -126,7 +124,6 @@ public final class ApfStats implements IpConnectivityLog.Event {
* @hide
*/
@SystemApi
- @TestApi
public static final class Builder {
private long mDurationMs;
private int mReceivedRas;
diff --git a/core/java/android/net/metrics/DhcpClientEvent.java b/core/java/android/net/metrics/DhcpClientEvent.java
index 8fc1ef80bba9..e0a93dd1c18f 100644
--- a/core/java/android/net/metrics/DhcpClientEvent.java
+++ b/core/java/android/net/metrics/DhcpClientEvent.java
@@ -19,7 +19,6 @@ package android.net.metrics;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.SystemApi;
-import android.annotation.TestApi;
import android.compat.annotation.UnsupportedAppUsage;
import android.os.Parcel;
import android.os.Parcelable;
@@ -30,7 +29,6 @@ import android.text.TextUtils;
* {@hide}
*/
@SystemApi
-@TestApi
public final class DhcpClientEvent implements IpConnectivityLog.Event {
// Names for recording DhcpClient pseudo-state transitions.
diff --git a/core/java/android/net/metrics/DhcpErrorEvent.java b/core/java/android/net/metrics/DhcpErrorEvent.java
index 32efb5adafcd..de3129d5e94d 100644
--- a/core/java/android/net/metrics/DhcpErrorEvent.java
+++ b/core/java/android/net/metrics/DhcpErrorEvent.java
@@ -18,7 +18,6 @@ package android.net.metrics;
import android.annotation.NonNull;
import android.annotation.SystemApi;
-import android.annotation.TestApi;
import android.os.Parcel;
import android.os.Parcelable;
import android.util.SparseArray;
@@ -30,7 +29,6 @@ import com.android.internal.util.MessageUtils;
* {@hide}
*/
@SystemApi
-@TestApi
public final class DhcpErrorEvent implements IpConnectivityLog.Event {
public static final int L2_ERROR = 1;
public static final int L3_ERROR = 2;
diff --git a/core/java/android/net/metrics/IpConnectivityLog.java b/core/java/android/net/metrics/IpConnectivityLog.java
index 680c01573f98..a008d855025a 100644
--- a/core/java/android/net/metrics/IpConnectivityLog.java
+++ b/core/java/android/net/metrics/IpConnectivityLog.java
@@ -18,7 +18,6 @@ package android.net.metrics;
import android.annotation.NonNull;
import android.annotation.SystemApi;
-import android.annotation.TestApi;
import android.net.ConnectivityMetricsEvent;
import android.net.IIpConnectivityMetrics;
import android.net.Network;
@@ -35,7 +34,6 @@ import com.android.internal.util.BitUtils;
* {@hide}
*/
@SystemApi
-@TestApi
public class IpConnectivityLog {
private static final String TAG = IpConnectivityLog.class.getSimpleName();
private static final boolean DBG = false;
@@ -52,7 +50,6 @@ public class IpConnectivityLog {
/** @hide */
@SystemApi
- @TestApi
public IpConnectivityLog() {
}
diff --git a/core/java/android/net/metrics/IpManagerEvent.java b/core/java/android/net/metrics/IpManagerEvent.java
index f14abb895cb4..4f7f3263117b 100644
--- a/core/java/android/net/metrics/IpManagerEvent.java
+++ b/core/java/android/net/metrics/IpManagerEvent.java
@@ -20,7 +20,6 @@ import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.SystemApi;
-import android.annotation.TestApi;
import android.os.Parcel;
import android.os.Parcelable;
import android.util.SparseArray;
@@ -36,7 +35,6 @@ import java.lang.annotation.RetentionPolicy;
* {@hide}
*/
@SystemApi
-@TestApi
public final class IpManagerEvent implements IpConnectivityLog.Event {
public static final int PROVISIONING_OK = 1;
diff --git a/core/java/android/net/metrics/IpReachabilityEvent.java b/core/java/android/net/metrics/IpReachabilityEvent.java
index 79e01d7116b6..d5003badd614 100644
--- a/core/java/android/net/metrics/IpReachabilityEvent.java
+++ b/core/java/android/net/metrics/IpReachabilityEvent.java
@@ -19,7 +19,6 @@ package android.net.metrics;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.SystemApi;
-import android.annotation.TestApi;
import android.os.Parcel;
import android.os.Parcelable;
import android.util.SparseArray;
@@ -32,7 +31,6 @@ import com.android.internal.util.MessageUtils;
* {@hide}
*/
@SystemApi
-@TestApi
public final class IpReachabilityEvent implements IpConnectivityLog.Event {
// Event types.
diff --git a/core/java/android/net/metrics/NetworkEvent.java b/core/java/android/net/metrics/NetworkEvent.java
index fe603cf9305c..8c28f7a7d643 100644
--- a/core/java/android/net/metrics/NetworkEvent.java
+++ b/core/java/android/net/metrics/NetworkEvent.java
@@ -20,7 +20,6 @@ import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.SystemApi;
-import android.annotation.TestApi;
import android.os.Parcel;
import android.os.Parcelable;
import android.util.SparseArray;
@@ -34,7 +33,6 @@ import java.lang.annotation.RetentionPolicy;
* {@hide}
*/
@SystemApi
-@TestApi
public final class NetworkEvent implements IpConnectivityLog.Event {
public static final int NETWORK_CONNECTED = 1;
diff --git a/core/java/android/net/metrics/RaEvent.java b/core/java/android/net/metrics/RaEvent.java
index 661f648fc74e..b54874f5a573 100644
--- a/core/java/android/net/metrics/RaEvent.java
+++ b/core/java/android/net/metrics/RaEvent.java
@@ -19,7 +19,6 @@ package android.net.metrics;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.SystemApi;
-import android.annotation.TestApi;
import android.os.Parcel;
import android.os.Parcelable;
@@ -28,7 +27,6 @@ import android.os.Parcelable;
* {@hide}
*/
@SystemApi
-@TestApi
public final class RaEvent implements IpConnectivityLog.Event {
private static final long NO_LIFETIME = -1L;
diff --git a/core/java/android/net/metrics/ValidationProbeEvent.java b/core/java/android/net/metrics/ValidationProbeEvent.java
index 8fab64ae6c4e..7f4e4a73677e 100644
--- a/core/java/android/net/metrics/ValidationProbeEvent.java
+++ b/core/java/android/net/metrics/ValidationProbeEvent.java
@@ -20,7 +20,6 @@ import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.SystemApi;
-import android.annotation.TestApi;
import android.os.Parcel;
import android.os.Parcelable;
import android.util.SparseArray;
@@ -35,7 +34,6 @@ import java.lang.annotation.RetentionPolicy;
* {@hide}
*/
@SystemApi
-@TestApi
public final class ValidationProbeEvent implements IpConnectivityLog.Event {
public static final int PROBE_DNS = 0;
diff --git a/core/java/android/net/util/SocketUtils.java b/core/java/android/net/util/SocketUtils.java
index 696708408c22..e64060f1b220 100644
--- a/core/java/android/net/util/SocketUtils.java
+++ b/core/java/android/net/util/SocketUtils.java
@@ -22,7 +22,6 @@ import static android.system.OsConstants.SO_BINDTODEVICE;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.SystemApi;
-import android.annotation.TestApi;
import android.net.NetworkUtils;
import android.system.ErrnoException;
import android.system.NetlinkSocketAddress;
@@ -40,7 +39,6 @@ import java.net.SocketAddress;
* @hide
*/
@SystemApi
-@TestApi
public final class SocketUtils {
/**
* Create a raw datagram socket that is bound to an interface.
diff --git a/core/java/android/os/BatteryManager.java b/core/java/android/os/BatteryManager.java
index 12ec0a0c21d5..9a16d3fee600 100644
--- a/core/java/android/os/BatteryManager.java
+++ b/core/java/android/os/BatteryManager.java
@@ -20,7 +20,6 @@ import android.Manifest.permission;
import android.annotation.RequiresPermission;
import android.annotation.SystemApi;
import android.annotation.SystemService;
-import android.annotation.TestApi;
import android.compat.annotation.UnsupportedAppUsage;
import android.content.Context;
import android.content.Intent;
@@ -392,7 +391,6 @@ public class BatteryManager {
*/
@RequiresPermission(permission.POWER_SAVER)
@SystemApi
- @TestApi
public boolean setChargingStateUpdateDelayMillis(int delayMillis) {
try {
return mBatteryStats.setChargingStateUpdateDelayMillis(delayMillis);
diff --git a/core/java/android/os/BatteryStats.java b/core/java/android/os/BatteryStats.java
index 88525895d9ec..b550c7d4ba81 100644
--- a/core/java/android/os/BatteryStats.java
+++ b/core/java/android/os/BatteryStats.java
@@ -4049,7 +4049,8 @@ public abstract class BatteryStats implements Parcelable {
if (cpuFreqs != null) {
sb.setLength(0);
for (int i = 0; i < cpuFreqs.length; ++i) {
- sb.append((i == 0 ? "" : ",") + cpuFreqs[i]);
+ if (i != 0) sb.append(',');
+ sb.append(cpuFreqs[i]);
}
dumpLine(pw, 0 /* uid */, category, GLOBAL_CPU_FREQ_DATA, sb.toString());
}
@@ -4368,12 +4369,13 @@ public abstract class BatteryStats implements Parcelable {
if (cpuFreqTimeMs != null && cpuFreqTimeMs.length == cpuFreqs.length) {
sb.setLength(0);
for (int i = 0; i < cpuFreqTimeMs.length; ++i) {
- sb.append((i == 0 ? "" : ",") + cpuFreqTimeMs[i]);
+ if (i != 0) sb.append(',');
+ sb.append(cpuFreqTimeMs[i]);
}
final long[] screenOffCpuFreqTimeMs = u.getScreenOffCpuFreqTimes(which);
if (screenOffCpuFreqTimeMs != null) {
for (int i = 0; i < screenOffCpuFreqTimeMs.length; ++i) {
- sb.append("," + screenOffCpuFreqTimeMs[i]);
+ sb.append(',').append(screenOffCpuFreqTimeMs[i]);
}
} else {
for (int i = 0; i < cpuFreqTimeMs.length; ++i) {
@@ -4389,13 +4391,14 @@ public abstract class BatteryStats implements Parcelable {
if (timesMs != null && timesMs.length == cpuFreqs.length) {
sb.setLength(0);
for (int i = 0; i < timesMs.length; ++i) {
- sb.append((i == 0 ? "" : ",") + timesMs[i]);
+ if (i != 0) sb.append(',');
+ sb.append(timesMs[i]);
}
final long[] screenOffTimesMs = u.getScreenOffCpuFreqTimes(
which, procState);
if (screenOffTimesMs != null) {
for (int i = 0; i < screenOffTimesMs.length; ++i) {
- sb.append("," + screenOffTimesMs[i]);
+ sb.append(',').append(screenOffTimesMs[i]);
}
} else {
for (int i = 0; i < timesMs.length; ++i) {
@@ -5427,7 +5430,7 @@ public abstract class BatteryStats implements Parcelable {
sb.setLength(0);
sb.append(" CPU freqs:");
for (int i = 0; i < cpuFreqs.length; ++i) {
- sb.append(" " + cpuFreqs[i]);
+ sb.append(' ').append(cpuFreqs[i]);
}
pw.println(sb.toString());
pw.println();
@@ -6036,7 +6039,7 @@ public abstract class BatteryStats implements Parcelable {
sb.setLength(0);
sb.append(" Total cpu time per freq:");
for (int i = 0; i < cpuFreqTimes.length; ++i) {
- sb.append(" " + cpuFreqTimes[i]);
+ sb.append(' ').append(cpuFreqTimes[i]);
}
pw.println(sb.toString());
}
@@ -6045,7 +6048,7 @@ public abstract class BatteryStats implements Parcelable {
sb.setLength(0);
sb.append(" Total screen-off cpu time per freq:");
for (int i = 0; i < screenOffCpuFreqTimes.length; ++i) {
- sb.append(" " + screenOffCpuFreqTimes[i]);
+ sb.append(' ').append(screenOffCpuFreqTimes[i]);
}
pw.println(sb.toString());
}
@@ -6054,8 +6057,8 @@ public abstract class BatteryStats implements Parcelable {
final long[] cpuTimes = u.getCpuFreqTimes(which, procState);
if (cpuTimes != null) {
sb.setLength(0);
- sb.append(" Cpu times per freq at state "
- + Uid.PROCESS_STATE_NAMES[procState] + ":");
+ sb.append(" Cpu times per freq at state ")
+ .append(Uid.PROCESS_STATE_NAMES[procState]).append(':');
for (int i = 0; i < cpuTimes.length; ++i) {
sb.append(" " + cpuTimes[i]);
}
@@ -6065,8 +6068,8 @@ public abstract class BatteryStats implements Parcelable {
final long[] screenOffCpuTimes = u.getScreenOffCpuFreqTimes(which, procState);
if (screenOffCpuTimes != null) {
sb.setLength(0);
- sb.append(" Screen-off cpu times per freq at state "
- + Uid.PROCESS_STATE_NAMES[procState] + ":");
+ sb.append(" Screen-off cpu times per freq at state ")
+ .append(Uid.PROCESS_STATE_NAMES[procState]).append(':');
for (int i = 0; i < screenOffCpuTimes.length; ++i) {
sb.append(" " + screenOffCpuTimes[i]);
}
diff --git a/core/java/android/os/Binder.java b/core/java/android/os/Binder.java
index d492e0870b2e..fce3437db049 100644
--- a/core/java/android/os/Binder.java
+++ b/core/java/android/os/Binder.java
@@ -379,6 +379,7 @@ public class Binder implements IBinder {
*
* @see #clearCallingIdentity
*/
+ @CriticalNative
public static final native void restoreCallingIdentity(long token);
/**
diff --git a/core/java/android/os/BugreportManager.java b/core/java/android/os/BugreportManager.java
index 9e996d15fa84..fe4d7296503f 100644
--- a/core/java/android/os/BugreportManager.java
+++ b/core/java/android/os/BugreportManager.java
@@ -24,13 +24,13 @@ import android.annotation.Nullable;
import android.annotation.RequiresPermission;
import android.annotation.SystemApi;
import android.annotation.SystemService;
-import android.annotation.TestApi;
import android.app.ActivityManager;
import android.content.Context;
import android.content.Intent;
import android.os.Handler;
import android.util.Log;
import android.widget.Toast;
+
import com.android.internal.R;
import com.android.internal.util.Preconditions;
@@ -48,7 +48,6 @@ import java.util.concurrent.Executor;
* @hide
*/
@SystemApi
-@TestApi
@SystemService(Context.BUGREPORT_SERVICE)
public final class BugreportManager {
diff --git a/core/java/android/os/BugreportParams.java b/core/java/android/os/BugreportParams.java
index c834781346f6..279ccae7c94f 100644
--- a/core/java/android/os/BugreportParams.java
+++ b/core/java/android/os/BugreportParams.java
@@ -18,7 +18,6 @@ package android.os;
import android.annotation.IntDef;
import android.annotation.SystemApi;
-import android.annotation.TestApi;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
@@ -29,7 +28,6 @@ import java.lang.annotation.RetentionPolicy;
* @hide
*/
@SystemApi
-@TestApi
public final class BugreportParams {
private final int mMode;
diff --git a/core/java/android/os/Debug.java b/core/java/android/os/Debug.java
index a2e53e29193c..4fed93204f59 100644
--- a/core/java/android/os/Debug.java
+++ b/core/java/android/os/Debug.java
@@ -2468,7 +2468,7 @@ public final class Debug
@UnsupportedAppUsage
public static String getCallers(final int depth) {
final StackTraceElement[] callStack = Thread.currentThread().getStackTrace();
- StringBuffer sb = new StringBuffer();
+ StringBuilder sb = new StringBuilder();
for (int i = 0; i < depth; i++) {
sb.append(getCaller(callStack, i)).append(" ");
}
@@ -2483,7 +2483,7 @@ public final class Debug
*/
public static String getCallers(final int start, int depth) {
final StackTraceElement[] callStack = Thread.currentThread().getStackTrace();
- StringBuffer sb = new StringBuffer();
+ StringBuilder sb = new StringBuilder();
depth += start;
for (int i = start; i < depth; i++) {
sb.append(getCaller(callStack, i)).append(" ");
@@ -2501,7 +2501,7 @@ public final class Debug
*/
public static String getCallers(final int depth, String linePrefix) {
final StackTraceElement[] callStack = Thread.currentThread().getStackTrace();
- StringBuffer sb = new StringBuffer();
+ StringBuilder sb = new StringBuilder();
for (int i = 0; i < depth; i++) {
sb.append(linePrefix).append(getCaller(callStack, i)).append("\n");
}
diff --git a/core/java/android/os/Environment.java b/core/java/android/os/Environment.java
index 085681d412e9..5745187fcbb9 100644
--- a/core/java/android/os/Environment.java
+++ b/core/java/android/os/Environment.java
@@ -256,7 +256,6 @@ public class Environment {
* @hide
*/
@SystemApi
- @TestApi
public static @NonNull File getOemDirectory() {
return DIR_OEM_ROOT;
}
@@ -268,7 +267,6 @@ public class Environment {
* @hide
*/
@SystemApi
- @TestApi
public static @NonNull File getOdmDirectory() {
return DIR_ODM_ROOT;
}
@@ -279,7 +277,6 @@ public class Environment {
* @hide
*/
@SystemApi
- @TestApi
public static @NonNull File getVendorDirectory() {
return DIR_VENDOR_ROOT;
}
@@ -291,7 +288,6 @@ public class Environment {
* @hide
*/
@SystemApi
- @TestApi
public static @NonNull File getProductDirectory() {
return DIR_PRODUCT_ROOT;
}
@@ -318,7 +314,6 @@ public class Environment {
* @hide
*/
@SystemApi
- @TestApi
public static @NonNull File getSystemExtDirectory() {
return DIR_SYSTEM_EXT_ROOT;
}
diff --git a/core/java/android/os/FileObserver.java b/core/java/android/os/FileObserver.java
index ca303d973235..25bffbc9e8d5 100644
--- a/core/java/android/os/FileObserver.java
+++ b/core/java/android/os/FileObserver.java
@@ -21,6 +21,7 @@ import android.annotation.NonNull;
import android.annotation.Nullable;
import android.compat.annotation.UnsupportedAppUsage;
import android.util.Log;
+import android.util.SparseArray;
import java.io.File;
import java.lang.annotation.Retention;
@@ -101,7 +102,9 @@ public abstract class FileObserver {
private static final String LOG_TAG = "FileObserver";
private static class ObserverThread extends Thread {
+ /** Temporarily retained; appears to be missing UnsupportedAppUsage annotation */
private HashMap<Integer, WeakReference> m_observers = new HashMap<Integer, WeakReference>();
+ private SparseArray<WeakReference> mRealObservers = new SparseArray<>();
private int m_fd;
public ObserverThread() {
@@ -127,10 +130,10 @@ public abstract class FileObserver {
final WeakReference<FileObserver> fileObserverWeakReference =
new WeakReference<>(observer);
- synchronized (m_observers) {
+ synchronized (mRealObservers) {
for (int wfd : wfds) {
if (wfd >= 0) {
- m_observers.put(wfd, fileObserverWeakReference);
+ mRealObservers.put(wfd, fileObserverWeakReference);
}
}
}
@@ -147,12 +150,12 @@ public abstract class FileObserver {
// look up our observer, fixing up the map if necessary...
FileObserver observer = null;
- synchronized (m_observers) {
- WeakReference weak = m_observers.get(wfd);
+ synchronized (mRealObservers) {
+ WeakReference weak = mRealObservers.get(wfd);
if (weak != null) { // can happen with lots of events from a dead wfd
observer = (FileObserver) weak.get();
if (observer == null) {
- m_observers.remove(wfd);
+ mRealObservers.remove(wfd);
}
}
}
diff --git a/core/java/android/os/FileUtils.java b/core/java/android/os/FileUtils.java
index 70c924a46c17..bbafc7b0875a 100644
--- a/core/java/android/os/FileUtils.java
+++ b/core/java/android/os/FileUtils.java
@@ -40,9 +40,16 @@ import static android.system.OsConstants.W_OK;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.TestApi;
+import android.app.AppGlobals;
import android.compat.annotation.UnsupportedAppUsage;
import android.content.ContentResolver;
+import android.content.Context;
+import android.content.pm.PackageManager;
+import android.content.pm.ProviderInfo;
+import android.content.res.AssetFileDescriptor;
+import android.net.Uri;
import android.provider.DocumentsContract.Document;
+import android.provider.MediaStore;
import android.system.ErrnoException;
import android.system.Os;
import android.system.StructStat;
@@ -118,6 +125,7 @@ public final class FileUtils {
// non-final so it can be toggled by Robolectric's ShadowFileUtils
private static boolean sEnableCopyOptimizations = true;
+ private static volatile int sMediaProviderAppId = -1;
private static final long COPY_CHECKPOINT_BYTES = 524288;
@@ -1425,6 +1433,54 @@ public final class FileUtils {
}
/** {@hide} */
+ public static FileDescriptor convertToModernFd(FileDescriptor fd) {
+ try {
+ Context context = AppGlobals.getInitialApplication();
+ if (UserHandle.getAppId(Process.myUid()) == getMediaProviderAppId(context)) {
+ // Never convert modern fd for MediaProvider, because this requires
+ // MediaStore#scanFile and can cause infinite loops when MediaProvider scans
+ return null;
+ }
+ File realFile = ParcelFileDescriptor.getFile(fd);
+ Log.i(TAG, "Changing to modern format dataSource for: " + realFile);
+ ContentResolver resolver = context.getContentResolver();
+
+ Uri uri = MediaStore.scanFile(resolver, realFile);
+ if (uri != null) {
+ Bundle opts = new Bundle();
+ // TODO(b/158465539): Use API constant
+ opts.putBoolean("android.provider.extra.ACCEPT_ORIGINAL_MEDIA_FORMAT", true);
+ AssetFileDescriptor afd = resolver.openTypedAssetFileDescriptor(uri, "*/*", opts);
+ Log.i(TAG, "Changed to modern format dataSource for: " + realFile);
+ return afd.getFileDescriptor();
+ } else {
+ Log.i(TAG, "Failed to change to modern format dataSource for: " + realFile);
+ }
+ } catch (Exception e) {
+ Log.w(TAG, "Failed to change to modern format dataSource");
+ }
+ return null;
+ }
+
+ private static int getMediaProviderAppId(Context context) {
+ if (sMediaProviderAppId != -1) {
+ return sMediaProviderAppId;
+ }
+
+ PackageManager pm = context.getPackageManager();
+ ProviderInfo provider = context.getPackageManager().resolveContentProvider(
+ MediaStore.AUTHORITY, PackageManager.MATCH_DIRECT_BOOT_AWARE
+ | PackageManager.MATCH_DIRECT_BOOT_UNAWARE
+ | PackageManager.MATCH_SYSTEM_ONLY);
+ if (provider == null) {
+ return -1;
+ }
+
+ sMediaProviderAppId = UserHandle.getAppId(provider.applicationInfo.uid);
+ return sMediaProviderAppId;
+ }
+
+ /** {@hide} */
@VisibleForTesting
public static class MemoryPipe extends Thread implements AutoCloseable {
private final FileDescriptor[] pipe;
diff --git a/core/java/android/os/GraphicsEnvironment.java b/core/java/android/os/GraphicsEnvironment.java
index 6ba1627dde47..be21fea1d0df 100644
--- a/core/java/android/os/GraphicsEnvironment.java
+++ b/core/java/android/os/GraphicsEnvironment.java
@@ -109,11 +109,11 @@ public class GraphicsEnvironment {
private static final int UPDATABLE_DRIVER_GLOBAL_OPT_IN_PRERELEASE_DRIVER = 2;
private static final int UPDATABLE_DRIVER_GLOBAL_OPT_IN_OFF = 3;
- // Values for GLOBAL_SETTINGS_ANGLE_GL_DRIVER_ALL_ANGLE
+ // Values for ANGLE_GL_DRIVER_ALL_ANGLE
private static final int ANGLE_GL_DRIVER_ALL_ANGLE_ON = 1;
private static final int ANGLE_GL_DRIVER_ALL_ANGLE_OFF = 0;
- // Values for GLOBAL_SETTINGS_ANGLE_GL_DRIVER_SELECTION_VALUES
+ // Values for ANGLE_GL_DRIVER_SELECTION_VALUES
private static final String ANGLE_GL_DRIVER_CHOICE_DEFAULT = "default";
private static final String ANGLE_GL_DRIVER_CHOICE_ANGLE = "angle";
private static final String ANGLE_GL_DRIVER_CHOICE_NATIVE = "native";
@@ -382,11 +382,11 @@ public class GraphicsEnvironment {
final int allUseAngle;
if (bundle != null) {
allUseAngle =
- bundle.getInt(Settings.Global.GLOBAL_SETTINGS_ANGLE_GL_DRIVER_ALL_ANGLE);
+ bundle.getInt(Settings.Global.ANGLE_GL_DRIVER_ALL_ANGLE);
} else {
ContentResolver contentResolver = context.getContentResolver();
allUseAngle = Settings.Global.getInt(contentResolver,
- Settings.Global.GLOBAL_SETTINGS_ANGLE_GL_DRIVER_ALL_ANGLE,
+ Settings.Global.ANGLE_GL_DRIVER_ALL_ANGLE,
ANGLE_GL_DRIVER_ALL_ANGLE_OFF);
}
if (allUseAngle == ANGLE_GL_DRIVER_ALL_ANGLE_ON) {
@@ -402,10 +402,10 @@ public class GraphicsEnvironment {
final ContentResolver contentResolver = context.getContentResolver();
final List<String> optInPackages =
getGlobalSettingsString(contentResolver, bundle,
- Settings.Global.GLOBAL_SETTINGS_ANGLE_GL_DRIVER_SELECTION_PKGS);
+ Settings.Global.ANGLE_GL_DRIVER_SELECTION_PKGS);
final List<String> optInValues =
getGlobalSettingsString(contentResolver, bundle,
- Settings.Global.GLOBAL_SETTINGS_ANGLE_GL_DRIVER_SELECTION_VALUES);
+ Settings.Global.ANGLE_GL_DRIVER_SELECTION_VALUES);
// Make sure we have good settings to use
if (optInPackages.size() != optInValues.size()) {
@@ -462,11 +462,11 @@ public class GraphicsEnvironment {
if (coreSettings != null) {
debugPackage =
- coreSettings.getString(Settings.Global.GLOBAL_SETTINGS_ANGLE_DEBUG_PACKAGE);
+ coreSettings.getString(Settings.Global.ANGLE_DEBUG_PACKAGE);
} else {
ContentResolver contentResolver = context.getContentResolver();
debugPackage = Settings.Global.getString(contentResolver,
- Settings.Global.GLOBAL_SETTINGS_ANGLE_DEBUG_PACKAGE);
+ Settings.Global.ANGLE_DEBUG_PACKAGE);
}
if (TextUtils.isEmpty(debugPackage)) {
return "";
@@ -578,7 +578,7 @@ public class GraphicsEnvironment {
final ContentResolver contentResolver = context.getContentResolver();
final List<String> angleAllowlist =
getGlobalSettingsString(contentResolver, bundle,
- Settings.Global.GLOBAL_SETTINGS_ANGLE_ALLOWLIST);
+ Settings.Global.ANGLE_ALLOWLIST);
if (DEBUG) Log.v(TAG, "ANGLE allowlist: " + angleAllowlist);
@@ -678,7 +678,7 @@ public class GraphicsEnvironment {
try {
ContentResolver contentResolver = context.getContentResolver();
final int showDialogBox = Settings.Global.getInt(contentResolver,
- Settings.Global.GLOBAL_SETTINGS_SHOW_ANGLE_IN_USE_DIALOG_BOX);
+ Settings.Global.SHOW_ANGLE_IN_USE_DIALOG_BOX);
return (showDialogBox == 1);
} catch (Settings.SettingNotFoundException | SecurityException e) {
diff --git a/core/java/android/os/HidlMemory.java b/core/java/android/os/HidlMemory.java
index 02d1e0ce9109..26fc6f0ae4ce 100644
--- a/core/java/android/os/HidlMemory.java
+++ b/core/java/android/os/HidlMemory.java
@@ -20,7 +20,6 @@ import android.annotation.IntRange;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.SystemApi;
-import android.annotation.TestApi;
import java.io.Closeable;
import java.io.IOException;
@@ -41,7 +40,6 @@ import java.io.IOException;
* @hide
*/
@SystemApi
-@TestApi
public class HidlMemory implements Closeable {
private final @NonNull String mName;
private final long mSize;
diff --git a/core/java/android/os/HwBinder.java b/core/java/android/os/HwBinder.java
index 64ab1d711765..0d2bfdf04905 100644
--- a/core/java/android/os/HwBinder.java
+++ b/core/java/android/os/HwBinder.java
@@ -17,7 +17,6 @@
package android.os;
import android.annotation.SystemApi;
-import android.annotation.TestApi;
import android.compat.annotation.UnsupportedAppUsage;
import libcore.util.NativeAllocationRegistry;
@@ -26,7 +25,6 @@ import java.util.NoSuchElementException;
/** @hide */
@SystemApi
-@TestApi
public abstract class HwBinder implements IHwBinder {
private static final String TAG = "HwBinder";
diff --git a/core/java/android/os/HwBlob.java b/core/java/android/os/HwBlob.java
index 154227b2a786..a43fbdbde4d2 100644
--- a/core/java/android/os/HwBlob.java
+++ b/core/java/android/os/HwBlob.java
@@ -19,7 +19,6 @@ package android.os;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.SystemApi;
-import android.annotation.TestApi;
import libcore.util.NativeAllocationRegistry;
@@ -30,7 +29,6 @@ import libcore.util.NativeAllocationRegistry;
* @hide
*/
@SystemApi
-@TestApi
public class HwBlob {
private static final String TAG = "HwBlob";
diff --git a/core/java/android/os/HwParcel.java b/core/java/android/os/HwParcel.java
index 228548ad7802..9fd37d4548ac 100644
--- a/core/java/android/os/HwParcel.java
+++ b/core/java/android/os/HwParcel.java
@@ -20,7 +20,6 @@ import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.SystemApi;
-import android.annotation.TestApi;
import android.compat.annotation.UnsupportedAppUsage;
import dalvik.annotation.optimization.FastNative;
@@ -34,7 +33,6 @@ import java.util.Arrays;
/** @hide */
@SystemApi
-@TestApi
public class HwParcel {
private static final String TAG = "HwParcel";
diff --git a/core/java/android/os/IHwBinder.java b/core/java/android/os/IHwBinder.java
index 46fa6ef3b783..249eb3aa3456 100644
--- a/core/java/android/os/IHwBinder.java
+++ b/core/java/android/os/IHwBinder.java
@@ -17,11 +17,9 @@
package android.os;
import android.annotation.SystemApi;
-import android.annotation.TestApi;
/** @hide */
@SystemApi
-@TestApi
public interface IHwBinder {
/**
* Process a hwbinder transaction.
diff --git a/core/java/android/os/IHwInterface.java b/core/java/android/os/IHwInterface.java
index 0a5a71550b06..f21f6e30a041 100644
--- a/core/java/android/os/IHwInterface.java
+++ b/core/java/android/os/IHwInterface.java
@@ -17,11 +17,9 @@
package android.os;
import android.annotation.SystemApi;
-import android.annotation.TestApi;
/** @hide */
@SystemApi
-@TestApi
public interface IHwInterface {
/**
* @return the binder object that corresponds to this interface.
diff --git a/core/java/android/os/IncidentManager.java b/core/java/android/os/IncidentManager.java
index 565d31a26dbc..a543a2d6a983 100644
--- a/core/java/android/os/IncidentManager.java
+++ b/core/java/android/os/IncidentManager.java
@@ -23,7 +23,6 @@ import android.annotation.Nullable;
import android.annotation.RequiresPermission;
import android.annotation.SystemApi;
import android.annotation.SystemService;
-import android.annotation.TestApi;
import android.content.Context;
import android.net.Uri;
import android.util.Slog;
@@ -45,7 +44,6 @@ import java.util.concurrent.Executor;
* @hide
*/
@SystemApi
-@TestApi
@SystemService(Context.INCIDENT_SERVICE)
public class IncidentManager {
private static final String TAG = "IncidentManager";
@@ -159,7 +157,6 @@ public class IncidentManager {
* @hide
*/
@SystemApi
- @TestApi
public static class PendingReport {
/**
* Encoded data.
@@ -277,7 +274,6 @@ public class IncidentManager {
* @hide
*/
@SystemApi
- @TestApi
public static class IncidentReport implements Parcelable, Closeable {
private final long mTimestampNs;
private final int mPrivacyPolicy;
diff --git a/core/java/android/os/IncidentReportArgs.java b/core/java/android/os/IncidentReportArgs.java
index 7e858e1dc390..73e4914ce6ae 100644
--- a/core/java/android/os/IncidentReportArgs.java
+++ b/core/java/android/os/IncidentReportArgs.java
@@ -18,7 +18,6 @@ package android.os;
import android.annotation.NonNull;
import android.annotation.SystemApi;
-import android.annotation.TestApi;
import android.os.Parcel;
import android.os.Parcelable;
import android.util.IntArray;
@@ -30,7 +29,6 @@ import java.util.ArrayList;
* {@hide}
*/
@SystemApi
-@TestApi
public final class IncidentReportArgs implements Parcelable {
private final IntArray mSections = new IntArray();
diff --git a/core/java/android/os/NativeHandle.java b/core/java/android/os/NativeHandle.java
index 8d341b603eb4..a26873a87552 100644
--- a/core/java/android/os/NativeHandle.java
+++ b/core/java/android/os/NativeHandle.java
@@ -20,7 +20,6 @@ import static android.system.OsConstants.F_DUPFD_CLOEXEC;
import android.annotation.NonNull;
import android.annotation.SystemApi;
-import android.annotation.TestApi;
import android.system.ErrnoException;
import android.system.Os;
@@ -33,7 +32,6 @@ import java.io.FileDescriptor;
* @hide
*/
@SystemApi
-@TestApi
public final class NativeHandle implements Closeable {
// whether this object owns mFds
private boolean mOwn = false;
diff --git a/core/java/android/os/Parcel.java b/core/java/android/os/Parcel.java
index 13d5f6a9c9d7..765ef48308ae 100644
--- a/core/java/android/os/Parcel.java
+++ b/core/java/android/os/Parcel.java
@@ -2010,13 +2010,13 @@ public final class Parcel {
* A map used by {@link #readSquashed} to cache parcelables. It's a map from
* an absolute position in a Parcel to the parcelable stored at the position.
*/
- private ArrayMap<Integer, Parcelable> mReadSquashableParcelables;
+ private SparseArray<Parcelable> mReadSquashableParcelables;
private void ensureReadSquashableParcelables() {
if (mReadSquashableParcelables != null) {
return;
}
- mReadSquashableParcelables = new ArrayMap<>();
+ mReadSquashableParcelables = new SparseArray<>();
}
/**
@@ -2112,9 +2112,13 @@ public final class Parcel {
final Parcelable p = mReadSquashableParcelables.get(firstAbsolutePos);
if (p == null) {
+ final StringBuilder sb = new StringBuilder();
+ for (int i = 0; i < mReadSquashableParcelables.size(); i++) {
+ sb.append(mReadSquashableParcelables.keyAt(i)).append(' ');
+ }
Slog.wtfStack(TAG, "Map doesn't contain offset "
+ firstAbsolutePos
- + " : contains=" + new ArrayList<>(mReadSquashableParcelables.keySet()));
+ + " : contains=" + sb.toString());
}
return (T) p;
}
diff --git a/core/java/android/os/Parcelable.java b/core/java/android/os/Parcelable.java
index f14f66b07630..7a624e1da26c 100644
--- a/core/java/android/os/Parcelable.java
+++ b/core/java/android/os/Parcelable.java
@@ -120,7 +120,7 @@ public interface Parcelable {
* @see ParcelableHolder
* @hide
*/
- @SystemApi(client = SystemApi.Client.MODULE_LIBRARIES)
+ @SystemApi(client = SystemApi.Client.PRIVILEGED_APPS)
public static final int PARCELABLE_STABILITY_LOCAL = 0x0000;
/**
* Something that is meant to be used between system and vendor.
@@ -128,7 +128,7 @@ public interface Parcelable {
* @see ParcelableHolder
* @hide
*/
- @SystemApi(client = SystemApi.Client.MODULE_LIBRARIES)
+ @SystemApi(client = SystemApi.Client.PRIVILEGED_APPS)
public static final int PARCELABLE_STABILITY_VINTF = 0x0001;
/**
diff --git a/core/java/android/os/ParcelableHolder.java b/core/java/android/os/ParcelableHolder.java
index 181f94b39841..95c07b6b2451 100644
--- a/core/java/android/os/ParcelableHolder.java
+++ b/core/java/android/os/ParcelableHolder.java
@@ -18,12 +18,54 @@ package android.os;
import android.annotation.NonNull;
import android.annotation.Nullable;
+import android.annotation.SystemApi;
import android.util.MathUtils;
/**
- * Parcelable containing the other Parcelable object.
+ * ParcelableHolder is a Parcelable which can contain another Parcelable.
+ * The main use case of ParcelableHolder is to make a Parcelable extensible.
+ * For example, an AOSP-defined Parcelable <code>AospDefinedParcelable</code>
+ * is expected to be extended by device implementers for their value-add features.
+ * Previously without ParcelableHolder, the device implementers had to
+ * directly modify the Parcelable to add more fields:
+ * <pre> {@code
+ * parcelable AospDefinedParcelable {
+ * int a;
+ * String b;
+ * String x; // added by a device implementer
+ * int[] y; // added by a device implementer
+ * }}</pre>
+ *
+ * This practice is very error-prone because the fields added by the device implementer
+ * might have a conflict when the Parcelable is revisioned in the next releases of Android.
+ *
+ * Using ParcelableHolder, one can define an extension point in a Parcelable.
+ * <pre> {@code
+ * parcelable AospDefinedParcelable {
+ * int a;
+ * String b;
+ * ParcelableHolder extension;
+ * }}</pre>
+ * Then the device implementers can define their own Parcelable for their extension.
+ *
+ * <pre> {@code
+ * parcelable OemDefinedParcelable {
+ * String x;
+ * int[] y;
+ * }}</pre>
+ * Finally, the new Parcelable can be attached to the original Parcelable via
+ * the ParcelableHolder field.
+ *
+ * <pre> {@code
+ * AospDefinedParcelable ap = ...;
+ * OemDefinedParcelable op = new OemDefinedParcelable();
+ * op.x = ...;
+ * op.y = ...;
+ * ap.extension.setParcelable(op);}</pre>
+ *
* @hide
*/
+@SystemApi
public final class ParcelableHolder implements Parcelable {
/**
* This is set by {@link #setParcelable}.
@@ -80,7 +122,7 @@ public final class ParcelableHolder implements Parcelable {
* Write a parcelable into ParcelableHolder, the previous parcelable will be removed.
* @return {@code false} if the parcelable's stability is more unstable ParcelableHolder.
*/
- public synchronized boolean setParcelable(@Nullable Parcelable p) {
+ public boolean setParcelable(@Nullable Parcelable p) {
// a ParcelableHolder can only hold things at its stability or higher
if (p != null && this.getStability() > p.getStability()) {
return false;
@@ -99,7 +141,7 @@ public final class ParcelableHolder implements Parcelable {
* the type written by (@link #setParcelable}.
*/
@Nullable
- public synchronized <T extends Parcelable> T getParcelable(@NonNull Class<T> clazz) {
+ public <T extends Parcelable> T getParcelable(@NonNull Class<T> clazz) {
if (mParcel == null) {
if (!clazz.isInstance(mParcelable)) {
return null;
@@ -123,7 +165,7 @@ public final class ParcelableHolder implements Parcelable {
/**
* Read ParcelableHolder from a parcel.
*/
- public synchronized void readFromParcel(@NonNull Parcel parcel) {
+ public void readFromParcel(@NonNull Parcel parcel) {
this.mStability = parcel.readInt();
mParcelable = null;
@@ -145,7 +187,7 @@ public final class ParcelableHolder implements Parcelable {
}
@Override
- public synchronized void writeToParcel(@NonNull Parcel parcel, int flags) {
+ public void writeToParcel(@NonNull Parcel parcel, int flags) {
parcel.writeInt(this.mStability);
if (mParcel != null) {
@@ -166,7 +208,7 @@ public final class ParcelableHolder implements Parcelable {
}
@Override
- public synchronized int describeContents() {
+ public int describeContents() {
if (mParcel != null) {
return mParcel.hasFileDescriptors() ? Parcelable.CONTENTS_FILE_DESCRIPTOR : 0;
}
diff --git a/core/java/android/os/PowerManager.java b/core/java/android/os/PowerManager.java
index 50f0c28cb8f8..e736e30b51e5 100644
--- a/core/java/android/os/PowerManager.java
+++ b/core/java/android/os/PowerManager.java
@@ -1565,7 +1565,6 @@ public final class PowerManager {
* @see #isPowerSaveMode()
*/
@SystemApi
- @TestApi
@RequiresPermission(anyOf = {
android.Manifest.permission.DEVICE_POWER,
android.Manifest.permission.POWER_SAVER
@@ -1610,7 +1609,6 @@ public final class PowerManager {
* @hide
*/
@SystemApi
- @TestApi
@RequiresPermission(permission.POWER_SAVER)
public boolean setDynamicPowerSaveHint(boolean powerSaveHint, int disableThreshold) {
try {
@@ -1670,7 +1668,6 @@ public final class PowerManager {
* @hide
*/
@SystemApi
- @TestApi
public static final int POWER_SAVE_MODE_TRIGGER_PERCENTAGE = 0;
/**
@@ -1683,7 +1680,6 @@ public final class PowerManager {
* @hide
*/
@SystemApi
- @TestApi
public static final int POWER_SAVE_MODE_TRIGGER_DYNAMIC = 1;
/** @hide */
@@ -1708,7 +1704,6 @@ public final class PowerManager {
*/
@AutoPowerSaveModeTriggers
@SystemApi
- @TestApi
@RequiresPermission(android.Manifest.permission.POWER_SAVER)
public int getPowerSaveModeTrigger() {
try {
@@ -1732,7 +1727,6 @@ public final class PowerManager {
* @hide
*/
@SystemApi
- @TestApi
@RequiresPermission(android.Manifest.permission.DEVICE_POWER)
public void setBatteryDischargePrediction(@NonNull Duration timeRemaining,
boolean isPersonalized) {
@@ -2005,7 +1999,7 @@ public final class PowerManager {
Preconditions.checkNotNull(listener, "listener cannot be null");
Preconditions.checkNotNull(executor, "executor cannot be null");
Preconditions.checkArgument(!mListenerMap.containsKey(listener),
- "Listener already registered: " + listener);
+ "Listener already registered: %s", listener);
IThermalStatusListener internalListener = new IThermalStatusListener.Stub() {
@Override
public void onStatusChange(int status) {
diff --git a/core/java/android/os/RemoteCallback.java b/core/java/android/os/RemoteCallback.java
index 373060f4ff4b..49f84adf2c21 100644
--- a/core/java/android/os/RemoteCallback.java
+++ b/core/java/android/os/RemoteCallback.java
@@ -19,14 +19,12 @@ package android.os;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.SystemApi;
-import android.annotation.TestApi;
import android.compat.annotation.UnsupportedAppUsage;
/**
* @hide
*/
@SystemApi
-@TestApi
public final class RemoteCallback implements Parcelable {
public interface OnResultListener {
diff --git a/core/java/android/os/StrictMode.java b/core/java/android/os/StrictMode.java
index 6c5b04a649e2..0fba8950cf15 100644
--- a/core/java/android/os/StrictMode.java
+++ b/core/java/android/os/StrictMode.java
@@ -60,6 +60,7 @@ import android.util.Log;
import android.util.Printer;
import android.util.Singleton;
import android.util.Slog;
+import android.util.SparseLongArray;
import android.view.IWindowManager;
import com.android.internal.annotations.GuardedBy;
@@ -1525,7 +1526,9 @@ public final class StrictMode {
// Map from violation stacktrace hashcode -> uptimeMillis of
// last violation. No locking needed, as this is only
// accessed by the same thread.
+ /** Temporarily retained; appears to be missing UnsupportedAppUsage annotation */
private ArrayMap<Integer, Long> mLastViolationTime;
+ private SparseLongArray mRealLastViolationTime;
public AndroidBlockGuardPolicy(@ThreadPolicyMask int threadPolicyMask) {
mThreadPolicyMask = threadPolicyMask;
@@ -1759,17 +1762,17 @@ public final class StrictMode {
long lastViolationTime = 0;
long now = SystemClock.uptimeMillis();
if (sLogger == LOGCAT_LOGGER) { // Don't throttle it if there is a non-default logger
- if (mLastViolationTime != null) {
- Long vtime = mLastViolationTime.get(crashFingerprint);
+ if (mRealLastViolationTime != null) {
+ Long vtime = mRealLastViolationTime.get(crashFingerprint);
if (vtime != null) {
lastViolationTime = vtime;
}
- clampViolationTimeMap(mLastViolationTime, Math.max(MIN_LOG_INTERVAL_MS,
+ clampViolationTimeMap(mRealLastViolationTime, Math.max(MIN_LOG_INTERVAL_MS,
Math.max(MIN_DIALOG_INTERVAL_MS, MIN_DROPBOX_INTERVAL_MS)));
} else {
- mLastViolationTime = new ArrayMap<>(1);
+ mRealLastViolationTime = new SparseLongArray(1);
}
- mLastViolationTime.put(crashFingerprint, now);
+ mRealLastViolationTime.put(crashFingerprint, now);
}
long timeSinceLastViolationMillis =
lastViolationTime == 0 ? Long.MAX_VALUE : (now - lastViolationTime);
@@ -2165,16 +2168,17 @@ public final class StrictMode {
}
final int uid = android.os.Process.myUid();
- String msg = "Detected cleartext network traffic from UID " + uid;
+ final StringBuilder msg = new StringBuilder("Detected cleartext network traffic from UID ")
+ .append(uid);
if (rawAddr != null) {
try {
- msg += " to " + InetAddress.getByAddress(rawAddr);
+ msg.append(" to ").append(InetAddress.getByAddress(rawAddr));
} catch (UnknownHostException ignored) {
}
}
- msg += HexDump.dumpHexString(firstPacket).trim() + " ";
+ msg.append(HexDump.dumpHexString(firstPacket).trim()).append(' ');
final boolean forceDeath = (sVmPolicy.mask & PENALTY_DEATH_ON_CLEARTEXT_NETWORK) != 0;
- onVmPolicyViolation(new CleartextNetworkViolation(msg), forceDeath);
+ onVmPolicyViolation(new CleartextNetworkViolation(msg.toString()), forceDeath);
}
/** @hide */
@@ -2231,18 +2235,19 @@ public final class StrictMode {
// Map from VM violation fingerprint to uptime millis.
@UnsupportedAppUsage
private static final HashMap<Integer, Long> sLastVmViolationTime = new HashMap<>();
+ private static final SparseLongArray sRealLastVmViolationTime = new SparseLongArray();
/**
* Clamp the given map by removing elements with timestamp older than the given retainSince.
*/
- private static void clampViolationTimeMap(final @NonNull Map<Integer, Long> violationTime,
+ private static void clampViolationTimeMap(final @NonNull SparseLongArray violationTime,
final long retainSince) {
- final Iterator<Map.Entry<Integer, Long>> iterator = violationTime.entrySet().iterator();
- while (iterator.hasNext()) {
- Map.Entry<Integer, Long> e = iterator.next();
- if (e.getValue() < retainSince) {
+ for (int i = 0; i < violationTime.size(); ) {
+ if (violationTime.valueAt(i) < retainSince) {
// Remove stale entries
- iterator.remove();
+ violationTime.removeAt(i);
+ } else {
+ i++;
}
}
// Ideally we'd cap the total size of the map, though it'll involve quickselect of topK,
@@ -2273,15 +2278,15 @@ public final class StrictMode {
long lastViolationTime;
long timeSinceLastViolationMillis = Long.MAX_VALUE;
if (sLogger == LOGCAT_LOGGER) { // Don't throttle it if there is a non-default logger
- synchronized (sLastVmViolationTime) {
- if (sLastVmViolationTime.containsKey(fingerprint)) {
- lastViolationTime = sLastVmViolationTime.get(fingerprint);
+ synchronized (sRealLastVmViolationTime) {
+ if (sRealLastVmViolationTime.indexOfKey(fingerprint) >= 0) {
+ lastViolationTime = sRealLastVmViolationTime.get(fingerprint);
timeSinceLastViolationMillis = now - lastViolationTime;
}
if (timeSinceLastViolationMillis > MIN_VM_INTERVAL_MS) {
- sLastVmViolationTime.put(fingerprint, now);
+ sRealLastVmViolationTime.put(fingerprint, now);
}
- clampViolationTimeMap(sLastVmViolationTime,
+ clampViolationTimeMap(sRealLastVmViolationTime,
now - Math.max(MIN_VM_INTERVAL_MS, MIN_LOG_INTERVAL_MS));
}
}
diff --git a/core/java/android/os/SystemConfigManager.java b/core/java/android/os/SystemConfigManager.java
index 12a1ffaf69c1..3f0632be90d1 100644
--- a/core/java/android/os/SystemConfigManager.java
+++ b/core/java/android/os/SystemConfigManager.java
@@ -20,7 +20,6 @@ import android.annotation.NonNull;
import android.annotation.RequiresPermission;
import android.annotation.SystemApi;
import android.annotation.SystemService;
-import android.annotation.TestApi;
import android.content.Context;
import android.util.ArraySet;
import android.util.Log;
@@ -40,7 +39,6 @@ import java.util.Set;
* @hide
*/
@SystemApi
-@TestApi
@SystemService(Context.SYSTEM_CONFIG_SERVICE)
public class SystemConfigManager {
private static final String TAG = SystemConfigManager.class.getSimpleName();
diff --git a/core/java/android/os/SystemProperties.java b/core/java/android/os/SystemProperties.java
index c5e5cc40d54e..a16452705efc 100644
--- a/core/java/android/os/SystemProperties.java
+++ b/core/java/android/os/SystemProperties.java
@@ -19,7 +19,6 @@ package android.os;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.SystemApi;
-import android.annotation.TestApi;
import android.compat.annotation.UnsupportedAppUsage;
import android.util.Log;
import android.util.MutableInt;
@@ -52,7 +51,6 @@ import java.util.HashMap;
* {@hide}
*/
@SystemApi
-@TestApi
public class SystemProperties {
private static final String TAG = "SystemProperties";
private static final boolean TRACK_KEY_ACCESS = false;
@@ -146,7 +144,6 @@ public class SystemProperties {
*/
@NonNull
@SystemApi
- @TestApi
public static String get(@NonNull String key) {
if (TRACK_KEY_ACCESS) onKeyAccess(key);
return native_get(key);
@@ -163,7 +160,6 @@ public class SystemProperties {
*/
@NonNull
@SystemApi
- @TestApi
public static String get(@NonNull String key, @Nullable String def) {
if (TRACK_KEY_ACCESS) onKeyAccess(key);
return native_get(key, def);
@@ -179,7 +175,6 @@ public class SystemProperties {
* @hide
*/
@SystemApi
- @TestApi
public static int getInt(@NonNull String key, int def) {
if (TRACK_KEY_ACCESS) onKeyAccess(key);
return native_get_int(key, def);
@@ -195,7 +190,6 @@ public class SystemProperties {
* @hide
*/
@SystemApi
- @TestApi
public static long getLong(@NonNull String key, long def) {
if (TRACK_KEY_ACCESS) onKeyAccess(key);
return native_get_long(key, def);
@@ -216,7 +210,6 @@ public class SystemProperties {
* @hide
*/
@SystemApi
- @TestApi
public static boolean getBoolean(@NonNull String key, boolean def) {
if (TRACK_KEY_ACCESS) onKeyAccess(key);
return native_get_boolean(key, def);
diff --git a/core/java/android/os/UserHandle.java b/core/java/android/os/UserHandle.java
index 60447e76f75e..d39c5328e330 100644
--- a/core/java/android/os/UserHandle.java
+++ b/core/java/android/os/UserHandle.java
@@ -47,7 +47,6 @@ public final class UserHandle implements Parcelable {
/** @hide A user handle to indicate all users on the device */
@SystemApi
- @TestApi
public static final @NonNull UserHandle ALL = new UserHandle(USER_ALL);
/** @hide A user id to indicate the currently active user */
@@ -56,7 +55,6 @@ public final class UserHandle implements Parcelable {
/** @hide A user handle to indicate the current user of the device */
@SystemApi
- @TestApi
public static final @NonNull UserHandle CURRENT = new UserHandle(USER_CURRENT);
/** @hide A user id to indicate that we would like to send to the current
@@ -107,7 +105,6 @@ public final class UserHandle implements Parcelable {
/** @hide A user handle to indicate the "system" user of the device */
@SystemApi
- @TestApi
public static final @NonNull UserHandle SYSTEM = new UserHandle(USER_SYSTEM);
/**
@@ -280,7 +277,6 @@ public final class UserHandle implements Parcelable {
}
/** @hide */
- @TestApi
@SystemApi
public static UserHandle of(@UserIdInt int userId) {
if (userId == USER_SYSTEM) {
@@ -325,7 +321,6 @@ public final class UserHandle implements Parcelable {
* Returns the app id (or base uid) for a given uid, stripping out the user id from it.
* @hide
*/
- @TestApi
@SystemApi
public static @AppIdInt int getAppId(int uid) {
return uid % PER_USER_RANGE;
@@ -483,7 +478,6 @@ public final class UserHandle implements Parcelable {
* @hide
*/
@SystemApi
- @TestApi
public static @UserIdInt int myUserId() {
return getUserId(Process.myUid());
}
@@ -522,7 +516,6 @@ public final class UserHandle implements Parcelable {
* @hide
*/
@SystemApi
- @TestApi
public @UserIdInt int getIdentifier() {
return mHandle;
}
diff --git a/core/java/android/os/UserManager.java b/core/java/android/os/UserManager.java
index 42ae93030f38..b0e76e3ea851 100644
--- a/core/java/android/os/UserManager.java
+++ b/core/java/android/os/UserManager.java
@@ -1407,8 +1407,7 @@ public class UserManager {
*
* @hide
*/
- @SystemApi
- @TestApi // To allow seeing it from CTS.
+ @SystemApi // To allow seeing it from CTS.
public static final String ACTION_USER_RESTRICTIONS_CHANGED =
"android.os.action.USER_RESTRICTIONS_CHANGED";
@@ -1468,6 +1467,48 @@ public class UserManager {
public @interface UserSwitchabilityResult {}
/**
+ * A response code from {@link #removeUserOrSetEphemeral(int)} indicating that the specified
+ * user has been successfully removed.
+ * @hide
+ */
+ 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.
+ * @hide
+ */
+ public static final int REMOVE_RESULT_SET_EPHEMERAL = 1;
+
+ /**
+ * A response code from {@link #removeUserOrSetEphemeral(int)} indicating that the specified
+ * user is already in the process of being removed.
+ * @hide
+ */
+ 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.
+ * @hide
+ */
+ public static final int REMOVE_RESULT_ERROR = 3;
+
+ /**
+ * Possible response codes from {@link #removeUserOrSetEphemeral(int)}.
+ * @hide
+ */
+ @IntDef(prefix = { "REMOVE_RESULT_" }, value = {
+ REMOVE_RESULT_REMOVED,
+ REMOVE_RESULT_SET_EPHEMERAL,
+ REMOVE_RESULT_ALREADY_BEING_REMOVED,
+ REMOVE_RESULT_ERROR,
+ })
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface RemoveResult {}
+
+ /**
* Indicates user operation is successful.
*/
public static final int USER_OPERATION_SUCCESS = 0;
@@ -3982,11 +4023,11 @@ public class UserManager {
* the current user, then set the user as ephemeral so that it will be removed when it is
* stopped.
*
- * @return the {@link com.android.server.pm.UserManagerService.RemoveResult} code
+ * @return the {@link RemoveResult} code
* @hide
*/
@RequiresPermission(android.Manifest.permission.MANAGE_USERS)
- public int removeUserOrSetEphemeral(@UserIdInt int userId) {
+ public @RemoveResult int removeUserOrSetEphemeral(@UserIdInt int userId) {
try {
return mService.removeUserOrSetEphemeral(userId);
} catch (RemoteException re) {
diff --git a/core/java/android/os/Vibrator.java b/core/java/android/os/Vibrator.java
index 0c0e6b5d73a6..7d85d13094a1 100644
--- a/core/java/android/os/Vibrator.java
+++ b/core/java/android/os/Vibrator.java
@@ -23,7 +23,6 @@ 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;
@@ -469,7 +468,6 @@ public abstract class Vibrator {
* @hide
*/
@SystemApi
- @TestApi
@RequiresPermission(android.Manifest.permission.ACCESS_VIBRATOR_STATE)
public boolean isVibrating() {
return false;
@@ -483,7 +481,6 @@ public abstract class Vibrator {
* @hide
*/
@SystemApi
- @TestApi
public interface OnVibratorStateChangedListener {
/**
* Called when the vibrator state has changed.
@@ -502,7 +499,6 @@ public abstract class Vibrator {
* @hide
*/
@SystemApi
- @TestApi
@RequiresPermission(android.Manifest.permission.ACCESS_VIBRATOR_STATE)
public void addVibratorStateListener(@NonNull OnVibratorStateChangedListener listener) {
}
@@ -516,7 +512,6 @@ public abstract class Vibrator {
* @hide
*/
@SystemApi
- @TestApi
@RequiresPermission(android.Manifest.permission.ACCESS_VIBRATOR_STATE)
public void addVibratorStateListener(
@NonNull @CallbackExecutor Executor executor,
@@ -531,7 +526,6 @@ public abstract class Vibrator {
* @hide
*/
@SystemApi
- @TestApi
@RequiresPermission(android.Manifest.permission.ACCESS_VIBRATOR_STATE)
public void removeVibratorStateListener(@NonNull OnVibratorStateChangedListener listener) {
}
diff --git a/core/java/android/os/WorkSource.java b/core/java/android/os/WorkSource.java
index a1b4dc3ffded..e0927ebd261a 100644
--- a/core/java/android/os/WorkSource.java
+++ b/core/java/android/os/WorkSource.java
@@ -98,7 +98,6 @@ public class WorkSource implements Parcelable {
* @param uid the uid performing the work
* @hide
*/
- @TestApi
@SystemApi
public WorkSource(int uid) {
mNum = 1;
@@ -152,7 +151,6 @@ public class WorkSource implements Parcelable {
* Returns the number of uids in this work source.
* @hide
*/
- @TestApi
@SystemApi
public int size() {
return mNum;
@@ -173,7 +171,6 @@ public class WorkSource implements Parcelable {
* If {@code index} < 0 or {@code index} >= {@link #size() N}, then the behavior is undefined.
* @hide
*/
- @TestApi
@SystemApi
public int getUid(int index) {
return mUids[index];
@@ -209,7 +206,6 @@ public class WorkSource implements Parcelable {
* If {@code index} < 0 or {@code index} >= {@link #size() N}, then the behavior is undefined.
* @hide
*/
- @TestApi
@SystemApi
@Nullable
public String getPackageName(int index) {
@@ -455,7 +451,6 @@ public class WorkSource implements Parcelable {
* @hide
*/
@SystemApi
- @TestApi
@NonNull
public WorkSource withoutNames() {
final WorkSource copy = new WorkSource(this);
@@ -582,7 +577,6 @@ public class WorkSource implements Parcelable {
* @hide for internal use only.
*/
@SystemApi
- @TestApi
public boolean isEmpty() {
return mNum == 0 && (mChains == null || mChains.isEmpty());
}
diff --git a/core/java/android/os/image/DynamicSystemClient.java b/core/java/android/os/image/DynamicSystemClient.java
index 50d8d8079ed5..58268e2fc914 100644
--- a/core/java/android/os/image/DynamicSystemClient.java
+++ b/core/java/android/os/image/DynamicSystemClient.java
@@ -22,7 +22,6 @@ import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.RequiresPermission;
import android.annotation.SystemApi;
-import android.annotation.TestApi;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
@@ -68,7 +67,6 @@ import java.util.concurrent.Executor;
* @hide
*/
@SystemApi
-@TestApi
public class DynamicSystemClient {
/** @hide */
@IntDef(prefix = { "STATUS_" }, value = {
@@ -286,7 +284,6 @@ public class DynamicSystemClient {
* @hide
*/
@SystemApi
- @TestApi
public DynamicSystemClient(@NonNull Context context) {
mContext = context;
mConnection = new DynSystemServiceConnection();
@@ -322,7 +319,6 @@ public class DynamicSystemClient {
*/
@RequiresPermission(android.Manifest.permission.INSTALL_DYNAMIC_SYSTEM)
@SystemApi
- @TestApi
public void bind() {
if (!featureFlagEnabled()) {
Slog.w(TAG, FeatureFlagUtils.DYNAMIC_SYSTEM + " not enabled; bind() aborted.");
@@ -345,7 +341,6 @@ public class DynamicSystemClient {
*/
@RequiresPermission(android.Manifest.permission.INSTALL_DYNAMIC_SYSTEM)
@SystemApi
- @TestApi
public void unbind() {
if (!mBound) {
return;
@@ -381,7 +376,6 @@ public class DynamicSystemClient {
*/
@RequiresPermission(android.Manifest.permission.INSTALL_DYNAMIC_SYSTEM)
@SystemApi
- @TestApi
public void start(@NonNull Uri systemUrl, @BytesLong long systemSize) {
start(systemUrl, systemSize, 0 /* Use the default userdata size */);
}
diff --git a/core/java/android/os/incremental/IIncrementalService.aidl b/core/java/android/os/incremental/IIncrementalService.aidl
index 52475e9cd89d..ca92ad5deae6 100644
--- a/core/java/android/os/incremental/IIncrementalService.aidl
+++ b/core/java/android/os/incremental/IIncrementalService.aidl
@@ -144,4 +144,14 @@ interface IIncrementalService {
* Stop listening for the loading progress change for a storage.
*/
boolean unregisterLoadingProgressListener(int storageId);
+
+ /**
+ * Register storage health status listener.
+ */
+ boolean registerStorageHealthListener(int storageId, in StorageHealthCheckParams params, in IStorageHealthListener listener);
+
+ /**
+ * Register storage health status listener.
+ */
+ void unregisterStorageHealthListener(int storageId);
}
diff --git a/core/java/android/os/incremental/IStorageHealthListener.aidl b/core/java/android/os/incremental/IStorageHealthListener.aidl
index 9f93ede5c9fc..c71e73f9ec8e 100644
--- a/core/java/android/os/incremental/IStorageHealthListener.aidl
+++ b/core/java/android/os/incremental/IStorageHealthListener.aidl
@@ -26,9 +26,15 @@ oneway interface IStorageHealthListener {
/** There are reads pending for params.blockedTimeoutMs, waiting till
* params.unhealthyTimeoutMs to confirm unhealthy state. */
const int HEALTH_STATUS_BLOCKED = 2;
- /** There are reads pending for params.unhealthyTimeoutMs>,
- * marking storage as unhealthy. */
+ /** There are reads pending for params.unhealthyTimeoutMs,
+ * marking storage as unhealthy due to unknown issues. */
const int HEALTH_STATUS_UNHEALTHY = 3;
+ /** There are reads pending for params.unhealthyTimeoutMs,
+ * due to data transportation issues. */
+ const int HEALTH_STATUS_UNHEALTHY_TRANSPORT = 4;
+ /** There are reads pending for params.unhealthyTimeoutMs,
+ * due to limited storage space. */
+ const int HEALTH_STATUS_UNHEALTHY_STORAGE = 5;
/** Health status callback. */
void onHealthStatus(in int storageId, in int status);
diff --git a/core/java/android/os/incremental/IncrementalManager.java b/core/java/android/os/incremental/IncrementalManager.java
index 768ef975bd99..fb47ef04b231 100644
--- a/core/java/android/os/incremental/IncrementalManager.java
+++ b/core/java/android/os/incremental/IncrementalManager.java
@@ -283,6 +283,7 @@ public final class IncrementalManager {
return;
}
mLoadingProgressCallbacks.cleanUpCallbacks(storage);
+ unregisterHealthListener(codePath);
mService.deleteStorage(storage.getId());
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
@@ -297,7 +298,7 @@ public final class IncrementalManager {
* @param callback To report loading progress to.
* @return True if the package name and associated storage id are valid. False otherwise.
*/
- public boolean registerCallback(@NonNull String codePath,
+ public boolean registerLoadingProgressCallback(@NonNull String codePath,
@NonNull IPackageLoadingProgressCallback callback) {
final IncrementalStorage storage = openStorage(codePath);
if (storage == null) {
@@ -314,7 +315,7 @@ public final class IncrementalManager {
* @param codePath Path of the installed package
* @return True if the package name and associated storage id are valid. False otherwise.
*/
- public boolean unregisterCallback(@NonNull String codePath,
+ public boolean unregisterLoadingProgressCallback(@NonNull String codePath,
@NonNull IPackageLoadingProgressCallback callback) {
final IncrementalStorage storage = openStorage(codePath);
if (storage == null) {
@@ -414,6 +415,38 @@ public final class IncrementalManager {
}
}
+ /**
+ * Specify the health check params and listener for listening to Incremental Storage health
+ * status changes. Notice that this will overwrite the previously registered listener.
+ * @param codePath Path of the installed package. This path is on an Incremental Storage.
+ * @param healthCheckParams The params for health state change timeouts.
+ * @param listener To report health status change.
+ * @return True if listener was successfully registered.
+ */
+ public boolean registerHealthListener(@NonNull String codePath,
+ @NonNull StorageHealthCheckParams healthCheckParams,
+ @NonNull IStorageHealthListener.Stub listener) {
+ final IncrementalStorage storage = openStorage(codePath);
+ if (storage == null) {
+ // storage does not exist, package not installed
+ return false;
+ }
+ return storage.registerStorageHealthListener(healthCheckParams, listener);
+ }
+
+ /**
+ * Stop listening to health status changes on an Incremental Storage.
+ * @param codePath Path of the installed package. This path is on an Incremental Storage.
+ */
+ public void unregisterHealthListener(@NonNull String codePath) {
+ final IncrementalStorage storage = openStorage(codePath);
+ if (storage == null) {
+ // storage does not exist, package not installed
+ return;
+ }
+ storage.unregisterStorageHealthListener();
+ }
+
/* Native methods */
private static native boolean nativeIsEnabled();
private static native boolean nativeIsIncrementalPath(@NonNull String path);
diff --git a/core/java/android/os/incremental/IncrementalStorage.java b/core/java/android/os/incremental/IncrementalStorage.java
index a1c3cc697e02..b913faf9cc83 100644
--- a/core/java/android/os/incremental/IncrementalStorage.java
+++ b/core/java/android/os/incremental/IncrementalStorage.java
@@ -545,4 +545,31 @@ public final class IncrementalStorage {
return false;
}
}
+
+ /**
+ * Register to listen to the status changes of the storage health.
+ * @param healthCheckParams Params to specify status change timeouts.
+ * @param listener To report health status change from Incremental Service to the caller.
+ */
+ public boolean registerStorageHealthListener(StorageHealthCheckParams healthCheckParams,
+ IStorageHealthListener listener) {
+ try {
+ return mService.registerStorageHealthListener(mId, healthCheckParams, listener);
+ } catch (RemoteException e) {
+ e.rethrowFromSystemServer();
+ return false;
+ }
+ }
+
+ /**
+ * Stops listening to the status changes of the storage health.
+ */
+ public void unregisterStorageHealthListener() {
+ try {
+ mService.unregisterStorageHealthListener(mId);
+ } catch (RemoteException e) {
+ e.rethrowFromSystemServer();
+ return;
+ }
+ }
}
diff --git a/core/java/android/os/storage/StorageManager.java b/core/java/android/os/storage/StorageManager.java
index 6b5eb16d7bff..270115beb09b 100644
--- a/core/java/android/os/storage/StorageManager.java
+++ b/core/java/android/os/storage/StorageManager.java
@@ -43,7 +43,6 @@ import android.annotation.SdkConstant;
import android.annotation.SuppressLint;
import android.annotation.SystemApi;
import android.annotation.SystemService;
-import android.annotation.TestApi;
import android.annotation.WorkerThread;
import android.app.Activity;
import android.app.ActivityThread;
@@ -1701,7 +1700,6 @@ public class StorageManager {
* @hide
*/
@SystemApi
- @TestApi
public static boolean hasIsolatedStorage() {
// Prefer to use snapshot for current boot when available
return SystemProperties.getBoolean(PROP_ISOLATED_STORAGE_SNAPSHOT,
diff --git a/core/java/android/permission/PermissionControllerManager.java b/core/java/android/permission/PermissionControllerManager.java
index d6c95db95e85..0ba09fdab808 100644
--- a/core/java/android/permission/PermissionControllerManager.java
+++ b/core/java/android/permission/PermissionControllerManager.java
@@ -79,7 +79,6 @@ import java.util.function.Consumer;
*
* @hide
*/
-@TestApi
@SystemApi
@SystemService(Context.PERMISSION_CONTROLLER_SERVICE)
public final class PermissionControllerManager {
diff --git a/core/java/android/permission/PermissionManager.java b/core/java/android/permission/PermissionManager.java
index 70b536d7ede0..e4220dd00a5b 100644
--- a/core/java/android/permission/PermissionManager.java
+++ b/core/java/android/permission/PermissionManager.java
@@ -16,6 +16,8 @@
package android.permission;
+import static android.os.Build.VERSION_CODES.S;
+
import android.Manifest;
import android.annotation.CallbackExecutor;
import android.annotation.IntRange;
@@ -24,12 +26,13 @@ import android.annotation.Nullable;
import android.annotation.RequiresPermission;
import android.annotation.SystemApi;
import android.annotation.SystemService;
-import android.annotation.TestApi;
import android.annotation.UserIdInt;
import android.app.ActivityManager;
import android.app.ActivityThread;
import android.app.IActivityManager;
import android.app.PropertyInvalidatedCache;
+import android.compat.annotation.ChangeId;
+import android.compat.annotation.EnabledAfter;
import android.content.Context;
import android.content.pm.IPackageManager;
import android.content.pm.PackageManager;
@@ -57,7 +60,6 @@ import java.util.function.Consumer;
*
* @hide
*/
-@TestApi
@SystemApi
@SystemService(Context.PERMISSION_SERVICE)
public final class PermissionManager {
@@ -70,6 +72,17 @@ public final class PermissionManager {
public static final String KILL_APP_REASON_GIDS_CHANGED =
"permission grant or revoke changed gids";
+ /**
+ * Refuse to install package if groups of permissions are bad
+ * - Permission groups should only be shared between apps sharing a certificate
+ * - If a permission belongs to a group that group should be defined
+ *
+ * @hide
+ */
+ @ChangeId
+ @EnabledAfter(targetSdkVersion = S)
+ public static final long CANNOT_INSTALL_WITH_BAD_PERMISSION_GROUPS = 146211400;
+
private final @NonNull Context mContext;
private final IPackageManager mPackageManager;
@@ -115,7 +128,6 @@ public final class PermissionManager {
*
* @hide
*/
- @TestApi
@SystemApi
@RequiresPermission(anyOf = {
Manifest.permission.ADJUST_RUNTIME_PERMISSIONS_POLICY,
@@ -136,7 +148,6 @@ public final class PermissionManager {
*
* @hide
*/
- @TestApi
@SystemApi
@RequiresPermission(anyOf = {
Manifest.permission.ADJUST_RUNTIME_PERMISSIONS_POLICY,
diff --git a/core/java/android/permission/RuntimePermissionPresentationInfo.java b/core/java/android/permission/RuntimePermissionPresentationInfo.java
index d696feabfc30..4fce14cef3f0 100644
--- a/core/java/android/permission/RuntimePermissionPresentationInfo.java
+++ b/core/java/android/permission/RuntimePermissionPresentationInfo.java
@@ -18,7 +18,6 @@ package android.permission;
import android.annotation.NonNull;
import android.annotation.SystemApi;
-import android.annotation.TestApi;
import android.os.Parcel;
import android.os.Parcelable;
@@ -33,7 +32,6 @@ import com.android.internal.util.Preconditions;
*
* @hide
*/
-@TestApi
@SystemApi
public final class RuntimePermissionPresentationInfo implements Parcelable {
private static final int FLAG_GRANTED = 1 << 0;
diff --git a/core/java/android/provider/DeviceConfig.java b/core/java/android/provider/DeviceConfig.java
index 99ffee3e2ad9..0315b561c120 100644
--- a/core/java/android/provider/DeviceConfig.java
+++ b/core/java/android/provider/DeviceConfig.java
@@ -55,7 +55,6 @@ import java.util.concurrent.Executor;
* @hide
*/
@SystemApi
-@TestApi
public final class DeviceConfig {
/**
* The content:// style URL for the config table.
@@ -116,7 +115,6 @@ public final class DeviceConfig {
* @hide
*/
@SystemApi
- @TestApi
public static final String NAMESPACE_AUTOFILL = "autofill";
/**
@@ -150,7 +148,6 @@ public final class DeviceConfig {
* @hide
*/
@SystemApi
- @TestApi
public static final String NAMESPACE_CONTENT_CAPTURE = "content_capture";
/**
@@ -250,7 +247,7 @@ public final class DeviceConfig {
*
* @hide
*/
- @SystemApi @TestApi
+ @SystemApi
public static final String NAMESPACE_ROLLBACK = "rollback";
/**
@@ -258,7 +255,7 @@ public final class DeviceConfig {
*
* @hide
*/
- @SystemApi @TestApi
+ @SystemApi
public static final String NAMESPACE_ROLLBACK_BOOT = "rollback_boot";
/**
@@ -403,7 +400,6 @@ public final class DeviceConfig {
* @hide
*/
@SystemApi
- @TestApi
public static final String NAMESPACE_PRIVACY = "privacy";
/**
@@ -412,7 +408,6 @@ public final class DeviceConfig {
* @hide
*/
@SystemApi
- @TestApi
public static final String NAMESPACE_BIOMETRICS = "biometrics";
/**
@@ -421,7 +416,6 @@ public final class DeviceConfig {
* @hide
*/
@SystemApi
- @TestApi
public static final String NAMESPACE_PERMISSIONS = "permissions";
/**
@@ -467,7 +461,6 @@ public final class DeviceConfig {
* @hide
*/
@SystemApi
- @TestApi
@RequiresPermission(READ_DEVICE_CONFIG)
public static String getProperty(@NonNull String namespace, @NonNull String name) {
// Fetch all properties for the namespace at once and cache them in the local process, so we
@@ -496,7 +489,6 @@ public final class DeviceConfig {
* @hide
*/
@SystemApi
- @TestApi
@NonNull
@RequiresPermission(READ_DEVICE_CONFIG)
public static Properties getProperties(@NonNull String namespace, @NonNull String ... names) {
@@ -516,7 +508,6 @@ public final class DeviceConfig {
* @hide
*/
@SystemApi
- @TestApi
@RequiresPermission(READ_DEVICE_CONFIG)
public static String getString(@NonNull String namespace, @NonNull String name,
@Nullable String defaultValue) {
@@ -535,7 +526,6 @@ public final class DeviceConfig {
* @hide
*/
@SystemApi
- @TestApi
@RequiresPermission(READ_DEVICE_CONFIG)
public static boolean getBoolean(@NonNull String namespace, @NonNull String name,
boolean defaultValue) {
@@ -554,7 +544,6 @@ public final class DeviceConfig {
* @hide
*/
@SystemApi
- @TestApi
@RequiresPermission(READ_DEVICE_CONFIG)
public static int getInt(@NonNull String namespace, @NonNull String name, int defaultValue) {
String value = getProperty(namespace, name);
@@ -580,7 +569,6 @@ public final class DeviceConfig {
* @hide
*/
@SystemApi
- @TestApi
@RequiresPermission(READ_DEVICE_CONFIG)
public static long getLong(@NonNull String namespace, @NonNull String name, long defaultValue) {
String value = getProperty(namespace, name);
@@ -606,7 +594,6 @@ public final class DeviceConfig {
* @hide
*/
@SystemApi
- @TestApi
@RequiresPermission(READ_DEVICE_CONFIG)
public static float getFloat(@NonNull String namespace, @NonNull String name,
float defaultValue) {
@@ -642,7 +629,6 @@ public final class DeviceConfig {
* @see #resetToDefaults(int, String).
*/
@SystemApi
- @TestApi
@RequiresPermission(WRITE_DEVICE_CONFIG)
public static boolean setProperty(@NonNull String namespace, @NonNull String name,
@Nullable String value, boolean makeDefault) {
@@ -666,7 +652,6 @@ public final class DeviceConfig {
* @hide
*/
@SystemApi
- @TestApi
@RequiresPermission(WRITE_DEVICE_CONFIG)
public static boolean setProperties(@NonNull Properties properties) throws BadConfigException {
ContentResolver contentResolver = ActivityThread.currentApplication().getContentResolver();
@@ -686,7 +671,6 @@ public final class DeviceConfig {
* @see #setProperty(String, String, String, boolean)
*/
@SystemApi
- @TestApi
@RequiresPermission(WRITE_DEVICE_CONFIG)
public static void resetToDefaults(@ResetMode int resetMode, @Nullable String namespace) {
ContentResolver contentResolver = ActivityThread.currentApplication().getContentResolver();
@@ -708,7 +692,6 @@ public final class DeviceConfig {
* @see #removeOnPropertiesChangedListener(OnPropertiesChangedListener)
*/
@SystemApi
- @TestApi
@RequiresPermission(READ_DEVICE_CONFIG)
public static void addOnPropertiesChangedListener(
@NonNull String namespace,
@@ -743,7 +726,6 @@ public final class DeviceConfig {
* @see #addOnPropertiesChangedListener(String, Executor, OnPropertiesChangedListener)
*/
@SystemApi
- @TestApi
public static void removeOnPropertiesChangedListener(
@NonNull OnPropertiesChangedListener onPropertiesChangedListener) {
Preconditions.checkNotNull(onPropertiesChangedListener);
@@ -878,7 +860,6 @@ public final class DeviceConfig {
* @hide
*/
@SystemApi
- @TestApi
public interface OnPropertiesChangedListener {
/**
* Called when one or more properties have changed, providing a Properties object with all
@@ -899,7 +880,6 @@ public final class DeviceConfig {
* @hide
*/
@SystemApi
- @TestApi
public static class BadConfigException extends Exception {}
/**
@@ -908,7 +888,6 @@ public final class DeviceConfig {
* @hide
*/
@SystemApi
- @TestApi
public static class Properties {
private final String mNamespace;
private final HashMap<String, String> mMap;
diff --git a/core/java/android/provider/DocumentsContract.java b/core/java/android/provider/DocumentsContract.java
index 8f69edb982cb..062d92900643 100644
--- a/core/java/android/provider/DocumentsContract.java
+++ b/core/java/android/provider/DocumentsContract.java
@@ -22,7 +22,6 @@ import static com.android.internal.util.Preconditions.checkCollectionNotEmpty;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.SystemApi;
-import android.annotation.TestApi;
import android.compat.annotation.UnsupportedAppUsage;
import android.content.ContentProvider;
import android.content.ContentResolver;
@@ -1304,7 +1303,6 @@ public final class DocumentsContract {
* {@hide}
*/
@SystemApi
- @TestApi
public static @NonNull Uri setManageMode(@NonNull Uri uri) {
Preconditions.checkNotNull(uri, "uri can not be null");
return uri.buildUpon().appendQueryParameter(PARAM_MANAGE, "true").build();
@@ -1316,7 +1314,6 @@ public final class DocumentsContract {
* {@hide}
*/
@SystemApi
- @TestApi
public static boolean isManageMode(@NonNull Uri uri) {
Preconditions.checkNotNull(uri, "uri can not be null");
return uri.getBooleanQueryParameter(PARAM_MANAGE, false);
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index 68d8d82aeb0c..59934acdc2f0 100644
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -229,7 +229,6 @@ public final class Settings {
*/
@SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
@SystemApi
- @TestApi
public static final String ACTION_TETHER_PROVISIONING_UI =
"android.settings.TETHER_PROVISIONING_UI";
@@ -1053,7 +1052,6 @@ public final class Settings {
*
* @hide
*/
- @TestApi
@SystemApi
@SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
public static final String ACTION_MANAGE_APP_OVERLAY_PERMISSION =
@@ -2017,7 +2015,6 @@ public final class Settings {
* @hide
*/
@SystemApi
- @TestApi
@SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
public static final String ACTION_ENTERPRISE_PRIVACY_SETTINGS
= "android.settings.ENTERPRISE_PRIVACY_SETTINGS";
@@ -2100,7 +2097,6 @@ public final class Settings {
* @hide
*/
@SystemApi
- @TestApi
@SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
public static final String ACTION_REQUEST_ENABLE_CONTENT_CAPTURE =
"android.settings.REQUEST_ENABLE_CONTENT_CAPTURE";
@@ -5580,7 +5576,6 @@ public final class Settings {
* @hide
*/
@SystemApi
- @TestApi
@RequiresPermission(Manifest.permission.WRITE_SECURE_SETTINGS)
public static void resetToDefaults(@NonNull ContentResolver resolver,
@Nullable String tag) {
@@ -6051,7 +6046,6 @@ public final class Settings {
* @hide
*/
@SystemApi
- @TestApi
public static final String AUTOFILL_FEATURE_FIELD_CLASSIFICATION =
"autofill_field_classification";
@@ -6085,7 +6079,6 @@ public final class Settings {
* @hide
*/
@SystemApi
- @TestApi
public static final String AUTOFILL_USER_DATA_MAX_USER_DATA_SIZE =
"autofill_user_data_max_user_data_size";
@@ -6096,7 +6089,6 @@ public final class Settings {
* @hide
*/
@SystemApi
- @TestApi
public static final String AUTOFILL_USER_DATA_MAX_FIELD_CLASSIFICATION_IDS_SIZE =
"autofill_user_data_max_field_classification_size";
@@ -6107,7 +6099,6 @@ public final class Settings {
* @hide
*/
@SystemApi
- @TestApi
public static final String AUTOFILL_USER_DATA_MAX_CATEGORY_COUNT =
"autofill_user_data_max_category_count";
@@ -6117,7 +6108,6 @@ public final class Settings {
* @hide
*/
@SystemApi
- @TestApi
public static final String AUTOFILL_USER_DATA_MAX_VALUE_LENGTH =
"autofill_user_data_max_value_length";
@@ -6127,7 +6117,6 @@ public final class Settings {
* @hide
*/
@SystemApi
- @TestApi
public static final String AUTOFILL_USER_DATA_MIN_VALUE_LENGTH =
"autofill_user_data_min_value_length";
@@ -6177,7 +6166,6 @@ public final class Settings {
* @hide
*/
@SystemApi
- @TestApi
public static final String USER_SETUP_COMPLETE = "user_setup_complete";
/**
@@ -6553,7 +6541,6 @@ public final class Settings {
* @hide
*/
@SystemApi
- @TestApi
public static final String LOCK_SCREEN_ALLOW_PRIVATE_NOTIFICATIONS =
"lock_screen_allow_private_notifications";
@@ -7841,7 +7828,6 @@ public final class Settings {
* @hide
*/
@SystemApi
- @TestApi
public static final String DOZE_ALWAYS_ON = "doze_always_on";
/**
@@ -8274,7 +8260,6 @@ public final class Settings {
* @hide
*/
@SystemApi
- @TestApi
public static final String LOCK_SCREEN_SHOW_NOTIFICATIONS =
"lock_screen_show_notifications";
@@ -8961,7 +8946,6 @@ public final class Settings {
* @hide
*/
@SystemApi
- @TestApi
public static final String LOCATION_ACCESS_CHECK_INTERVAL_MILLIS =
"location_access_check_interval_millis";
@@ -8970,7 +8954,6 @@ public final class Settings {
* @hide
*/
@SystemApi
- @TestApi
public static final String LOCATION_ACCESS_CHECK_DELAY_MILLIS =
"location_access_check_delay_millis";
@@ -10391,7 +10374,6 @@ public final class Settings {
* @hide
*/
@SystemApi
- @TestApi
public static final String TETHER_OFFLOAD_DISABLED = "tether_offload_disabled";
/**
@@ -10452,14 +10434,6 @@ public final class Settings {
"webview_data_reduction_proxy_key";
/**
- * Whether or not the WebView fallback mechanism should be enabled.
- * 0=disabled, 1=enabled.
- * @hide
- */
- public static final String WEBVIEW_FALLBACK_LOGIC_ENABLED =
- "webview_fallback_logic_enabled";
-
- /**
* Name of the package used as WebView provider (if unset the provider is instead determined
* by the system).
* @hide
@@ -12367,37 +12341,34 @@ public final class Settings {
* to dumpable apps that opt-in.
* @hide
*/
- public static final String GLOBAL_SETTINGS_ANGLE_DEBUG_PACKAGE =
- "angle_debug_package";
+ public static final String ANGLE_DEBUG_PACKAGE = "angle_debug_package";
/**
* Force all PKGs to use ANGLE, regardless of any other settings
* The value is a boolean (1 or 0).
* @hide
*/
- public static final String GLOBAL_SETTINGS_ANGLE_GL_DRIVER_ALL_ANGLE =
- "angle_gl_driver_all_angle";
+ public static final String ANGLE_GL_DRIVER_ALL_ANGLE = "angle_gl_driver_all_angle";
/**
* List of PKGs that have an OpenGL driver selected
* @hide
*/
- public static final String GLOBAL_SETTINGS_ANGLE_GL_DRIVER_SELECTION_PKGS =
+ public static final String ANGLE_GL_DRIVER_SELECTION_PKGS =
"angle_gl_driver_selection_pkgs";
/**
* List of selected OpenGL drivers, corresponding to the PKGs in GLOBAL_SETTINGS_DRIVER_PKGS
* @hide
*/
- public static final String GLOBAL_SETTINGS_ANGLE_GL_DRIVER_SELECTION_VALUES =
+ public static final String ANGLE_GL_DRIVER_SELECTION_VALUES =
"angle_gl_driver_selection_values";
/**
* List of package names that should check ANGLE rules
* @hide
*/
- public static final String GLOBAL_SETTINGS_ANGLE_ALLOWLIST =
- "angle_allowlist";
+ public static final String ANGLE_ALLOWLIST = "angle_allowlist";
/**
* Lists of ANGLE EGL features for debugging.
@@ -12413,8 +12384,7 @@ public final class Settings {
* The value is a boolean (1 or 0).
* @hide
*/
- public static final String GLOBAL_SETTINGS_SHOW_ANGLE_IN_USE_DIALOG_BOX =
- "show_angle_in_use_dialog_box";
+ public static final String SHOW_ANGLE_IN_USE_DIALOG_BOX = "show_angle_in_use_dialog_box";
/**
* Updatable driver global preference for all Apps.
@@ -13373,7 +13343,6 @@ public final class Settings {
* @hide
*/
@SystemApi
- @TestApi
public static final String AUTOFILL_COMPAT_MODE_ALLOWED_PACKAGES =
"autofill_compat_mode_allowed_packages";
@@ -14551,6 +14520,16 @@ public final class Settings {
public static final String SHOW_PEOPLE_SPACE = "show_people_space";
/**
+ * Which types of conversations to show in People Space.
+ * Values are:
+ * 0: All conversations (default)
+ * 1: Priority conversations only
+ * @hide
+ */
+ public static final String PEOPLE_SPACE_CONVERSATION_TYPE =
+ "people_space_conversation_type";
+
+ /**
* Whether to show new lockscreen & AOD UI.
* Values are:
* 0: Disabled (default)
diff --git a/core/java/android/provider/Telephony.java b/core/java/android/provider/Telephony.java
index 79d6bb4a062a..2c735fd9012f 100644
--- a/core/java/android/provider/Telephony.java
+++ b/core/java/android/provider/Telephony.java
@@ -4045,7 +4045,6 @@ public final class Telephony {
* @hide
*/
@SystemApi
- @TestApi
public static final class CellBroadcasts implements BaseColumns {
/**
diff --git a/core/java/android/service/appprediction/AppPredictionService.java b/core/java/android/service/appprediction/AppPredictionService.java
index be20570ef62d..2d8aee567010 100644
--- a/core/java/android/service/appprediction/AppPredictionService.java
+++ b/core/java/android/service/appprediction/AppPredictionService.java
@@ -22,7 +22,6 @@ import android.annotation.MainThread;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.SystemApi;
-import android.annotation.TestApi;
import android.app.Service;
import android.app.prediction.AppPredictionContext;
import android.app.prediction.AppPredictionSessionId;
@@ -52,7 +51,6 @@ import java.util.function.Consumer;
* @hide
*/
@SystemApi
-@TestApi
public abstract class AppPredictionService extends Service {
private static final String TAG = "AppPredictionService";
diff --git a/core/java/android/service/autofill/AutofillFieldClassificationService.java b/core/java/android/service/autofill/AutofillFieldClassificationService.java
index 28842a7fa1d7..9d9b881ebdfc 100644
--- a/core/java/android/service/autofill/AutofillFieldClassificationService.java
+++ b/core/java/android/service/autofill/AutofillFieldClassificationService.java
@@ -20,7 +20,6 @@ import static com.android.internal.util.function.pooled.PooledLambda.obtainMessa
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.SystemApi;
-import android.annotation.TestApi;
import android.app.Service;
import android.content.Intent;
import android.os.Bundle;
@@ -53,7 +52,6 @@ import java.util.Map;
* {@hide}
*/
@SystemApi
-@TestApi
public abstract class AutofillFieldClassificationService extends Service {
private static final String TAG = "AutofillFieldClassificationService";
@@ -121,7 +119,6 @@ public abstract class AutofillFieldClassificationService extends Service {
/** @hide */
@SystemApi
- @TestApi
public AutofillFieldClassificationService() {
}
diff --git a/core/java/android/service/autofill/BatchUpdates.java b/core/java/android/service/autofill/BatchUpdates.java
index e0b1c2f91ed2..d15514dfb899 100644
--- a/core/java/android/service/autofill/BatchUpdates.java
+++ b/core/java/android/service/autofill/BatchUpdates.java
@@ -117,7 +117,7 @@ public final class BatchUpdates implements Parcelable {
public Builder transformChild(int id, @NonNull Transformation transformation) {
throwIfDestroyed();
Preconditions.checkArgument((transformation instanceof InternalTransformation),
- "not provided by Android System: " + transformation);
+ "not provided by Android System: %s", transformation);
if (mTransformations == null) {
mTransformations = new ArrayList<>();
}
diff --git a/core/java/android/service/autofill/CustomDescription.java b/core/java/android/service/autofill/CustomDescription.java
index e274460cdf03..6df01545c09f 100644
--- a/core/java/android/service/autofill/CustomDescription.java
+++ b/core/java/android/service/autofill/CustomDescription.java
@@ -180,7 +180,7 @@ public final class CustomDescription implements Parcelable {
public Builder addChild(int id, @NonNull Transformation transformation) {
throwIfDestroyed();
Preconditions.checkArgument((transformation instanceof InternalTransformation),
- "not provided by Android System: " + transformation);
+ "not provided by Android System: %s", transformation);
if (mTransformations == null) {
mTransformations = new ArrayList<>();
}
@@ -275,7 +275,7 @@ public final class CustomDescription implements Parcelable {
public Builder batchUpdate(@NonNull Validator condition, @NonNull BatchUpdates updates) {
throwIfDestroyed();
Preconditions.checkArgument((condition instanceof InternalValidator),
- "not provided by Android System: " + condition);
+ "not provided by Android System: %s", condition);
Preconditions.checkNotNull(updates);
if (mUpdates == null) {
mUpdates = new ArrayList<>();
@@ -329,7 +329,7 @@ public final class CustomDescription implements Parcelable {
public Builder addOnClickAction(int id, @NonNull OnClickAction action) {
throwIfDestroyed();
Preconditions.checkArgument((action instanceof InternalOnClickAction),
- "not provided by Android System: " + action);
+ "not provided by Android System: %s", action);
if (mActions == null) {
mActions = new SparseArray<InternalOnClickAction>();
}
diff --git a/core/java/android/service/autofill/Dataset.java b/core/java/android/service/autofill/Dataset.java
index 2d99c413cc89..18d79927388b 100644
--- a/core/java/android/service/autofill/Dataset.java
+++ b/core/java/android/service/autofill/Dataset.java
@@ -21,7 +21,6 @@ import static android.view.autofill.Helper.sDebug;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.SystemApi;
-import android.annotation.TestApi;
import android.content.IntentSender;
import android.os.Parcel;
import android.os.Parcelable;
@@ -249,7 +248,6 @@ public final class Dataset implements Parcelable {
* @hide
*/
@SystemApi
- @TestApi
public Builder(@NonNull InlinePresentation inlinePresentation) {
Preconditions.checkNotNull(inlinePresentation, "inlinePresentation must be non-null");
mInlinePresentation = inlinePresentation;
@@ -604,7 +602,6 @@ public final class Dataset implements Parcelable {
* @hide
*/
@SystemApi
- @TestApi
public @NonNull Builder setFieldInlinePresentation(@NonNull AutofillId id,
@Nullable AutofillValue value, @Nullable Pattern filter,
@NonNull InlinePresentation inlinePresentation) {
diff --git a/core/java/android/service/autofill/InlineSuggestionRenderService.java b/core/java/android/service/autofill/InlineSuggestionRenderService.java
index 839caff5c3d4..cdcd65910974 100644
--- a/core/java/android/service/autofill/InlineSuggestionRenderService.java
+++ b/core/java/android/service/autofill/InlineSuggestionRenderService.java
@@ -20,7 +20,6 @@ import static com.android.internal.util.function.pooled.PooledLambda.obtainMessa
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.SystemApi;
-import android.annotation.TestApi;
import android.app.Service;
import android.content.Intent;
import android.content.IntentSender;
@@ -51,7 +50,6 @@ import java.lang.ref.WeakReference;
* {@hide}
*/
@SystemApi
-@TestApi
public abstract class InlineSuggestionRenderService extends Service {
private static final String TAG = "InlineSuggestionRenderService";
diff --git a/core/java/android/service/autofill/SaveInfo.java b/core/java/android/service/autofill/SaveInfo.java
index e640eecc03c0..619bfa225cf1 100644
--- a/core/java/android/service/autofill/SaveInfo.java
+++ b/core/java/android/service/autofill/SaveInfo.java
@@ -687,7 +687,7 @@ public final class SaveInfo implements Parcelable {
public @NonNull Builder setValidator(@NonNull Validator validator) {
throwIfDestroyed();
Preconditions.checkArgument((validator instanceof InternalValidator),
- "not provided by Android System: " + validator);
+ "not provided by Android System: %s", validator);
mValidator = (InternalValidator) validator;
return this;
}
@@ -734,7 +734,7 @@ public final class SaveInfo implements Parcelable {
throwIfDestroyed();
Preconditions.checkArgument(!ArrayUtils.isEmpty(ids), "ids cannot be empty or null");
Preconditions.checkArgument((sanitizer instanceof InternalSanitizer),
- "not provided by Android System: " + sanitizer);
+ "not provided by Android System: %s", sanitizer);
if (mSanitizers == null) {
mSanitizers = new ArrayMap<>();
diff --git a/core/java/android/service/autofill/UserData.java b/core/java/android/service/autofill/UserData.java
index 7814f70b612b..eaffc92c1d6b 100644
--- a/core/java/android/service/autofill/UserData.java
+++ b/core/java/android/service/autofill/UserData.java
@@ -344,11 +344,11 @@ public final class UserData implements FieldClassificationUserData, Parcelable {
if (!mUniqueCategoryIds.contains(categoryId)) {
// New category - check size
Preconditions.checkState(mUniqueCategoryIds.size() < getMaxCategoryCount(),
- "already added " + mUniqueCategoryIds.size() + " unique category ids");
+ "already added %d unique category ids", mUniqueCategoryIds.size());
}
Preconditions.checkState(mValues.size() < getMaxUserDataSize(),
- "already added " + mValues.size() + " elements");
+ "already added %d elements", mValues.size());
addMapping(value, categoryId);
return this;
diff --git a/core/java/android/service/autofill/Validators.java b/core/java/android/service/autofill/Validators.java
index 0f1ba9891a99..0a2115848bd5 100644
--- a/core/java/android/service/autofill/Validators.java
+++ b/core/java/android/service/autofill/Validators.java
@@ -67,7 +67,7 @@ public final class Validators {
@NonNull
public static Validator not(@NonNull Validator validator) {
Preconditions.checkArgument(validator instanceof InternalValidator,
- "validator not provided by Android System: " + validator);
+ "validator not provided by Android System: %s", validator);
return new NegationValidator((InternalValidator) validator);
}
@@ -78,7 +78,7 @@ public final class Validators {
for (int i = 0; i < validators.length; i++) {
Preconditions.checkArgument((validators[i] instanceof InternalValidator),
- "element " + i + " not provided by Android System: " + validators[i]);
+ "element %d not provided by Android System: %s", i, validators[i]);
internals[i] = (InternalValidator) validators[i];
}
return internals;
diff --git a/core/java/android/service/autofill/augmented/AugmentedAutofillService.java b/core/java/android/service/autofill/augmented/AugmentedAutofillService.java
index 620c457024b8..b34c2dceeee8 100644
--- a/core/java/android/service/autofill/augmented/AugmentedAutofillService.java
+++ b/core/java/android/service/autofill/augmented/AugmentedAutofillService.java
@@ -25,7 +25,6 @@ import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.SystemApi;
-import android.annotation.TestApi;
import android.app.Service;
import android.content.ComponentName;
import android.content.Intent;
@@ -70,7 +69,6 @@ import java.util.List;
* @hide
*/
@SystemApi
-@TestApi
public abstract class AugmentedAutofillService extends Service {
private static final String TAG = AugmentedAutofillService.class.getSimpleName();
diff --git a/core/java/android/service/autofill/augmented/FillCallback.java b/core/java/android/service/autofill/augmented/FillCallback.java
index fc3baf1c9836..9fc7f34ec0ef 100644
--- a/core/java/android/service/autofill/augmented/FillCallback.java
+++ b/core/java/android/service/autofill/augmented/FillCallback.java
@@ -20,7 +20,6 @@ import static android.service.autofill.augmented.AugmentedAutofillService.sDebug
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.SystemApi;
-import android.annotation.TestApi;
import android.os.Bundle;
import android.service.autofill.Dataset;
import android.service.autofill.augmented.AugmentedAutofillService.AutofillProxy;
@@ -34,7 +33,6 @@ import java.util.List;
* @hide
*/
@SystemApi
-@TestApi
public final class FillCallback {
private static final String TAG = FillCallback.class.getSimpleName();
diff --git a/core/java/android/service/autofill/augmented/FillController.java b/core/java/android/service/autofill/augmented/FillController.java
index 7d552d62fa72..7cd674e847fd 100644
--- a/core/java/android/service/autofill/augmented/FillController.java
+++ b/core/java/android/service/autofill/augmented/FillController.java
@@ -19,7 +19,6 @@ import static android.service.autofill.augmented.AugmentedAutofillService.sDebug
import android.annotation.NonNull;
import android.annotation.SystemApi;
-import android.annotation.TestApi;
import android.os.RemoteException;
import android.service.autofill.augmented.AugmentedAutofillService.AutofillProxy;
import android.util.Log;
@@ -37,7 +36,6 @@ import java.util.List;
* @hide
*/
@SystemApi
-@TestApi
public final class FillController {
private static final String TAG = FillController.class.getSimpleName();
diff --git a/core/java/android/service/autofill/augmented/FillResponse.java b/core/java/android/service/autofill/augmented/FillResponse.java
index f72eb782c407..53484cf200c4 100644
--- a/core/java/android/service/autofill/augmented/FillResponse.java
+++ b/core/java/android/service/autofill/augmented/FillResponse.java
@@ -18,7 +18,6 @@ package android.service.autofill.augmented;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.SystemApi;
-import android.annotation.TestApi;
import android.os.Bundle;
import android.service.autofill.Dataset;
@@ -33,7 +32,6 @@ import java.util.List;
* @hide
*/
@SystemApi
-@TestApi
@DataClass(
genBuilder = true,
genHiddenGetters = true)
diff --git a/core/java/android/service/autofill/augmented/FillWindow.java b/core/java/android/service/autofill/augmented/FillWindow.java
index 8e866466e8df..d4f7e114c291 100644
--- a/core/java/android/service/autofill/augmented/FillWindow.java
+++ b/core/java/android/service/autofill/augmented/FillWindow.java
@@ -23,7 +23,6 @@ import static com.android.internal.util.function.pooled.PooledLambda.obtainMessa
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.SystemApi;
-import android.annotation.TestApi;
import android.graphics.Rect;
import android.os.Handler;
import android.os.Looper;
@@ -64,7 +63,6 @@ import java.lang.ref.WeakReference;
* @hide
*/
@SystemApi
-@TestApi
public final class FillWindow implements AutoCloseable {
private static final String TAG = FillWindow.class.getSimpleName();
diff --git a/core/java/android/service/autofill/augmented/PresentationParams.java b/core/java/android/service/autofill/augmented/PresentationParams.java
index 8b3a001f58e6..fe78d2218266 100644
--- a/core/java/android/service/autofill/augmented/PresentationParams.java
+++ b/core/java/android/service/autofill/augmented/PresentationParams.java
@@ -18,7 +18,6 @@ package android.service.autofill.augmented;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.SystemApi;
-import android.annotation.TestApi;
import android.graphics.Rect;
import android.service.autofill.augmented.AugmentedAutofillService.AutofillProxy;
import android.view.View;
@@ -36,7 +35,6 @@ import java.io.PrintWriter;
* @hide
*/
@SystemApi
-@TestApi
public abstract class PresentationParams {
// /** @hide */
@@ -61,7 +59,6 @@ public abstract class PresentationParams {
* @hide
*/
@SystemApi
- @TestApi
public abstract static class Area {
/** @hide */
diff --git a/core/java/android/service/contentcapture/ActivityEvent.java b/core/java/android/service/contentcapture/ActivityEvent.java
index b741cff9328e..1188a3f1021e 100644
--- a/core/java/android/service/contentcapture/ActivityEvent.java
+++ b/core/java/android/service/contentcapture/ActivityEvent.java
@@ -19,7 +19,6 @@ package android.service.contentcapture;
import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.SystemApi;
-import android.annotation.TestApi;
import android.app.usage.UsageEvents.Event;
import android.content.ComponentName;
import android.os.Parcel;
@@ -34,7 +33,6 @@ import java.lang.annotation.RetentionPolicy;
* @hide
*/
@SystemApi
-@TestApi
public final class ActivityEvent implements Parcelable {
/**
diff --git a/core/java/android/service/contentcapture/ContentCaptureService.java b/core/java/android/service/contentcapture/ContentCaptureService.java
index 84f602820f4a..3c44cfd4c7f6 100644
--- a/core/java/android/service/contentcapture/ContentCaptureService.java
+++ b/core/java/android/service/contentcapture/ContentCaptureService.java
@@ -26,7 +26,6 @@ import android.annotation.CallSuper;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.SystemApi;
-import android.annotation.TestApi;
import android.app.Service;
import android.content.ComponentName;
import android.content.ContentCaptureOptions;
@@ -74,7 +73,6 @@ import java.util.function.Consumer;
* @hide
*/
@SystemApi
-@TestApi
public abstract class ContentCaptureService extends Service {
private static final String TAG = ContentCaptureService.class.getSimpleName();
@@ -344,7 +342,6 @@ public abstract class ContentCaptureService extends Service {
* @hide
*/
@SystemApi
- @TestApi
public void onDataShareRequest(@NonNull DataShareRequest request,
@NonNull DataShareCallback callback) {
if (sVerbose) Log.v(TAG, "onDataShareRequest()");
diff --git a/core/java/android/service/contentcapture/DataShareCallback.java b/core/java/android/service/contentcapture/DataShareCallback.java
index 5df8a4b174bf..e3c7bb3cd24f 100644
--- a/core/java/android/service/contentcapture/DataShareCallback.java
+++ b/core/java/android/service/contentcapture/DataShareCallback.java
@@ -19,7 +19,6 @@ package android.service.contentcapture;
import android.annotation.CallbackExecutor;
import android.annotation.NonNull;
import android.annotation.SystemApi;
-import android.annotation.TestApi;
import java.util.concurrent.Executor;
@@ -33,7 +32,6 @@ import java.util.concurrent.Executor;
* @hide
**/
@SystemApi
-@TestApi
public interface DataShareCallback {
/** Accept the data share.
diff --git a/core/java/android/service/contentcapture/DataShareReadAdapter.java b/core/java/android/service/contentcapture/DataShareReadAdapter.java
index 8cd9eea1e6e0..4526aba6933b 100644
--- a/core/java/android/service/contentcapture/DataShareReadAdapter.java
+++ b/core/java/android/service/contentcapture/DataShareReadAdapter.java
@@ -18,7 +18,6 @@ package android.service.contentcapture;
import android.annotation.NonNull;
import android.annotation.SystemApi;
-import android.annotation.TestApi;
import android.os.ParcelFileDescriptor;
import android.view.contentcapture.ContentCaptureManager.DataShareError;
@@ -29,7 +28,6 @@ import android.view.contentcapture.ContentCaptureManager.DataShareError;
* @hide
**/
@SystemApi
-@TestApi
public interface DataShareReadAdapter {
/**
diff --git a/core/java/android/service/contentcapture/SnapshotData.java b/core/java/android/service/contentcapture/SnapshotData.java
index 5b3930ab6336..bf469b4b3ad8 100644
--- a/core/java/android/service/contentcapture/SnapshotData.java
+++ b/core/java/android/service/contentcapture/SnapshotData.java
@@ -19,7 +19,6 @@ package android.service.contentcapture;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.SystemApi;
-import android.annotation.TestApi;
import android.app.assist.AssistContent;
import android.app.assist.AssistStructure;
import android.os.Bundle;
@@ -32,7 +31,6 @@ import android.os.Parcelable;
* @hide
*/
@SystemApi
-@TestApi
public final class SnapshotData implements Parcelable {
private final @NonNull Bundle mAssistData;
diff --git a/core/java/android/service/notification/Adjustment.java b/core/java/android/service/notification/Adjustment.java
index 8464c6df4425..4b25c8832068 100644
--- a/core/java/android/service/notification/Adjustment.java
+++ b/core/java/android/service/notification/Adjustment.java
@@ -19,7 +19,6 @@ import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.StringDef;
import android.annotation.SystemApi;
-import android.annotation.TestApi;
import android.app.Notification;
import android.os.Bundle;
import android.os.Parcel;
@@ -42,7 +41,6 @@ import java.lang.annotation.RetentionPolicy;
* @hide
*/
@SystemApi
-@TestApi
public final class Adjustment implements Parcelable {
private final String mPackage;
private final String mKey;
@@ -148,7 +146,6 @@ public final class Adjustment implements Parcelable {
* @hide
*/
@SystemApi
- @TestApi
public Adjustment(String pkg, String key, Bundle signals, CharSequence explanation, int user) {
mPackage = pkg;
mKey = key;
@@ -232,7 +229,6 @@ public final class Adjustment implements Parcelable {
/** @hide */
@SystemApi
- @TestApi
public int getUser() {
return mUser;
}
diff --git a/core/java/android/service/notification/NotificationAssistantService.java b/core/java/android/service/notification/NotificationAssistantService.java
index 975e75ccaeeb..632014936425 100644
--- a/core/java/android/service/notification/NotificationAssistantService.java
+++ b/core/java/android/service/notification/NotificationAssistantService.java
@@ -23,7 +23,6 @@ import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.SdkConstant;
import android.annotation.SystemApi;
-import android.annotation.TestApi;
import android.app.Notification;
import android.app.NotificationChannel;
import android.app.NotificationManager;
@@ -66,7 +65,6 @@ import java.util.List;
* @hide
*/
@SystemApi
-@TestApi
public abstract class NotificationAssistantService extends NotificationListenerService {
private static final String TAG = "NotificationAssistants";
diff --git a/core/java/android/service/notification/NotificationListenerService.java b/core/java/android/service/notification/NotificationListenerService.java
index e1b2dfb3c3f0..25f140f29e00 100644
--- a/core/java/android/service/notification/NotificationListenerService.java
+++ b/core/java/android/service/notification/NotificationListenerService.java
@@ -22,7 +22,6 @@ import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.SdkConstant;
import android.annotation.SystemApi;
-import android.annotation.TestApi;
import android.app.ActivityManager;
import android.app.INotificationManager;
import android.app.Notification;
@@ -452,7 +451,6 @@ public abstract class NotificationListenerService extends Service {
*
* @hide
*/
- @TestApi
@SystemApi
public void onNotificationRemoved(@NonNull StatusBarNotification sbn,
@NonNull RankingMap rankingMap, @NonNull NotificationStats stats, int reason) {
diff --git a/core/java/android/service/notification/NotificationStats.java b/core/java/android/service/notification/NotificationStats.java
index 2cd8b8ba42d9..206e4fa4fb11 100644
--- a/core/java/android/service/notification/NotificationStats.java
+++ b/core/java/android/service/notification/NotificationStats.java
@@ -19,7 +19,6 @@ import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.SystemApi;
-import android.annotation.TestApi;
import android.app.RemoteInput;
import android.os.Parcel;
import android.os.Parcelable;
@@ -31,7 +30,6 @@ import java.lang.annotation.RetentionPolicy;
* Information about how the user has interacted with a given notification.
* @hide
*/
-@TestApi
@SystemApi
public final class NotificationStats implements Parcelable {
diff --git a/core/java/android/service/notification/SnoozeCriterion.java b/core/java/android/service/notification/SnoozeCriterion.java
index eb624c9d85f4..d3da07a6fb80 100644
--- a/core/java/android/service/notification/SnoozeCriterion.java
+++ b/core/java/android/service/notification/SnoozeCriterion.java
@@ -17,7 +17,6 @@ package android.service.notification;
import android.annotation.Nullable;
import android.annotation.SystemApi;
-import android.annotation.TestApi;
import android.os.Parcel;
import android.os.Parcelable;
@@ -27,7 +26,6 @@ import android.os.Parcelable;
* @hide
*/
@SystemApi
-@TestApi
public final class SnoozeCriterion implements Parcelable {
private final String mId;
private final CharSequence mExplanation;
diff --git a/core/java/android/service/textclassifier/TextClassifierService.java b/core/java/android/service/textclassifier/TextClassifierService.java
index 93faa5872a69..1fb18fab3775 100644
--- a/core/java/android/service/textclassifier/TextClassifierService.java
+++ b/core/java/android/service/textclassifier/TextClassifierService.java
@@ -22,7 +22,6 @@ import android.annotation.MainThread;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.SystemApi;
-import android.annotation.TestApi;
import android.app.Service;
import android.content.ComponentName;
import android.content.Context;
@@ -88,7 +87,6 @@ import java.util.concurrent.Executors;
* @hide
*/
@SystemApi
-@TestApi
public abstract class TextClassifierService extends Service {
private static final String LOG_TAG = "TextClassifierService";
diff --git a/core/java/android/service/wallpaper/WallpaperService.java b/core/java/android/service/wallpaper/WallpaperService.java
index 6a70a856e09a..4249e5c20d3b 100644
--- a/core/java/android/service/wallpaper/WallpaperService.java
+++ b/core/java/android/service/wallpaper/WallpaperService.java
@@ -20,6 +20,7 @@ import static android.graphics.Matrix.MSCALE_X;
import static android.graphics.Matrix.MSCALE_Y;
import static android.graphics.Matrix.MSKEW_X;
import static android.graphics.Matrix.MSKEW_Y;
+import static android.view.View.SYSTEM_UI_FLAG_VISIBLE;
import android.annotation.FloatRange;
import android.annotation.Nullable;
@@ -33,6 +34,7 @@ import android.app.WallpaperManager;
import android.compat.annotation.UnsupportedAppUsage;
import android.content.Context;
import android.content.Intent;
+import android.content.res.Configuration;
import android.content.res.TypedArray;
import android.graphics.Bitmap;
import android.graphics.Canvas;
@@ -878,7 +880,6 @@ public abstract class WallpaperService extends Service {
if (mSession.addToDisplay(mWindow, mLayout, View.VISIBLE,
mDisplay.getDisplayId(), mInsetsState, mWinFrames.frame,
- mWinFrames.contentInsets, mWinFrames.stableInsets,
mWinFrames.displayCutout, inputChannel, mInsetsState,
mTempControls) < 0) {
Log.w(TAG, "Failed to add window while updating wallpaper surface.");
@@ -914,20 +915,22 @@ public abstract class WallpaperService extends Service {
int w = mWinFrames.frame.width();
int h = mWinFrames.frame.height();
+ final DisplayCutout rawCutout = mWinFrames.displayCutout.get();
+ final Configuration config = getResources().getConfiguration();
+ final Rect visibleFrame = new Rect(mWinFrames.frame);
+ visibleFrame.intersect(mInsetsState.getDisplayFrame());
+ WindowInsets windowInsets = mInsetsState.calculateInsets(visibleFrame,
+ null /* ignoringVisibilityState */, config.isScreenRound(),
+ false /* alwaysConsumeSystemBars */, rawCutout, mLayout.softInputMode,
+ mLayout.flags, SYSTEM_UI_FLAG_VISIBLE, mLayout.type,
+ config.windowConfiguration.getWindowingMode(), null /* typeSideMap */);
+
if (!fixedSize) {
final Rect padding = mIWallpaperEngine.mDisplayPadding;
w += padding.left + padding.right;
h += padding.top + padding.bottom;
- mWinFrames.contentInsets.left += padding.left;
- mWinFrames.contentInsets.top += padding.top;
- mWinFrames.contentInsets.right += padding.right;
- mWinFrames.contentInsets.bottom += padding.bottom;
- mWinFrames.stableInsets.left += padding.left;
- mWinFrames.stableInsets.top += padding.top;
- mWinFrames.stableInsets.right += padding.right;
- mWinFrames.stableInsets.bottom += padding.bottom;
- mWinFrames.displayCutout.set(mWinFrames.displayCutout.get().inset(
- -padding.left, -padding.top, -padding.right, -padding.bottom));
+ windowInsets = windowInsets.insetUnchecked(
+ -padding.left, -padding.top, -padding.right, -padding.bottom);
} else {
w = myWidth;
h = myHeight;
@@ -946,9 +949,12 @@ public abstract class WallpaperService extends Service {
Log.v(TAG, "Wallpaper size has changed: (" + mCurWidth + ", " + mCurHeight);
}
- final DisplayCutout displayCutout = mWinFrames.displayCutout.get();
- insetsChanged |= !mDispatchedContentInsets.equals(mWinFrames.contentInsets);
- insetsChanged |= !mDispatchedStableInsets.equals(mWinFrames.stableInsets);
+ final Rect contentInsets = windowInsets.getSystemWindowInsets().toRect();
+ final Rect stableInsets = windowInsets.getStableInsets().toRect();
+ final DisplayCutout displayCutout = windowInsets.getDisplayCutout() != null
+ ? windowInsets.getDisplayCutout() : rawCutout;
+ insetsChanged |= !mDispatchedContentInsets.equals(contentInsets);
+ insetsChanged |= !mDispatchedStableInsets.equals(stableInsets);
insetsChanged |= !mDispatchedDisplayCutout.equals(displayCutout);
mSurfaceHolder.setSurfaceFrameSize(w, h);
@@ -1008,18 +1014,13 @@ public abstract class WallpaperService extends Service {
}
if (insetsChanged) {
- mDispatchedContentInsets.set(mWinFrames.contentInsets);
- mDispatchedStableInsets.set(mWinFrames.stableInsets);
+ mDispatchedContentInsets.set(contentInsets);
+ mDispatchedStableInsets.set(stableInsets);
mDispatchedDisplayCutout = displayCutout;
- mFinalStableInsets.set(mDispatchedStableInsets);
- WindowInsets insets = new WindowInsets(mFinalSystemInsets,
- mFinalStableInsets,
- getResources().getConfiguration().isScreenRound(), false,
- mDispatchedDisplayCutout);
if (DEBUG) {
- Log.v(TAG, "dispatching insets=" + insets);
+ Log.v(TAG, "dispatching insets=" + windowInsets);
}
- onApplyWindowInsets(insets);
+ onApplyWindowInsets(windowInsets);
}
if (redrawNeeded) {
diff --git a/core/java/android/service/watchdog/ExplicitHealthCheckService.java b/core/java/android/service/watchdog/ExplicitHealthCheckService.java
index b1647fe0fcf9..49e00d6f6328 100644
--- a/core/java/android/service/watchdog/ExplicitHealthCheckService.java
+++ b/core/java/android/service/watchdog/ExplicitHealthCheckService.java
@@ -66,7 +66,6 @@ import java.util.concurrent.TimeUnit;
* </pre>
* @hide
*/
-@TestApi
@SystemApi
public abstract class ExplicitHealthCheckService extends Service {
@@ -195,7 +194,6 @@ public abstract class ExplicitHealthCheckService extends Service {
*
* @hide
*/
- @TestApi
@SystemApi
public static final class PackageConfig implements Parcelable {
private static final long DEFAULT_HEALTH_CHECK_TIMEOUT_MILLIS = TimeUnit.HOURS.toMillis(1);
diff --git a/core/java/android/telephony/PhoneStateListener.java b/core/java/android/telephony/PhoneStateListener.java
index 70c11f282a2b..6a5d5c63cb4d 100644
--- a/core/java/android/telephony/PhoneStateListener.java
+++ b/core/java/android/telephony/PhoneStateListener.java
@@ -20,7 +20,6 @@ import android.Manifest;
import android.annotation.NonNull;
import android.annotation.RequiresPermission;
import android.annotation.SystemApi;
-import android.annotation.TestApi;
import android.compat.annotation.ChangeId;
import android.compat.annotation.UnsupportedAppUsage;
import android.os.Binder;
@@ -437,7 +436,6 @@ public class PhoneStateListener {
* @hide
*/
@SystemApi
- @TestApi
@RequiresPermission(Manifest.permission.READ_ACTIVE_EMERGENCY_SESSION)
public static final int LISTEN_OUTGOING_EMERGENCY_CALL = 0x10000000;
@@ -450,7 +448,6 @@ public class PhoneStateListener {
* @hide
*/
@SystemApi
- @TestApi
@RequiresPermission(Manifest.permission.READ_ACTIVE_EMERGENCY_SESSION)
public static final int LISTEN_OUTGOING_EMERGENCY_SMS = 0x20000000;
@@ -969,7 +966,6 @@ public class PhoneStateListener {
* @hide
*/
@SystemApi
- @TestApi
@Deprecated
public void onOutgoingEmergencyCall(@NonNull EmergencyNumber placedEmergencyNumber) {
// default implementation empty
@@ -994,7 +990,6 @@ public class PhoneStateListener {
* @hide
*/
@SystemApi
- @TestApi
public void onOutgoingEmergencyCall(@NonNull EmergencyNumber placedEmergencyNumber,
int subscriptionId) {
// Default implementation for backwards compatibility
@@ -1011,7 +1006,6 @@ public class PhoneStateListener {
* @hide
*/
@SystemApi
- @TestApi
@Deprecated
public void onOutgoingEmergencySms(@NonNull EmergencyNumber sentEmergencyNumber) {
// default implementation empty
@@ -1033,7 +1027,6 @@ public class PhoneStateListener {
* @hide
*/
@SystemApi
- @TestApi
public void onOutgoingEmergencySms(@NonNull EmergencyNumber sentEmergencyNumber,
int subscriptionId) {
// Default implementation for backwards compatibility
diff --git a/core/java/android/text/TextLine.java b/core/java/android/text/TextLine.java
index 4471056e23dd..6318c4757bce 100644
--- a/core/java/android/text/TextLine.java
+++ b/core/java/android/text/TextLine.java
@@ -931,7 +931,8 @@ public class TextLine {
float totalWidth = 0;
final int numDecorations = decorations == null ? 0 : decorations.size();
- if (needWidth || (c != null && (wp.bgColor != 0 || numDecorations != 0 || runIsRtl))) {
+ if (needWidth || ((c != null || consumer != null) && (wp.bgColor != 0
+ || numDecorations != 0 || runIsRtl))) {
totalWidth = getRunAdvance(wp, start, end, contextStart, contextEnd, runIsRtl, offset);
}
diff --git a/core/java/android/text/TextShaper.java b/core/java/android/text/TextShaper.java
index dd2570401b3e..02fd7b4470f0 100644
--- a/core/java/android/text/TextShaper.java
+++ b/core/java/android/text/TextShaper.java
@@ -198,6 +198,10 @@ public class TextShaper {
/**
* Shape multi-styled text.
*
+ * In the LTR context, the shape result will go from left to right, thus you may want to draw
+ * glyphs from left most position of the canvas. In the RTL context, the shape result will go
+ * from right to left, thus you may want to draw glyphs from right most position of the canvas.
+ *
* @param text a styled text.
* @param start a start index of shaping target in the text.
* @param count a length of shaping target in the text.
@@ -215,7 +219,7 @@ public class TextShaper {
try {
tl.set(paint, text, start, start + count,
mp.getParagraphDir(),
- mp.getDirections(start, start + count),
+ mp.getDirections(0, count),
false /* tabstop is not supported */,
null,
-1, -1 // ellipsis is not supported.
diff --git a/core/java/android/text/TextUtils.java b/core/java/android/text/TextUtils.java
index 72b35b9253eb..d0fd2b393633 100644
--- a/core/java/android/text/TextUtils.java
+++ b/core/java/android/text/TextUtils.java
@@ -2095,6 +2095,9 @@ public class TextUtils {
* <li>{@code %s} for {@code String}
* <li>{@code %x} for hex representation of {@code int} or {@code long}
* <li>{@code %%} for literal {@code %}
+ * <li>{@code %04d} style grammar to specify the argument width, such as
+ * {@code %04d} to prefix an {@code int} with zeros or {@code %10b} to
+ * prefix a {@code boolean} with spaces
* </ul>
*
* @throws IllegalArgumentException if the format string or arguments don't
@@ -2106,8 +2109,23 @@ public class TextUtils {
int j = 0;
for (int i = 0; i < sb.length(); ) {
if (sb.charAt(i) == '%') {
+ char code = sb.charAt(i + 1);
+
+ // Decode any argument width request
+ char prefixChar = '\0';
+ int prefixLen = 0;
+ int consume = 2;
+ while ('0' <= code && code <= '9') {
+ if (prefixChar == '\0') {
+ prefixChar = (code == '0') ? '0' : ' ';
+ }
+ prefixLen *= 10;
+ prefixLen += Character.digit(code, 10);
+ consume += 1;
+ code = sb.charAt(i + consume - 1);
+ }
+
final String repl;
- final char code = sb.charAt(i + 1);
switch (code) {
case 'b': {
if (j == args.length) {
@@ -2155,8 +2173,15 @@ public class TextUtils {
throw new IllegalArgumentException("Unsupported format code " + code);
}
}
- sb.replace(i, i + 2, repl);
- i += repl.length();
+
+ sb.replace(i, i + consume, repl);
+
+ // Apply any argument width request
+ final int prefixInsert = (prefixChar == '0' && repl.charAt(0) == '-') ? 1 : 0;
+ for (int k = repl.length(); k < prefixLen; k++) {
+ sb.insert(i + prefixInsert, prefixChar);
+ }
+ i += Math.max(repl.length(), prefixLen);
} else {
i++;
}
diff --git a/core/java/android/text/style/LineHeightSpan.java b/core/java/android/text/style/LineHeightSpan.java
index 610cf2c7c784..ae565d1c3317 100644
--- a/core/java/android/text/style/LineHeightSpan.java
+++ b/core/java/android/text/style/LineHeightSpan.java
@@ -89,7 +89,7 @@ public interface LineHeightSpan extends ParagraphStyle, WrapTogetherSpan {
* Set the line height of the paragraph to <code>height</code> physical pixels.
*/
public Standard(@Px @IntRange(from = 1) int height) {
- Preconditions.checkArgument(height > 0, "Height:" + height + "must be positive");
+ Preconditions.checkArgument(height > 0, "Height: %d must be positive", height);
mHeight = height;
}
diff --git a/core/java/android/util/FeatureFlagUtils.java b/core/java/android/util/FeatureFlagUtils.java
index 9244647432c7..c20b0639b1c4 100644
--- a/core/java/android/util/FeatureFlagUtils.java
+++ b/core/java/android/util/FeatureFlagUtils.java
@@ -36,7 +36,6 @@ public class FeatureFlagUtils {
public static final String FFLAG_PREFIX = "sys.fflag.";
public static final String FFLAG_OVERRIDE_PREFIX = FFLAG_PREFIX + "override.";
public static final String PERSIST_PREFIX = "persist." + FFLAG_OVERRIDE_PREFIX;
- public static final String SEAMLESS_TRANSFER = "settings_seamless_transfer";
public static final String HEARING_AID_SETTINGS = "settings_bluetooth_hearing_aid";
public static final String SCREENRECORD_LONG_PRESS = "settings_screenrecord_long_press";
public static final String DYNAMIC_SYSTEM = "settings_dynamic_system";
@@ -54,7 +53,6 @@ public class FeatureFlagUtils {
DEFAULT_FLAGS.put("settings_audio_switcher", "true");
DEFAULT_FLAGS.put("settings_systemui_theme", "true");
DEFAULT_FLAGS.put(DYNAMIC_SYSTEM, "false");
- DEFAULT_FLAGS.put(SEAMLESS_TRANSFER, "false");
DEFAULT_FLAGS.put(HEARING_AID_SETTINGS, "false");
DEFAULT_FLAGS.put(SCREENRECORD_LONG_PRESS, "false");
DEFAULT_FLAGS.put("settings_wifi_details_datausage_header", "false");
diff --git a/core/java/android/util/proto/EncodedBuffer.java b/core/java/android/util/proto/EncodedBuffer.java
index 56a0bfa2adb1..2a8f405ffd7f 100644
--- a/core/java/android/util/proto/EncodedBuffer.java
+++ b/core/java/android/util/proto/EncodedBuffer.java
@@ -648,7 +648,7 @@ public final class EncodedBuffer {
* Print the internal buffer chunks.
*/
private static int dumpByteString(String tag, String prefix, int start, byte[] buf) {
- StringBuffer sb = new StringBuffer();
+ StringBuilder sb = new StringBuilder();
final int length = buf.length;
final int lineLen = 16;
int i;
@@ -656,7 +656,7 @@ public final class EncodedBuffer {
if (i % lineLen == 0) {
if (i != 0) {
Log.d(tag, sb.toString());
- sb = new StringBuffer();
+ sb = new StringBuilder();
}
sb.append(prefix);
sb.append('[');
diff --git a/core/java/android/util/proto/ProtoInputStream.java b/core/java/android/util/proto/ProtoInputStream.java
index aa70d07ff787..9789b10a0a61 100644
--- a/core/java/android/util/proto/ProtoInputStream.java
+++ b/core/java/android/util/proto/ProtoInputStream.java
@@ -16,10 +16,11 @@
package android.util.proto;
+import android.util.LongArray;
+
import java.io.IOException;
import java.io.InputStream;
import java.nio.charset.StandardCharsets;
-import java.util.ArrayList;
/**
* Class to read to a protobuf stream.
@@ -98,7 +99,7 @@ public final class ProtoInputStream extends ProtoStream {
/**
* Keeps track of the currently read nested Objects, for end object checking and debug
*/
- private ArrayList<Long> mExpectedObjectTokenStack = null;
+ private LongArray mExpectedObjectTokenStack = null;
/**
* Current nesting depth of start calls.
@@ -498,7 +499,7 @@ public final class ProtoInputStream extends ProtoStream {
int messageSize = (int) readVarint();
if (mExpectedObjectTokenStack == null) {
- mExpectedObjectTokenStack = new ArrayList<>();
+ mExpectedObjectTokenStack = new LongArray();
}
if (++mDepth == mExpectedObjectTokenStack.size()) {
// Create a token to keep track of nested Object and extend the object stack
diff --git a/core/java/android/uwb/AngleMeasurement.java b/core/java/android/uwb/AngleMeasurement.java
new file mode 100644
index 000000000000..c3e2ecc9e0f3
--- /dev/null
+++ b/core/java/android/uwb/AngleMeasurement.java
@@ -0,0 +1,149 @@
+/*
+ * Copyright 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 android.uwb;
+
+import android.annotation.FloatRange;
+
+/**
+ * Angle measurement
+ *
+ * <p>The actual angle is interpreted as:
+ * {@link #getRadians()} +/- {@link #getErrorRadians()} ()} at {@link #getConfidenceLevel()}
+ *
+ * @hide
+ */
+public final class AngleMeasurement {
+ private final double mRadians;
+ private final double mErrorRadians;
+ private final double mConfidenceLevel;
+
+ private AngleMeasurement(double radians, double errorRadians, double confidenceLevel) {
+ mRadians = radians;
+ mErrorRadians = errorRadians;
+ mConfidenceLevel = confidenceLevel;
+ }
+
+ /**
+ * Angle measurement in radians
+ *
+ * @return angle in radians
+ */
+ @FloatRange(from = -Math.PI, to = +Math.PI)
+ public double getRadians() {
+ return mRadians;
+ }
+
+ /**
+ * Error of angle measurement in radians
+ *
+ * <p>Must be a positive value
+ *
+ * @return angle measurement error in radians
+ */
+ @FloatRange(from = 0.0, to = +Math.PI)
+ public double getErrorRadians() {
+ return mErrorRadians;
+ }
+
+ /**
+ * Angle measurement confidence level expressed as a value between
+ * 0.0 to 1.0.
+ *
+ * <p>A value of 0.0 indicates there is no confidence in the measurement. A value of 1.0
+ * indicates there is maximum confidence in the measurement.
+ *
+ * @return the confidence level of the angle measurement
+ */
+ @FloatRange(from = 0.0, to = 1.0)
+ public double getConfidenceLevel() {
+ return mConfidenceLevel;
+ }
+
+ /**
+ * Builder class for {@link AngleMeasurement}.
+ */
+ public static final class Builder {
+ private double mRadians = Double.NaN;
+ private double mErrorRadians = Double.NaN;
+ private double mConfidenceLevel = Double.NaN;
+
+ /**
+ * Set the angle in radians
+ *
+ * @param radians angle in radians
+ * @throws IllegalArgumentException if angle exceeds allowed limits of [-Math.PI, +Math.PI]
+ */
+ public Builder setRadians(double radians) {
+ if (radians < -Math.PI || radians > Math.PI) {
+ throw new IllegalArgumentException("Invalid radians: " + radians);
+ }
+ mRadians = radians;
+ return this;
+ }
+
+ /**
+ * Set the angle error in radians
+ *
+ * @param errorRadians error of the angle in radians
+ * @throws IllegalArgumentException if the error exceeds the allowed limits of [0, +Math.PI]
+ */
+ public Builder setErrorRadians(double errorRadians) {
+ if (errorRadians < 0.0 || errorRadians > Math.PI) {
+ throw new IllegalArgumentException(
+ "Invalid error radians: " + errorRadians);
+ }
+ mErrorRadians = errorRadians;
+ return this;
+ }
+
+ /**
+ * Set the angle confidence level
+ *
+ * @param confidenceLevel level of confidence of the angle measurement
+ * @throws IllegalArgumentException if the error exceeds the allowed limits of [0.0, 1.0]
+ */
+ public Builder setConfidenceLevel(double confidenceLevel) {
+ if (confidenceLevel < 0.0 || confidenceLevel > 1.0) {
+ throw new IllegalArgumentException(
+ "Invalid confidence level: " + confidenceLevel);
+ }
+ mConfidenceLevel = confidenceLevel;
+ return this;
+ }
+
+ /**
+ * Build the {@link AngleMeasurement} object
+ *
+ * @throws IllegalStateException if angle, error, or confidence values are missing
+ */
+ public AngleMeasurement build() {
+ if (Double.isNaN(mRadians)) {
+ throw new IllegalStateException("Angle is not set");
+ }
+
+ if (Double.isNaN(mErrorRadians)) {
+ throw new IllegalStateException("Angle error is not set");
+ }
+
+ if (Double.isNaN(mConfidenceLevel)) {
+ throw new IllegalStateException("Angle confidence level is not set");
+ }
+
+ return new AngleMeasurement(mRadians, mErrorRadians, mConfidenceLevel);
+ }
+ }
+}
diff --git a/core/java/android/uwb/AngleOfArrivalMeasurement.java b/core/java/android/uwb/AngleOfArrivalMeasurement.java
new file mode 100644
index 000000000000..a7b5eae728cb
--- /dev/null
+++ b/core/java/android/uwb/AngleOfArrivalMeasurement.java
@@ -0,0 +1,114 @@
+/*
+ * Copyright 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 android.uwb;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+
+/**
+ * Represents an angle of arrival measurement between two devices using Ultra Wideband
+ *
+ * @hide
+ */
+public final class AngleOfArrivalMeasurement {
+ private final AngleMeasurement mAzimuthAngleMeasurement;
+ private final AngleMeasurement mAltitudeAngleMeasurement;
+
+ private AngleOfArrivalMeasurement(@NonNull AngleMeasurement azimuthAngleMeasurement,
+ @Nullable AngleMeasurement altitudeAngleMeasurement) {
+ mAzimuthAngleMeasurement = azimuthAngleMeasurement;
+ mAltitudeAngleMeasurement = altitudeAngleMeasurement;
+ }
+
+ /**
+ * Azimuth angle measurement
+ * <p>Azimuth {@link AngleMeasurement} of remote device in horizontal coordinate system, this is
+ * the angle clockwise from the meridian when viewing above the north pole.
+ *
+ * <p>See: https://en.wikipedia.org/wiki/Horizontal_coordinate_system
+ *
+ * <p>On an Android device, azimuth north is defined as the angle perpendicular away from the
+ * back of the device when holding it in portrait mode upright.
+ *
+ * <p>Azimuth angle must be supported when Angle of Arrival is supported
+ *
+ * @return the azimuth {@link AngleMeasurement}
+ */
+ @NonNull
+ public AngleMeasurement getAzimuth() {
+ return mAzimuthAngleMeasurement;
+ }
+
+ /**
+ * Altitude angle measurement
+ * <p>Altitude {@link AngleMeasurement} of remote device in horizontal coordinate system, this
+ * is the angle above the equator when the north pole is up.
+ *
+ * <p>See: https://en.wikipedia.org/wiki/Horizontal_coordinate_system
+ *
+ * <p>On an Android device, altitude is defined as the angle vertical from ground when holding
+ * the device in portrait mode upright.
+ *
+ * @return altitude {@link AngleMeasurement} or null when this is not available
+ */
+ @Nullable
+ public AngleMeasurement getAltitude() {
+ return mAltitudeAngleMeasurement;
+ }
+
+ /**
+ * Builder class for {@link AngleOfArrivalMeasurement}.
+ */
+ public static final class Builder {
+ private AngleMeasurement mAzimuthAngleMeasurement = null;
+ private AngleMeasurement mAltitudeAngleMeasurement = null;
+
+ /**
+ * Set the azimuth angle
+ *
+ * @param azimuthAngle azimuth angle
+ */
+ public Builder setAzimuthAngleMeasurement(@NonNull AngleMeasurement azimuthAngle) {
+ mAzimuthAngleMeasurement = azimuthAngle;
+ return this;
+ }
+
+ /**
+ * Set the altitude angle
+ *
+ * @param altitudeAngle altitude angle
+ */
+ public Builder setAltitudeAngleMeasurement(@NonNull AngleMeasurement altitudeAngle) {
+ mAltitudeAngleMeasurement = altitudeAngle;
+ return this;
+ }
+
+ /**
+ * Build the {@link AngleOfArrivalMeasurement} object
+ *
+ * @throws IllegalStateException if the required azimuth angle is not provided
+ */
+ public AngleOfArrivalMeasurement build() {
+ if (mAzimuthAngleMeasurement == null) {
+ throw new IllegalStateException("Azimuth angle measurement is not set");
+ }
+
+ return new AngleOfArrivalMeasurement(mAzimuthAngleMeasurement,
+ mAltitudeAngleMeasurement);
+ }
+ }
+}
diff --git a/core/java/android/uwb/DistanceMeasurement.java b/core/java/android/uwb/DistanceMeasurement.java
new file mode 100644
index 000000000000..4cd5d83f4efc
--- /dev/null
+++ b/core/java/android/uwb/DistanceMeasurement.java
@@ -0,0 +1,145 @@
+/*
+ * Copyright 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 android.uwb;
+
+import android.annotation.FloatRange;
+
+/**
+ * A data point for the distance measurement
+ *
+ * <p>The actual distance is interpreted as:
+ * {@link #getMeters()} +/- {@link #getErrorMeters()} at {@link #getConfidenceLevel()}
+ *
+ * @hide
+ */
+public final class DistanceMeasurement {
+ private final double mMeters;
+ private final double mErrorMeters;
+ private final double mConfidenceLevel;
+
+ private DistanceMeasurement(double meters, double errorMeters, double confidenceLevel) {
+ mMeters = meters;
+ mErrorMeters = errorMeters;
+ mConfidenceLevel = confidenceLevel;
+ }
+
+ /**
+ * Distance measurement in meters
+ *
+ * @return distance in meters
+ */
+ public double getMeters() {
+ return mMeters;
+ }
+
+ /**
+ * Error of distance measurement in meters
+ * <p>Must be positive
+ *
+ * @return error of distance measurement in meters
+ */
+ public double getErrorMeters() {
+ return mErrorMeters;
+ }
+
+ /**
+ * Distance measurement confidence level expressed as a value between 0.0 to 1.0.
+ *
+ * <p>A value of 0.0 indicates no confidence in the measurement. A value of 1.0 represents
+ * maximum confidence in the measurement
+ *
+ * @return confidence level
+ */
+ @FloatRange(from = 0.0, to = 1.0)
+ public double getConfidenceLevel() {
+ return mConfidenceLevel;
+ }
+
+ /**
+ * Builder to get a {@link DistanceMeasurement} object.
+ */
+ public static final class Builder {
+ private double mMeters = Double.NaN;
+ private double mErrorMeters = Double.NaN;
+ private double mConfidenceLevel = Double.NaN;
+
+ /**
+ * Set the distance measurement in meters
+ *
+ * @param meters distance in meters
+ * @throws IllegalArgumentException if meters is NaN
+ */
+ public Builder setMeters(double meters) {
+ if (Double.isNaN(meters)) {
+ throw new IllegalArgumentException("meters cannot be NaN");
+ }
+ mMeters = meters;
+ return this;
+ }
+
+ /**
+ * Set the distance error in meters
+ *
+ * @param errorMeters distance error in meters
+ * @throws IllegalArgumentException if error is negative or NaN
+ */
+ public Builder setErrorMeters(double errorMeters) {
+ if (Double.isNaN(errorMeters) || errorMeters < 0.0) {
+ throw new IllegalArgumentException(
+ "errorMeters must be >= 0.0 and not NaN: " + errorMeters);
+ }
+ mErrorMeters = errorMeters;
+ return this;
+ }
+
+ /**
+ * Set the confidence level
+ *
+ * @param confidenceLevel the confidence level in the distance measurement
+ * @throws IllegalArgumentException if confidence level is not in the range of [0.0, 1.0]
+ */
+ public Builder setConfidenceLevel(double confidenceLevel) {
+ if (confidenceLevel < 0.0 || confidenceLevel > 1.0) {
+ throw new IllegalArgumentException(
+ "confidenceLevel must be in the range [0.0, 1.0]: " + confidenceLevel);
+ }
+ mConfidenceLevel = confidenceLevel;
+ return this;
+ }
+
+ /**
+ * Builds the {@link DistanceMeasurement} object
+ *
+ * @throws IllegalStateException if meters, error, or confidence are not set
+ */
+ public DistanceMeasurement build() {
+ if (Double.isNaN(mMeters)) {
+ throw new IllegalStateException("Meters cannot be NaN");
+ }
+
+ if (Double.isNaN(mErrorMeters)) {
+ throw new IllegalStateException("Error meters cannot be NaN");
+ }
+
+ if (Double.isNaN(mConfidenceLevel)) {
+ throw new IllegalStateException("Confidence level cannot be NaN");
+ }
+
+ return new DistanceMeasurement(mMeters, mErrorMeters, mConfidenceLevel);
+ }
+ }
+}
diff --git a/core/java/android/uwb/RangingMeasurement.java b/core/java/android/uwb/RangingMeasurement.java
new file mode 100644
index 000000000000..33a34e3954c2
--- /dev/null
+++ b/core/java/android/uwb/RangingMeasurement.java
@@ -0,0 +1,229 @@
+/*
+ * Copyright 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 android.uwb;
+
+import android.annotation.IntDef;
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.annotation.SuppressLint;
+import android.os.SystemClock;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+
+/**
+ * Representation of a ranging measurement between the local device and a remote device
+ *
+ * @hide
+ */
+public final class RangingMeasurement {
+ private final UwbAddress mRemoteDeviceAddress;
+ private final @Status int mStatus;
+ private final long mElapsedRealtimeNanos;
+ private final DistanceMeasurement mDistanceMeasurement;
+ private final AngleOfArrivalMeasurement mAngleOfArrivalMeasurement;
+
+ private RangingMeasurement(@NonNull UwbAddress remoteDeviceAddress, @Status int status,
+ long elapsedRealtimeNanos, @Nullable DistanceMeasurement distanceMeasurement,
+ @Nullable AngleOfArrivalMeasurement angleOfArrivalMeasurement) {
+ mRemoteDeviceAddress = remoteDeviceAddress;
+ mStatus = status;
+ mElapsedRealtimeNanos = elapsedRealtimeNanos;
+ mDistanceMeasurement = distanceMeasurement;
+ mAngleOfArrivalMeasurement = angleOfArrivalMeasurement;
+ }
+
+ /**
+ * Get the remote device's {@link UwbAddress}
+ *
+ * @return the remote device's {@link UwbAddress}
+ */
+ @NonNull
+ public UwbAddress getRemoteDeviceAddress() {
+ return mRemoteDeviceAddress;
+ }
+
+ @Retention(RetentionPolicy.SOURCE)
+ @IntDef(value = {
+ RANGING_STATUS_SUCCESS,
+ RANGING_STATUS_FAILURE_OUT_OF_RANGE,
+ RANGING_STATUS_FAILURE_UNKNOWN_ERROR})
+ public @interface Status {}
+
+ /**
+ * Ranging attempt was successful for this device
+ */
+ public static final int RANGING_STATUS_SUCCESS = 0;
+
+ /**
+ * Ranging failed for this device because it is out of range
+ */
+ public static final int RANGING_STATUS_FAILURE_OUT_OF_RANGE = 1;
+
+ /**
+ * Ranging failed for this device because of unknown error
+ */
+ public static final int RANGING_STATUS_FAILURE_UNKNOWN_ERROR = -1;
+
+ /**
+ * Get the status of this ranging measurement
+ *
+ * <p>Possible values are
+ * {@link #RANGING_STATUS_SUCCESS},
+ * {@link #RANGING_STATUS_FAILURE_OUT_OF_RANGE},
+ * {@link #RANGING_STATUS_FAILURE_UNKNOWN_ERROR}.
+ *
+ * @return the status of the ranging measurement
+ */
+ @Status
+ public int getStatus() {
+ return mStatus;
+ }
+
+ /**
+ * Timestamp of this ranging measurement in time since boot nanos in the same namespace as
+ * {@link SystemClock#elapsedRealtimeNanos()}
+ *
+ * @return timestamp of ranging measurement in nanoseconds
+ */
+ @SuppressLint("MethodNameUnits")
+ public long getElapsedRealtimeNanos() {
+ return mElapsedRealtimeNanos;
+ }
+
+ /**
+ * Get the distance measurement
+ *
+ * @return a {@link DistanceMeasurement} or null if {@link #getStatus()} !=
+ * {@link #RANGING_STATUS_SUCCESS}
+ */
+ @Nullable
+ public DistanceMeasurement getDistance() {
+ return mDistanceMeasurement;
+ }
+
+ /**
+ * Get the angle of arrival measurement
+ *
+ * @return an {@link AngleOfArrivalMeasurement} or null if {@link #getStatus()} !=
+ * {@link #RANGING_STATUS_SUCCESS}
+ */
+ @Nullable
+ public AngleOfArrivalMeasurement getAngleOfArrival() {
+ return mAngleOfArrivalMeasurement;
+ }
+
+ /**
+ * Builder for a {@link RangingMeasurement} object.
+ */
+ public static final class Builder {
+ private UwbAddress mRemoteDeviceAddress = null;
+ private @Status int mStatus = RANGING_STATUS_FAILURE_UNKNOWN_ERROR;
+ private long mElapsedRealtimeNanos = -1L;
+ private DistanceMeasurement mDistanceMeasurement = null;
+ private AngleOfArrivalMeasurement mAngleOfArrivalMeasurement = null;
+
+ /**
+ * Set the remote device address that this measurement is for
+ *
+ * @param remoteDeviceAddress remote device's address
+ */
+ public Builder setRemoteDeviceAddress(@NonNull UwbAddress remoteDeviceAddress) {
+ mRemoteDeviceAddress = remoteDeviceAddress;
+ return this;
+ }
+
+ /**
+ * Set the status of ranging measurement
+ *
+ * @param status the status of the ranging measurement
+ */
+ public Builder setStatus(@Status int status) {
+ mStatus = status;
+ return this;
+ }
+
+ /**
+ * Set the elapsed realtime in nanoseconds when the ranging measurement occurred
+ *
+ * @param elapsedRealtimeNanos time the ranging measurement occurred
+ */
+ public Builder setElapsedRealtimeNanos(long elapsedRealtimeNanos) {
+ if (elapsedRealtimeNanos < 0) {
+ throw new IllegalArgumentException("elapsedRealtimeNanos must be >= 0");
+ }
+ mElapsedRealtimeNanos = elapsedRealtimeNanos;
+ return this;
+ }
+
+ /**
+ * Set the {@link DistanceMeasurement}
+ *
+ * @param distanceMeasurement the distance measurement for this ranging measurement
+ */
+ public Builder setDistanceMeasurement(@NonNull DistanceMeasurement distanceMeasurement) {
+ mDistanceMeasurement = distanceMeasurement;
+ return this;
+ }
+
+ /**
+ * Set the {@link AngleOfArrivalMeasurement}
+ *
+ * @param angleOfArrivalMeasurement the angle of arrival measurement for this ranging
+ * measurement
+ */
+ public Builder setAngleOfArrivalMeasurement(
+ @NonNull AngleOfArrivalMeasurement angleOfArrivalMeasurement) {
+ mAngleOfArrivalMeasurement = angleOfArrivalMeasurement;
+ return this;
+ }
+
+ /**
+ * Build the {@link RangingMeasurement} object
+ *
+ * @throws IllegalStateException if a distance or angle of arrival measurement is provided
+ * but the measurement was not successful, if the
+ * elapsedRealtimeNanos of the measurement is invalid, or
+ * if no remote device address is set
+ */
+ public RangingMeasurement build() {
+ if (mStatus != RANGING_STATUS_SUCCESS) {
+ if (mDistanceMeasurement != null) {
+ throw new IllegalStateException(
+ "Distance Measurement must be null if ranging is not successful");
+ }
+
+ if (mAngleOfArrivalMeasurement != null) {
+ throw new IllegalStateException(
+ "Angle of Arrival must be null if ranging is not successful");
+ }
+ }
+
+ if (mRemoteDeviceAddress == null) {
+ throw new IllegalStateException("No remote device address was set");
+ }
+
+ if (mElapsedRealtimeNanos < 0) {
+ throw new IllegalStateException(
+ "elapsedRealtimeNanos must be >=0: " + mElapsedRealtimeNanos);
+ }
+
+ return new RangingMeasurement(mRemoteDeviceAddress, mStatus, mElapsedRealtimeNanos,
+ mDistanceMeasurement, mAngleOfArrivalMeasurement);
+ }
+ }
+}
diff --git a/core/java/android/uwb/RangingParams.java b/core/java/android/uwb/RangingParams.java
new file mode 100644
index 000000000000..a50de3e61425
--- /dev/null
+++ b/core/java/android/uwb/RangingParams.java
@@ -0,0 +1,381 @@
+/*
+ * Copyright 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 android.uwb;
+
+import android.annotation.IntDef;
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.os.PersistableBundle;
+import android.util.Duration;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
+/**
+ * An object used when requesting to open a new {@link RangingSession}.
+ * <p>Use {@link RangingParams.Builder} to create an instance of this class.
+ *
+ * @hide
+ */
+public final class RangingParams {
+ private final boolean mIsInitiator;
+ private final boolean mIsController;
+ private final Duration mSamplePeriod;
+ private final UwbAddress mLocalDeviceAddress;
+ private final List<UwbAddress> mRemoteDeviceAddresses;
+ private final int mChannelNumber;
+ private final int mTransmitPreambleCodeIndex;
+ private final int mReceivePreambleCodeIndex;
+ private final int mStsPhyPacketType;
+ private final PersistableBundle mSpecificationParameters;
+
+ private RangingParams(boolean isInitiator, boolean isController,
+ @NonNull Duration samplingPeriod, @NonNull UwbAddress localDeviceAddress,
+ @NonNull List<UwbAddress> remoteDeviceAddresses, int channelNumber,
+ int transmitPreambleCodeIndex, int receivePreambleCodeIndex,
+ @StsPhyPacketType int stsPhyPacketType,
+ @NonNull PersistableBundle specificationParameters) {
+ mIsInitiator = isInitiator;
+ mIsController = isController;
+ mSamplePeriod = samplingPeriod;
+ mLocalDeviceAddress = localDeviceAddress;
+ mRemoteDeviceAddresses = remoteDeviceAddresses;
+ mChannelNumber = channelNumber;
+ mTransmitPreambleCodeIndex = transmitPreambleCodeIndex;
+ mReceivePreambleCodeIndex = receivePreambleCodeIndex;
+ mStsPhyPacketType = stsPhyPacketType;
+ mSpecificationParameters = specificationParameters;
+ }
+
+ /**
+ * Get if the local device is the initiator
+ *
+ * @return true if the device is the initiator
+ */
+ public boolean isInitiator() {
+ return mIsInitiator;
+ }
+
+ /**
+ * Get if the local device is the controller
+ *
+ * @return true if the device is the controller
+ */
+ public boolean isController() {
+ return mIsController;
+ }
+
+ /**
+ * The desired amount of time between two adjacent samples of measurement
+ *
+ * @return the ranging sample period
+ */
+ @NonNull
+ public Duration getSamplingPeriod() {
+ return mSamplePeriod;
+ }
+
+ /**
+ * Local device's {@link UwbAddress}
+ *
+ * <p>Simultaneous {@link RangingSession}s on the same device can have different results for
+ * {@link #getLocalDeviceAddress()}.
+ *
+ * @return the local device's {@link UwbAddress}
+ */
+ @NonNull
+ public UwbAddress getLocalDeviceAddress() {
+ return mLocalDeviceAddress;
+ }
+
+ /**
+ * Gets a list of all remote device's {@link UwbAddress}
+ *
+ * @return a {@link List} of {@link UwbAddress} representing the remote devices
+ */
+ @NonNull
+ public List<UwbAddress> getRemoteDeviceAddresses() {
+ return mRemoteDeviceAddresses;
+ }
+
+ /**
+ * Channel number used between this device pair as defined by 802.15.4z
+ *
+ * Range: -1, 0-15
+ *
+ * @return the channel to use
+ */
+ public int getChannelNumber() {
+ return mChannelNumber;
+ }
+
+ /**
+ * Preamble index used between this device pair as defined by 802.15.4z
+ *
+ * Range: 0, 0-32
+ *
+ * @return the preamble index to use for transmitting
+ */
+ public int getTxPreambleIndex() {
+ return mTransmitPreambleCodeIndex;
+ }
+
+ /**
+ * preamble index used between this device pair as defined by 802.15.4z
+ *
+ * Range: 0, 13-16, 21-32
+ *
+ * @return the preamble index to use for receiving
+ */
+ public int getRxPreambleIndex() {
+ return mReceivePreambleCodeIndex;
+ }
+
+ @Retention(RetentionPolicy.SOURCE)
+ @IntDef(value = {
+ STS_PHY_PACKET_TYPE_SP0,
+ STS_PHY_PACKET_TYPE_SP1,
+ STS_PHY_PACKET_TYPE_SP2,
+ STS_PHY_PACKET_TYPE_SP3})
+ public @interface StsPhyPacketType {}
+
+ /**
+ * PHY packet type SP0 when STS is used as defined by 802.15.4z
+ */
+ public static final int STS_PHY_PACKET_TYPE_SP0 = 0;
+
+ /**
+ * PHY packet type SP1 when STS is used as defined by 802.15.4z
+ */
+ public static final int STS_PHY_PACKET_TYPE_SP1 = 1;
+
+ /**
+ * PHY packet type SP2 when STS is used as defined by 802.15.4z
+ */
+ public static final int STS_PHY_PACKET_TYPE_SP2 = 2;
+
+ /**
+ * PHY packet type SP3 when STS is used as defined by 802.15.4z
+ */
+ public static final int STS_PHY_PACKET_TYPE_SP3 = 3;
+
+ /**
+ * Get the type of PHY packet when STS is used as defined by 802.15.4z
+ *
+ * @return the {@link StsPhyPacketType} to use
+ */
+ @StsPhyPacketType
+ public int getStsPhyPacketType() {
+ return mStsPhyPacketType;
+ }
+
+ /**
+ * Parameters for a specific UWB protocol constructed using a support library.
+ *
+ * <p>Android reserves the '^android.*' namespace
+ *
+ * @return a {@link PersistableBundle} copy of protocol specific parameters
+ */
+ public @Nullable PersistableBundle getSpecificationParameters() {
+ return new PersistableBundle(mSpecificationParameters);
+ }
+
+ /**
+ * Builder class for {@link RangingParams}.
+ */
+ public static final class Builder {
+ private boolean mIsInitiator = false;
+ private boolean mIsController = false;
+ private Duration mSamplePeriod = null;
+ private UwbAddress mLocalDeviceAddress = null;
+ private List<UwbAddress> mRemoteDeviceAddresses = new ArrayList<>();
+ private int mChannelNumber = 0;
+ private int mTransmitPreambleCodeIndex = 0;
+ private int mReceivePreambleCodeIndex = 0;
+ private int mStsPhyPacketType = STS_PHY_PACKET_TYPE_SP0;
+ private PersistableBundle mSpecificationParameters = new PersistableBundle();
+
+ /**
+ * Set whether the device is the initiator or responder as defined by IEEE 802.15.4z
+ *
+ * @param isInitiator whether the device is the initiator (true) or responder (false)
+ */
+ public Builder setIsInitiator(boolean isInitiator) {
+ mIsInitiator = isInitiator;
+ return this;
+ }
+
+ /**
+ * Set whether the local device is the controller or controlee as defined by IEEE 802.15.4z
+ *
+ * @param isController whether the device is the controller (true) or controlee (false)
+ */
+ public Builder setIsController(boolean isController) {
+ mIsController = isController;
+ return this;
+ }
+
+ /**
+ * Set the time between ranging samples
+ *
+ * @param samplePeriod the time between ranging samples
+ */
+ public Builder setSamplePeriod(@NonNull Duration samplePeriod) {
+ mSamplePeriod = samplePeriod;
+ return this;
+ }
+
+ /**
+ * Set the local device address
+ *
+ * @param localDeviceAddress the local device's address for the {@link RangingSession}
+ */
+ public Builder setLocalDeviceAddress(@NonNull UwbAddress localDeviceAddress) {
+ mLocalDeviceAddress = localDeviceAddress;
+ return this;
+ }
+
+ /**
+ * Add a remote device's address to the ranging session
+ *
+ * @param remoteDeviceAddress a remote device's address for the {@link RangingSession}
+ * @throws IllegalArgumentException if {@code remoteDeviceAddress} is already present.
+ */
+ public Builder addRemoteDeviceAddress(@NonNull UwbAddress remoteDeviceAddress) {
+ if (mRemoteDeviceAddresses.contains(remoteDeviceAddress)) {
+ throw new IllegalArgumentException(
+ "Remote device address already added: " + remoteDeviceAddress.toString());
+ }
+ mRemoteDeviceAddresses.add(remoteDeviceAddress);
+ return this;
+ }
+
+ /**
+ * Set the IEEE 802.15.4z channel to use for the {@link RangingSession}
+ * <p>Valid values are in the range [-1, 15]
+ *
+ * @param channelNumber the channel to use for the {@link RangingSession}
+ * @throws IllegalArgumentException if {@code channelNumber} is invalid.
+ */
+ public Builder setChannelNumber(int channelNumber) {
+ if (channelNumber < -1 || channelNumber > 15) {
+ throw new IllegalArgumentException("Invalid channel number");
+ }
+ mChannelNumber = channelNumber;
+ return this;
+ }
+
+ private static final Set<Integer> VALID_TX_PREAMBLE_CODES = new HashSet<Integer>(
+ Arrays.asList(0, 13, 14, 15, 16, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32));
+
+ /**
+ * Set the IEEE 802.15.4z preamble code index to use when transmitting
+ *
+ * <p>Valid values are in the ranges: [0], [13-16], [21-32]
+ *
+ * @param transmitPreambleCodeIndex preamble code index to use for transmitting
+ * @throws IllegalArgumentException if {@code transmitPreambleCodeIndex} is invalid.
+ */
+ public Builder setTransmitPreambleCodeIndex(int transmitPreambleCodeIndex) {
+ if (!VALID_TX_PREAMBLE_CODES.contains(transmitPreambleCodeIndex)) {
+ throw new IllegalArgumentException(
+ "Invalid transmit preamble: " + transmitPreambleCodeIndex);
+ }
+ mTransmitPreambleCodeIndex = transmitPreambleCodeIndex;
+ return this;
+ }
+
+ private static final Set<Integer> VALID_RX_PREAMBLE_CODES = new HashSet<Integer>(
+ Arrays.asList(0, 16, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32));
+
+ /**
+ * Set the IEEE 802.15.4z preamble code index to use when receiving
+ *
+ * Valid values are in the ranges: [0], [16-32]
+ *
+ * @param receivePreambleCodeIndex preamble code index to use for receiving
+ * @throws IllegalArgumentException if {@code receivePreambleCodeIndex} is invalid.
+ */
+ public Builder setReceivePreambleCodeIndex(int receivePreambleCodeIndex) {
+ if (!VALID_RX_PREAMBLE_CODES.contains(receivePreambleCodeIndex)) {
+ throw new IllegalArgumentException(
+ "Invalid receive preamble: " + receivePreambleCodeIndex);
+ }
+ mReceivePreambleCodeIndex = receivePreambleCodeIndex;
+ return this;
+ }
+
+ /**
+ * Set the IEEE 802.15.4z PHY packet type when STS is used
+ *
+ * @param stsPhyPacketType PHY packet type when STS is used
+ * @throws IllegalArgumentException if {@code stsPhyPacketType} is invalid.
+ */
+ public Builder setStsPhPacketType(@StsPhyPacketType int stsPhyPacketType) {
+ if (stsPhyPacketType != STS_PHY_PACKET_TYPE_SP0
+ && stsPhyPacketType != STS_PHY_PACKET_TYPE_SP1
+ && stsPhyPacketType != STS_PHY_PACKET_TYPE_SP2
+ && stsPhyPacketType != STS_PHY_PACKET_TYPE_SP3) {
+ throw new IllegalArgumentException("unknown StsPhyPacketType: " + stsPhyPacketType);
+ }
+
+ mStsPhyPacketType = stsPhyPacketType;
+ return this;
+ }
+
+ /**
+ * Set the specification parameters
+ *
+ * <p>Creates a copy of the parameters
+ *
+ * @param parameters specification parameters built from support library
+ */
+ public Builder setSpecificationParameters(@NonNull PersistableBundle parameters) {
+ mSpecificationParameters = new PersistableBundle(parameters);
+ return this;
+ }
+
+ /**
+ * Build the {@link RangingParams} object.
+ *
+ * @throws IllegalStateException if required parameters are missing
+ */
+ public RangingParams build() {
+ if (mSamplePeriod == null) {
+ throw new IllegalStateException("No sample period provided");
+ }
+
+ if (mLocalDeviceAddress == null) {
+ throw new IllegalStateException("Local device address not provided");
+ }
+
+ if (mRemoteDeviceAddresses.size() == 0) {
+ throw new IllegalStateException("No remote device address(es) provided");
+ }
+
+ return new RangingParams(mIsInitiator, mIsController, mSamplePeriod,
+ mLocalDeviceAddress, mRemoteDeviceAddresses, mChannelNumber,
+ mTransmitPreambleCodeIndex, mReceivePreambleCodeIndex, mStsPhyPacketType,
+ mSpecificationParameters);
+ }
+ }
+}
diff --git a/core/java/android/uwb/RangingReport.java b/core/java/android/uwb/RangingReport.java
new file mode 100644
index 000000000000..5aca12aaf2cf
--- /dev/null
+++ b/core/java/android/uwb/RangingReport.java
@@ -0,0 +1,101 @@
+/*
+ * Copyright 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 android.uwb;
+
+import android.annotation.NonNull;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * This class contains the UWB ranging data
+ *
+ * @hide
+ */
+public final class RangingReport {
+ private final List<RangingMeasurement> mRangingMeasurements;
+
+ private RangingReport(@NonNull List<RangingMeasurement> rangingMeasurements) {
+ mRangingMeasurements = rangingMeasurements;
+ }
+
+ /**
+ * Get a {@link List} of {@link RangingMeasurement} objects in the last measurement interval
+ * <p>The underlying UWB adapter may choose to do multiple measurements in each ranging
+ * interval.
+ *
+ * <p>The entries in the {@link List} are ordered in ascending order based on
+ * {@link RangingMeasurement#getElapsedRealtimeNanos()}
+ *
+ * @return a {@link List} of {@link RangingMeasurement} objects
+ */
+ @NonNull
+ public List<RangingMeasurement> getMeasurements() {
+ return mRangingMeasurements;
+ }
+
+ /**
+ * Builder for {@link RangingReport} object
+ */
+ public static final class Builder {
+ List<RangingMeasurement> mMeasurements = new ArrayList<>();
+
+ /**
+ * Add a single {@link RangingMeasurement}
+ *
+ * @param rangingMeasurement a ranging measurement
+ */
+ public Builder addMeasurement(@NonNull RangingMeasurement rangingMeasurement) {
+ mMeasurements.add(rangingMeasurement);
+ return this;
+ }
+
+ /**
+ * Add a {@link List} of {@link RangingMeasurement}s
+ *
+ * @param rangingMeasurements {@link List} of {@link RangingMeasurement}s to add
+ */
+ public Builder addMeasurements(@NonNull List<RangingMeasurement> rangingMeasurements) {
+ mMeasurements.addAll(rangingMeasurements);
+ return this;
+ }
+
+ /**
+ * Build the {@link RangingReport} object
+ *
+ * @throws IllegalStateException if measurements are not in monotonically increasing order
+ */
+ public RangingReport build() {
+ // Verify that all measurement timestamps are monotonically increasing
+ RangingMeasurement prevMeasurement = null;
+ for (int curIndex = 0; curIndex < mMeasurements.size(); curIndex++) {
+ RangingMeasurement curMeasurement = mMeasurements.get(curIndex);
+ if (prevMeasurement != null
+ && (prevMeasurement.getElapsedRealtimeNanos()
+ > curMeasurement.getElapsedRealtimeNanos())) {
+ throw new IllegalStateException(
+ "Timestamp (" + curMeasurement.getElapsedRealtimeNanos()
+ + ") at index " + curIndex + " is less than previous timestamp ("
+ + prevMeasurement.getElapsedRealtimeNanos() + ")");
+ }
+ prevMeasurement = curMeasurement;
+ }
+ return new RangingReport(mMeasurements);
+ }
+ }
+}
+
diff --git a/core/java/android/uwb/RangingSession.java b/core/java/android/uwb/RangingSession.java
new file mode 100644
index 000000000000..f4033fe0d29e
--- /dev/null
+++ b/core/java/android/uwb/RangingSession.java
@@ -0,0 +1,148 @@
+/*
+ * Copyright 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 android.uwb;
+
+import android.annotation.IntDef;
+import android.os.PersistableBundle;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.util.concurrent.Executor;
+
+/**
+ * This class provides a way to control an active UWB ranging session.
+ * <p>It also defines the required {@link RangingSession.Callback} that must be implemented
+ * in order to be notified of UWB ranging results and status events related to the
+ * {@link RangingSession}.
+ *
+ * <p>To get an instance of {@link RangingSession}, first use
+ * {@link UwbManager#openRangingSession(RangingParams, Executor, Callback)} to request to open a
+ * session. Once the session is opened, a {@link RangingSession} object is provided through
+ * {@link RangingSession.Callback#onOpenSuccess(RangingSession, PersistableBundle)}. If opening a
+ * session fails, the failure is reported through {@link RangingSession.Callback#onClosed(int)} with
+ * the failure reason.
+ *
+ * @hide
+ */
+public final class RangingSession implements AutoCloseable {
+ /**
+ * Interface for receiving {@link RangingSession} events
+ */
+ public interface Callback {
+ /**
+ * Invoked when {@link UwbManager#openRangingSession(RangingParams, Executor, Callback)}
+ * is successful
+ *
+ * @param session the newly opened {@link RangingSession}
+ * @param sessionInfo session specific parameters from lower layers
+ */
+ void onOpenSuccess(RangingSession session, PersistableBundle sessionInfo);
+
+ @Retention(RetentionPolicy.SOURCE)
+ @IntDef(value = {
+ CLOSE_REASON_UNKNOWN,
+ CLOSE_REASON_LOCAL_CLOSE_API,
+ CLOSE_REASON_LOCAL_BAD_PARAMETERS,
+ CLOSE_REASON_LOCAL_GENERIC_ERROR,
+ CLOSE_REASON_LOCAL_MAX_SESSIONS_REACHED,
+ CLOSE_REASON_LOCAL_SYSTEM_POLICY,
+ CLOSE_REASON_REMOTE_GENERIC_ERROR,
+ CLOSE_REASON_REMOTE_REQUEST})
+ @interface CloseReason {}
+
+ /**
+ * Indicates that the session was closed or failed to open due to an unknown reason
+ */
+ int CLOSE_REASON_UNKNOWN = 0;
+
+ /**
+ * Indicates that the session was closed or failed to open because
+ * {@link AutoCloseable#close()} or {@link RangingSession#close()} was called
+ */
+ int CLOSE_REASON_LOCAL_CLOSE_API = 1;
+
+ /**
+ * Indicates that the session failed to open due to erroneous parameters passed
+ * to {@link UwbManager#openRangingSession(RangingParams, Executor, Callback)}
+ */
+ int CLOSE_REASON_LOCAL_BAD_PARAMETERS = 2;
+
+ /**
+ * Indicates that the session was closed due to some local error on this device besides the
+ * error code already listed
+ */
+ int CLOSE_REASON_LOCAL_GENERIC_ERROR = 3;
+
+ /**
+ * Indicates that the session failed to open because the number of currently open sessions
+ * is equal to {@link UwbManager#getMaxSimultaneousSessions()}
+ */
+ int CLOSE_REASON_LOCAL_MAX_SESSIONS_REACHED = 4;
+
+ /**
+ * Indicates that the session was closed or failed to open due to local system policy, such
+ * as privacy policy, power management policy, permissions, and more.
+ */
+ int CLOSE_REASON_LOCAL_SYSTEM_POLICY = 5;
+
+ /**
+ * Indicates that the session was closed or failed to open due to an error with the remote
+ * device besides error codes already listed.
+ */
+ int CLOSE_REASON_REMOTE_GENERIC_ERROR = 6;
+
+ /**
+ * Indicates that the session was closed or failed to open due to an explicit request from
+ * the remote device.
+ */
+ int CLOSE_REASON_REMOTE_REQUEST = 7;
+
+ /**
+ * Invoked when session is either closed spontaneously, or per user request via
+ * {@link RangingSession#close()} or {@link AutoCloseable#close()}, or when session failed
+ * to open.
+ *
+ * @param reason reason for the session closure
+ */
+ void onClosed(@CloseReason int reason);
+
+ /**
+ * Called once per ranging interval even when a ranging measurement fails
+ *
+ * @param rangingReport ranging report for this interval's measurements
+ */
+ void onReportReceived(RangingReport rangingReport);
+ }
+
+ /**
+ * Close the ranging session
+ * <p>If this session is currently open, it will close and stop the session.
+ * <p>If the session is in the process of being opened, it will attempt to stop the session from
+ * being opened.
+ * <p>If the session is already closed, the registered {@link Callback#onClosed(int)} callback
+ * will still be invoked.
+ *
+ * <p>{@link Callback#onClosed(int)} will be invoked using the same callback
+ * object given to {@link UwbManager#openRangingSession(RangingParams, Executor, Callback)} when
+ * the {@link RangingSession} was opened. The callback will be invoked after each call to
+ * {@link #close()}, even if the {@link RangingSession} is already closed.
+ */
+ @Override
+ public void close() {
+ throw new UnsupportedOperationException();
+ }
+}
diff --git a/core/java/android/uwb/UwbManager.java b/core/java/android/uwb/UwbManager.java
index 8097dc6dca11..d58d5bfd8de3 100644
--- a/core/java/android/uwb/UwbManager.java
+++ b/core/java/android/uwb/UwbManager.java
@@ -266,4 +266,33 @@ public final class UwbManager {
public int getMaxRemoteDevicesPerResponderSession() {
throw new UnsupportedOperationException();
}
+
+ /**
+ * Open a {@link RangingSession} with the given parameters
+ * <p>This function is asynchronous and will return before ranging begins. The
+ * {@link RangingSession.Callback#onOpenSuccess(RangingSession, PersistableBundle)} function is
+ * called with a {@link RangingSession} object used to control ranging when the session is
+ * successfully opened.
+ *
+ * <p>If a session cannot be opened, then {@link RangingSession.Callback#onClosed(int)} will be
+ * invoked with the appropriate {@link RangingSession.Callback.CloseReason}.
+ *
+ * <p>An open {@link RangingSession} will be automatically closed if client application process
+ * dies.
+ *
+ * @param params {@link RangingParams} used to initialize this {@link RangingSession}
+ * @param executor {@link Executor} to run callbacks
+ * @param callbacks {@link RangingSession.Callback} to associate with the
+ * {@link RangingSession} that is being opened.
+ *
+ * @return an {@link AutoCloseable} that is able to be used to close or cancel the opening of a
+ * {@link RangingSession} that has been requested through {@link #openRangingSession}
+ * but has not yet been made available by
+ * {@link RangingSession.Callback#onOpenSuccess}.
+ */
+ @NonNull
+ public AutoCloseable openRangingSession(@NonNull RangingParams params,
+ @NonNull Executor executor, @NonNull RangingSession.Callback callbacks) {
+ throw new UnsupportedOperationException();
+ }
}
diff --git a/core/java/android/view/IScrollCaptureController.aidl b/core/java/android/view/IScrollCaptureCallbacks.aidl
index 8474a00b302f..d97e3c66cc5d 100644
--- a/core/java/android/view/IScrollCaptureController.aidl
+++ b/core/java/android/view/IScrollCaptureCallbacks.aidl
@@ -20,32 +20,31 @@ import android.graphics.Point;
import android.graphics.Rect;
import android.view.Surface;
-import android.view.IScrollCaptureClient;
+import android.view.IScrollCaptureConnection;
/**
- * Interface to a controller passed to the {@link IScrollCaptureClient} which provides the client an
- * asynchronous callback channel for responses.
+ * Asynchronous callback channel for responses to scroll capture requests.
*
* {@hide}
*/
-interface IScrollCaptureController {
+interface IScrollCaptureCallbacks {
/**
- * Scroll capture is available, and a client connect has been returned.
+ * Scroll capture is available, and a connection has been provided.
*
- * @param client interface to a ScrollCaptureCallback in the window process
+ * @param connection a connection to a window process and scrollable content
* @param scrollAreaInWindow the location of scrolling in global (window) coordinate space
*/
- oneway void onClientConnected(in IScrollCaptureClient client, in Rect scrollBounds,
+ oneway void onConnected(in IScrollCaptureConnection connection, in Rect scrollBounds,
in Point positionInWindow);
/**
- * Nothing in the window can be scrolled, scroll capture not offered.
+ * The window does not support scroll capture.
*/
- oneway void onClientUnavailable();
+ oneway void onUnavailable();
/**
- * Notifies the system that the client has confirmed the request and is ready to begin providing
- * image requests.
+ * Called when the remote end has confirmed the request and is ready to begin providing image
+ * requests.
*/
oneway void onCaptureStarted();
diff --git a/core/java/android/view/IScrollCaptureClient.aidl b/core/java/android/view/IScrollCaptureConnection.aidl
index 5f135a37dfef..63a4f48aeb20 100644
--- a/core/java/android/view/IScrollCaptureClient.aidl
+++ b/core/java/android/view/IScrollCaptureConnection.aidl
@@ -26,7 +26,7 @@ import android.view.Surface;
*
* {@hide}
*/
-interface IScrollCaptureClient {
+interface IScrollCaptureConnection {
/**
* Informs the client that it has been selected for scroll capture and should prepare to
diff --git a/core/java/android/view/IWindow.aidl b/core/java/android/view/IWindow.aidl
index 193e674dd1b0..e685b30421be 100644
--- a/core/java/android/view/IWindow.aidl
+++ b/core/java/android/view/IWindow.aidl
@@ -26,7 +26,7 @@ import android.view.DisplayCutout;
import android.view.DragEvent;
import android.view.InsetsSourceControl;
import android.view.InsetsState;
-import android.view.IScrollCaptureController;
+import android.view.IScrollCaptureCallbacks;
import android.view.KeyEvent;
import android.view.MotionEvent;
import android.window.ClientWindowFrames;
@@ -137,7 +137,7 @@ oneway interface IWindow {
/**
* Called when Scroll Capture support is requested for a window.
*
- * @param controller the controller to receive responses
+ * @param callbacks to receive responses
*/
- void requestScrollCapture(in IScrollCaptureController controller);
+ void requestScrollCapture(in IScrollCaptureCallbacks callbacks);
}
diff --git a/core/java/android/view/IWindowManager.aidl b/core/java/android/view/IWindowManager.aidl
index c460f74e7460..f572eb91ef34 100644
--- a/core/java/android/view/IWindowManager.aidl
+++ b/core/java/android/view/IWindowManager.aidl
@@ -42,7 +42,7 @@ import android.view.IDisplayFoldListener;
import android.view.IDisplayWindowRotationController;
import android.view.IOnKeyguardExitResult;
import android.view.IPinnedStackListener;
-import android.view.IScrollCaptureController;
+import android.view.IScrollCaptureCallbacks;
import android.view.RemoteAnimationAdapter;
import android.view.IRotationWatcher;
import android.view.ISystemGestureExclusionListener;
@@ -729,7 +729,6 @@ interface IWindowManager
* @return {@code true} if system bars are always comsumed.
*/
boolean getWindowInsets(in WindowManager.LayoutParams attrs, int displayId,
- out Rect outContentInsets, out Rect outStableInsets,
out DisplayCutout.ParcelableWrapper outDisplayCutout, out InsetsState outInsetsState);
/**
@@ -751,12 +750,10 @@ interface IWindowManager
* @param behindClient token for a window, used to filter the search to windows behind it, or
* {@code null} to accept a window at any zOrder
* @param taskId specifies the id of a task the result must belong to, or -1 to ignore task ids
- * @param controller the controller to receive results, a call to either
- * {@link IScrollCaptureController#onClientConnected} or
- * {@link IScrollCaptureController#onClientUnavailable}.
+ * @param callbacks the object to receive replies
*/
void requestScrollCapture(int displayId, IBinder behindClient, int taskId,
- IScrollCaptureController controller);
+ IScrollCaptureCallbacks callbacks);
/**
* Holds the WM lock for the specified amount of milliseconds.
diff --git a/core/java/android/view/IWindowSession.aidl b/core/java/android/view/IWindowSession.aidl
index 7f36169ada50..9febc9f09ef3 100644
--- a/core/java/android/view/IWindowSession.aidl
+++ b/core/java/android/view/IWindowSession.aidl
@@ -46,18 +46,16 @@ import java.util.List;
interface IWindowSession {
int addToDisplay(IWindow window, in WindowManager.LayoutParams attrs,
in int viewVisibility, in int layerStackId, in InsetsState requestedVisibility,
- out Rect outFrame, out Rect outContentInsets, out Rect outStableInsets,
+ out Rect outFrame, out DisplayCutout.ParcelableWrapper displayCutout,
+ out InputChannel outInputChannel, out InsetsState insetsState,
+ out InsetsSourceControl[] activeControls);
+ int addToDisplayAsUser(IWindow window, in WindowManager.LayoutParams attrs,
+ in int viewVisibility, in int layerStackId, in int userId,
+ in InsetsState requestedVisibility, out Rect outFrame,
out DisplayCutout.ParcelableWrapper displayCutout, out InputChannel outInputChannel,
out InsetsState insetsState, out InsetsSourceControl[] activeControls);
- int addToDisplayAsUser(IWindow window, in WindowManager.LayoutParams attrs,
- in int viewVisibility, in int layerStackId, in int userId,
- in InsetsState requestedVisibility,
- out Rect outFrame, out Rect outContentInsets, out Rect outStableInsets,
- out DisplayCutout.ParcelableWrapper displayCutout, out InputChannel outInputChannel,
- out InsetsState insetsState, out InsetsSourceControl[] activeControls);
int addToDisplayWithoutInputChannel(IWindow window, in WindowManager.LayoutParams attrs,
- in int viewVisibility, in int layerStackId, out Rect outContentInsets,
- out Rect outStableInsets, out InsetsState insetsState);
+ in int viewVisibility, in int layerStackId, out InsetsState insetsState);
@UnsupportedAppUsage
void remove(IWindow window);
diff --git a/core/java/android/view/InsetsAnimationControlImpl.java b/core/java/android/view/InsetsAnimationControlImpl.java
index 878583be87c9..06ddf3c69f8e 100644
--- a/core/java/android/view/InsetsAnimationControlImpl.java
+++ b/core/java/android/view/InsetsAnimationControlImpl.java
@@ -38,6 +38,7 @@ import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION;
import static com.android.internal.annotations.VisibleForTesting.Visibility.PACKAGE;
import android.annotation.Nullable;
+import android.content.res.CompatibilityInfo;
import android.graphics.Insets;
import android.graphics.Matrix;
import android.graphics.Rect;
@@ -90,6 +91,7 @@ public class InsetsAnimationControlImpl implements WindowInsetsAnimationControll
private final WindowInsetsAnimation mAnimation;
/** @see WindowInsetsAnimationController#hasZeroInsetsIme */
private final boolean mHasZeroInsetsIme;
+ private final CompatibilityInfo.Translator mTranslator;
private Insets mCurrentInsets;
private Insets mPendingInsets;
private float mPendingFraction;
@@ -107,7 +109,7 @@ public class InsetsAnimationControlImpl implements WindowInsetsAnimationControll
InsetsState state, WindowInsetsAnimationControlListener listener,
@InsetsType int types,
InsetsAnimationControlCallbacks controller, long durationMs, Interpolator interpolator,
- @AnimationType int animationType) {
+ @AnimationType int animationType, CompatibilityInfo.Translator translator) {
mControls = controls;
mListener = listener;
mTypes = types;
@@ -131,6 +133,7 @@ public class InsetsAnimationControlImpl implements WindowInsetsAnimationControll
durationMs);
mAnimation.setAlpha(getCurrentAlpha());
mAnimationType = animationType;
+ mTranslator = translator;
mController.startAnimation(this, listener, types, mAnimation,
new Bounds(mHiddenInsets, mShownInsets));
@@ -396,21 +399,23 @@ public class InsetsAnimationControlImpl implements WindowInsetsAnimationControll
private void addTranslationToMatrix(@InternalInsetsSide int side, int inset, Matrix m,
Rect frame) {
+ final float surfaceOffset = mTranslator != null
+ ? mTranslator.translateLengthInAppWindowToScreen(inset) : inset;
switch (side) {
case ISIDE_LEFT:
- m.postTranslate(-inset, 0);
+ m.postTranslate(-surfaceOffset, 0);
frame.offset(-inset, 0);
break;
case ISIDE_TOP:
- m.postTranslate(0, -inset);
+ m.postTranslate(0, -surfaceOffset);
frame.offset(0, -inset);
break;
case ISIDE_RIGHT:
- m.postTranslate(inset, 0);
+ m.postTranslate(surfaceOffset, 0);
frame.offset(inset, 0);
break;
case ISIDE_BOTTOM:
- m.postTranslate(0, inset);
+ m.postTranslate(0, surfaceOffset);
frame.offset(0, inset);
break;
}
diff --git a/core/java/android/view/InsetsAnimationThreadControlRunner.java b/core/java/android/view/InsetsAnimationThreadControlRunner.java
index 1307052a25cc..4a5fa0f971ae 100644
--- a/core/java/android/view/InsetsAnimationThreadControlRunner.java
+++ b/core/java/android/view/InsetsAnimationThreadControlRunner.java
@@ -20,6 +20,7 @@ import static android.view.InsetsController.DEBUG;
import static android.view.SyncRtSurfaceTransactionApplier.applyParams;
import android.annotation.UiThread;
+import android.content.res.CompatibilityInfo;
import android.graphics.Rect;
import android.os.Handler;
import android.os.Trace;
@@ -102,11 +103,12 @@ public class InsetsAnimationThreadControlRunner implements InsetsAnimationContro
InsetsState state, WindowInsetsAnimationControlListener listener,
@InsetsType int types,
InsetsAnimationControlCallbacks controller, long durationMs, Interpolator interpolator,
- @AnimationType int animationType, Handler mainThreadHandler) {
+ @AnimationType int animationType, CompatibilityInfo.Translator translator,
+ Handler mainThreadHandler) {
mMainThreadHandler = mainThreadHandler;
mOuterCallbacks = controller;
mControl = new InsetsAnimationControlImpl(controls, frame, state, listener,
- types, mCallbacks, durationMs, interpolator, animationType);
+ types, mCallbacks, durationMs, interpolator, animationType, translator);
InsetsAnimationThread.getHandler().post(() -> {
Trace.asyncTraceBegin(Trace.TRACE_TAG_VIEW,
"InsetsAsyncAnimation: " + WindowInsets.Type.toString(types), types);
diff --git a/core/java/android/view/InsetsController.java b/core/java/android/view/InsetsController.java
index 5037d9e5bfe8..b5bf08443a6c 100644
--- a/core/java/android/view/InsetsController.java
+++ b/core/java/android/view/InsetsController.java
@@ -33,6 +33,7 @@ import android.animation.ValueAnimator;
import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.Nullable;
+import android.content.res.CompatibilityInfo;
import android.graphics.Insets;
import android.graphics.Rect;
import android.os.CancellationSignal;
@@ -176,6 +177,14 @@ public class InsetsController implements WindowInsetsController, InsetsAnimation
*/
@Nullable
IBinder getWindowToken();
+
+ /**
+ * @return Translator associated with the host, if it has one.
+ */
+ @Nullable
+ default CompatibilityInfo.Translator getTranslator() {
+ return null;
+ }
}
private static final String TAG = "InsetsController";
@@ -994,10 +1003,10 @@ public class InsetsController implements WindowInsetsController, InsetsAnimation
final InsetsAnimationControlRunner runner = useInsetsAnimationThread
? new InsetsAnimationThreadControlRunner(controls,
frame, mState, listener, typesReady, this, durationMs, interpolator,
- animationType, mHost.getHandler())
+ animationType, mHost.getTranslator(), mHost.getHandler())
: new InsetsAnimationControlImpl(controls,
frame, mState, listener, typesReady, this, durationMs, interpolator,
- animationType);
+ animationType, mHost.getTranslator());
mRunningAnimations.add(new RunningAnimation(runner, animationType));
if (DEBUG) Log.d(TAG, "Animation added to runner. useInsetsAnimationThread: "
+ useInsetsAnimationThread);
diff --git a/core/java/android/view/InsetsState.java b/core/java/android/view/InsetsState.java
index b9f1f6a43992..ac29f2eb5c0b 100644
--- a/core/java/android/view/InsetsState.java
+++ b/core/java/android/view/InsetsState.java
@@ -427,6 +427,25 @@ public class InsetsState implements Parcelable {
}
}
+ /**
+ * Scales the frame and the visible frame (if there is one) of each source.
+ *
+ * @param scale the scale to be applied
+ */
+ public void scale(float scale) {
+ mDisplayFrame.scale(scale);
+ for (int i = 0; i < SIZE; i++) {
+ final InsetsSource source = mSources[i];
+ if (source != null) {
+ source.getFrame().scale(scale);
+ final Rect visibleFrame = source.getVisibleFrame();
+ if (visibleFrame != null) {
+ visibleFrame.scale(scale);
+ }
+ }
+ }
+ }
+
public void set(InsetsState other) {
set(other, false /* copySources */);
}
diff --git a/core/java/android/view/NotificationHeaderView.java b/core/java/android/view/NotificationHeaderView.java
index 0c3d61f31dfb..355b314a0b8f 100644
--- a/core/java/android/view/NotificationHeaderView.java
+++ b/core/java/android/view/NotificationHeaderView.java
@@ -17,7 +17,6 @@
package android.view;
import android.annotation.Nullable;
-import android.app.Notification;
import android.compat.annotation.UnsupportedAppUsage;
import android.content.Context;
import android.content.res.Resources;
@@ -27,8 +26,6 @@ import android.graphics.Outline;
import android.graphics.Rect;
import android.graphics.drawable.Drawable;
import android.util.AttributeSet;
-import android.widget.ImageView;
-import android.widget.LinearLayout;
import android.widget.RemoteViews;
import com.android.internal.R;
@@ -44,7 +41,6 @@ import java.util.ArrayList;
*/
@RemoteViews.RemoteView
public class NotificationHeaderView extends ViewGroup {
- public static final int NO_COLOR = Notification.COLOR_INVALID;
private final int mChildMinWidth;
private final int mContentEndMargin;
private final int mGravity;
@@ -54,12 +50,10 @@ public class NotificationHeaderView extends ViewGroup {
private OnClickListener mExpandClickListener;
private OnClickListener mFeedbackListener;
private HeaderTouchListener mTouchListener = new HeaderTouchListener();
- private LinearLayout mTransferChip;
private NotificationExpandButton mExpandButton;
private CachingIconView mIcon;
private View mProfileBadge;
private View mFeedbackIcon;
- private boolean mExpanded;
private boolean mShowExpandButtonAtEnd;
private boolean mShowWorkBadgeAtEnd;
private int mHeaderTextMarginEnd;
@@ -111,7 +105,6 @@ public class NotificationHeaderView extends ViewGroup {
mAppName = findViewById(com.android.internal.R.id.app_name_text);
mHeaderText = findViewById(com.android.internal.R.id.header_text);
mSecondaryHeaderText = findViewById(com.android.internal.R.id.header_text_secondary);
- mTransferChip = findViewById(com.android.internal.R.id.media_seamless);
mExpandButton = findViewById(com.android.internal.R.id.expand_button);
mIcon = findViewById(com.android.internal.R.id.icon);
mProfileBadge = findViewById(com.android.internal.R.id.profile_badge);
@@ -143,8 +136,7 @@ public class NotificationHeaderView extends ViewGroup {
// Icons that should go at the end
if ((child == mExpandButton && mShowExpandButtonAtEnd)
|| child == mProfileBadge
- || child == mFeedbackIcon
- || child == mTransferChip) {
+ || child == mFeedbackIcon) {
iconWidth += lp.leftMargin + lp.rightMargin + child.getMeasuredWidth();
} else {
totalWidth += lp.leftMargin + lp.rightMargin + child.getMeasuredWidth();
@@ -208,8 +200,7 @@ public class NotificationHeaderView extends ViewGroup {
// Icons that should go at the end
if ((child == mExpandButton && mShowExpandButtonAtEnd)
|| child == mProfileBadge
- || child == mFeedbackIcon
- || child == mTransferChip) {
+ || child == mFeedbackIcon) {
if (end == getMeasuredWidth()) {
layoutRight = end - mContentEndMargin;
} else {
@@ -301,35 +292,6 @@ public class NotificationHeaderView extends ViewGroup {
updateTouchListener();
}
- public int getOriginalIconColor() {
- return mIcon.getOriginalIconColor();
- }
-
- public int getOriginalNotificationColor() {
- return mExpandButton.getOriginalNotificationColor();
- }
-
- @RemotableViewMethod
- public void setExpanded(boolean expanded) {
- mExpanded = expanded;
- updateExpandButton();
- }
-
- private void updateExpandButton() {
- int drawableId;
- int contentDescriptionId;
- if (mExpanded) {
- drawableId = R.drawable.ic_collapse_notification;
- contentDescriptionId = R.string.expand_button_content_description_expanded;
- } else {
- drawableId = R.drawable.ic_expand_notification;
- contentDescriptionId = R.string.expand_button_content_description_collapsed;
- }
- mExpandButton.setImageDrawable(getContext().getDrawable(drawableId));
- mExpandButton.setColorFilter(getOriginalNotificationColor());
- mExpandButton.setContentDescription(mContext.getText(contentDescriptionId));
- }
-
public void setShowWorkBadgeAtEnd(boolean showWorkBadgeAtEnd) {
if (showWorkBadgeAtEnd != mShowWorkBadgeAtEnd) {
setClipToPadding(!showWorkBadgeAtEnd);
@@ -349,14 +311,6 @@ public class NotificationHeaderView extends ViewGroup {
}
}
- public View getWorkProfileIcon() {
- return mProfileBadge;
- }
-
- public CachingIconView getIcon() {
- return mIcon;
- }
-
/**
* Sets the margin end for the text portion of the header, excluding right-aligned elements
* @param headerTextMarginEnd margin size
@@ -495,10 +449,6 @@ public class NotificationHeaderView extends ViewGroup {
return this;
}
- public ImageView getExpandButton() {
- return mExpandButton;
- }
-
@Override
public boolean hasOverlappingRendering() {
return false;
diff --git a/core/java/android/view/ScrollCaptureCallback.java b/core/java/android/view/ScrollCaptureCallback.java
index e1a4e7443600..d3aad2c72d27 100644
--- a/core/java/android/view/ScrollCaptureCallback.java
+++ b/core/java/android/view/ScrollCaptureCallback.java
@@ -29,8 +29,8 @@ import java.util.function.Consumer;
* callbacks registered within the window.
* <p>
* A callback is assigned to a View using {@link View#setScrollCaptureCallback}, or to the window as
- * {@link Window#addScrollCaptureCallback}. The point where the callback is registered defines the
- * frame of reference for the bounds measurements used.
+ * {@link Window#registerScrollCaptureCallback}. The point where the callback is registered defines
+ * the frame of reference for the bounds measurements used.
* <p>
* <b>Terminology</b>
* <dl>
@@ -39,9 +39,9 @@ import java.util.function.Consumer;
* is assigned directly to a window.</dd>
*
* <dt>Scroll Bounds</dt>
- * <dd>A rectangle which describes an area within the containing view where scrolling content may
- * be positioned. This may be the Containing View bounds itself, or any rectangle within.
- * Requested by {@link #onScrollCaptureSearch}.</dd>
+ * <dd>A rectangle which describes an area within the containing view where scrolling content
+ * appears. This may be the entire view or any rectangle within. This defines a frame of reference
+ * for requests as well as the width and maximum height of a single request.</dd>
*
* <dt>Scroll Delta</dt>
* <dd>The distance the scroll position has moved since capture started. Implementations are
@@ -57,7 +57,7 @@ import java.util.function.Consumer;
*
* @see View#setScrollCaptureHint(int)
* @see View#setScrollCaptureCallback(ScrollCaptureCallback)
- * @see Window#addScrollCaptureCallback(ScrollCaptureCallback)
+ * @see Window#registerScrollCaptureCallback(ScrollCaptureCallback)
*
* @hide
*/
diff --git a/core/java/android/view/ScrollCaptureClient.java b/core/java/android/view/ScrollCaptureConnection.java
index f163124f3a98..0e6cdd1dbec5 100644
--- a/core/java/android/view/ScrollCaptureClient.java
+++ b/core/java/android/view/ScrollCaptureConnection.java
@@ -19,7 +19,6 @@ package android.view;
import static java.util.Objects.requireNonNull;
import android.annotation.NonNull;
-import android.annotation.Nullable;
import android.annotation.UiThread;
import android.annotation.WorkerThread;
import android.graphics.Point;
@@ -33,15 +32,15 @@ import com.android.internal.annotations.VisibleForTesting;
import java.util.concurrent.atomic.AtomicBoolean;
/**
- * A client of the system providing Scroll Capture capability on behalf of a Window.
+ * Mediator between a selected scroll capture target view and a remote process.
* <p>
* An instance is created to wrap the selected {@link ScrollCaptureCallback}.
*
* @hide
*/
-public class ScrollCaptureClient extends IScrollCaptureClient.Stub {
+public class ScrollCaptureConnection extends IScrollCaptureConnection.Stub {
- private static final String TAG = "ScrollCaptureClient";
+ private static final String TAG = "ScrollCaptureConnection";
private static final int DEFAULT_TIMEOUT = 1000;
private final Handler mHandler;
@@ -49,7 +48,7 @@ public class ScrollCaptureClient extends IScrollCaptureClient.Stub {
private int mTimeoutMillis = DEFAULT_TIMEOUT;
protected Surface mSurface;
- private IScrollCaptureController mController;
+ private IScrollCaptureCallbacks mCallbacks;
private final Rect mScrollBounds;
private final Point mPositionInWindow;
@@ -62,18 +61,18 @@ public class ScrollCaptureClient extends IScrollCaptureClient.Stub {
private DelayedAction mTimeoutAction;
/**
- * Constructs a ScrollCaptureClient.
+ * Constructs a ScrollCaptureConnection.
*
* @param selectedTarget the target the client is controlling
- * @param controller the callbacks to reply to system requests
+ * @param callbacks the callbacks to reply to system requests
*
* @hide
*/
- public ScrollCaptureClient(
+ public ScrollCaptureConnection(
@NonNull ScrollCaptureTarget selectedTarget,
- @NonNull IScrollCaptureController controller) {
+ @NonNull IScrollCaptureCallbacks callbacks) {
requireNonNull(selectedTarget, "<selectedTarget> must non-null");
- requireNonNull(controller, "<controller> must non-null");
+ requireNonNull(callbacks, "<callbacks> must non-null");
final Rect scrollBounds = requireNonNull(selectedTarget.getScrollBounds(),
"target.getScrollBounds() must be non-null to construct a client");
@@ -82,7 +81,7 @@ public class ScrollCaptureClient extends IScrollCaptureClient.Stub {
mScrollBounds = new Rect(scrollBounds);
mPositionInWindow = new Point(selectedTarget.getPositionInWindow());
- mController = controller;
+ mCallbacks = callbacks;
mCloseGuard = new CloseGuard();
mCloseGuard.open("close");
@@ -106,14 +105,13 @@ public class ScrollCaptureClient extends IScrollCaptureClient.Stub {
mTimeoutMillis = timeoutMillis;
}
- @Nullable
@VisibleForTesting
public DelayedAction getTimeoutAction() {
return mTimeoutAction;
}
private void checkConnected() {
- if (mSelectedTarget == null || mController == null) {
+ if (mSelectedTarget == null || mCallbacks == null) {
throw new IllegalStateException("This client has been disconnected.");
}
}
@@ -124,7 +122,7 @@ public class ScrollCaptureClient extends IScrollCaptureClient.Stub {
}
}
- @WorkerThread // IScrollCaptureClient
+ @WorkerThread // IScrollCaptureConnection
@Override
public void startCapture(Surface surface) throws RemoteException {
checkConnected();
@@ -140,7 +138,7 @@ public class ScrollCaptureClient extends IScrollCaptureClient.Stub {
if (cancelTimeout()) {
mHandler.post(() -> {
try {
- mController.onCaptureStarted();
+ mCallbacks.onCaptureStarted();
} catch (RemoteException e) {
doShutdown();
}
@@ -153,7 +151,7 @@ public class ScrollCaptureClient extends IScrollCaptureClient.Stub {
endCapture();
}
- @WorkerThread // IScrollCaptureClient
+ @WorkerThread // IScrollCaptureConnection
@Override
public void requestImage(Rect requestRect) {
checkConnected();
@@ -170,7 +168,7 @@ public class ScrollCaptureClient extends IScrollCaptureClient.Stub {
if (cancelTimeout()) {
mHandler.post(() -> {
try {
- mController.onCaptureBufferSent(frameNumber, finalCapturedArea);
+ mCallbacks.onCaptureBufferSent(frameNumber, finalCapturedArea);
} catch (RemoteException e) {
doShutdown();
}
@@ -183,7 +181,7 @@ public class ScrollCaptureClient extends IScrollCaptureClient.Stub {
endCapture();
}
- @WorkerThread // IScrollCaptureClient
+ @WorkerThread // IScrollCaptureConnection
@Override
public void endCapture() {
if (isStarted()) {
@@ -196,7 +194,7 @@ public class ScrollCaptureClient extends IScrollCaptureClient.Stub {
}
private boolean isStarted() {
- return mController != null && mSelectedTarget != null;
+ return mCallbacks != null && mSelectedTarget != null;
}
@UiThread
@@ -214,8 +212,8 @@ public class ScrollCaptureClient extends IScrollCaptureClient.Stub {
private void doShutdown() {
try {
- if (mController != null) {
- mController.onConnectionClosed();
+ if (mCallbacks != null) {
+ mCallbacks.onConnectionClosed();
}
} catch (RemoteException e) {
// Ignore
@@ -235,15 +233,15 @@ public class ScrollCaptureClient extends IScrollCaptureClient.Stub {
}
mSelectedTarget = null;
- mController = null;
+ mCallbacks = null;
}
/** @return a string representation of the state of this client */
public String toString() {
- return "ScrollCaptureClient{"
+ return "ScrollCaptureConnection{"
+ ", session=" + mSession
+ ", selectedTarget=" + mSelectedTarget
- + ", clientCallbacks=" + mController
+ + ", clientCallbacks=" + mCallbacks
+ "}";
}
diff --git a/core/java/android/view/ScrollCaptureSession.java b/core/java/android/view/ScrollCaptureSession.java
index 628e23fb3f5e..92617a325265 100644
--- a/core/java/android/view/ScrollCaptureSession.java
+++ b/core/java/android/view/ScrollCaptureSession.java
@@ -36,15 +36,15 @@ public class ScrollCaptureSession {
private final Point mPositionInWindow;
@Nullable
- private ScrollCaptureClient mClient;
+ private ScrollCaptureConnection mConnection;
/** @hide */
public ScrollCaptureSession(Surface surface, Rect scrollBounds, Point positionInWindow,
- ScrollCaptureClient client) {
+ ScrollCaptureConnection connection) {
mSurface = surface;
mScrollBounds = scrollBounds;
mPositionInWindow = positionInWindow;
- mClient = client;
+ mConnection = connection;
}
/**
@@ -88,8 +88,8 @@ public class ScrollCaptureSession {
* @param capturedArea the area captured, relative to scroll bounds
*/
public void notifyBufferSent(long frameNumber, @NonNull Rect capturedArea) {
- if (mClient != null) {
- mClient.onRequestImageCompleted(frameNumber, capturedArea);
+ if (mConnection != null) {
+ mConnection.onRequestImageCompleted(frameNumber, capturedArea);
}
}
@@ -97,7 +97,7 @@ public class ScrollCaptureSession {
* @hide
*/
public void disconnect() {
- mClient = null;
+ mConnection = null;
if (mSurface.isValid()) {
mSurface.release();
}
diff --git a/core/java/android/view/ScrollCaptureTargetResolver.java b/core/java/android/view/ScrollCaptureTargetResolver.java
index 71e82c511e2c..5106534694a1 100644
--- a/core/java/android/view/ScrollCaptureTargetResolver.java
+++ b/core/java/android/view/ScrollCaptureTargetResolver.java
@@ -57,7 +57,6 @@ import java.util.function.Consumer;
@UiThread
public class ScrollCaptureTargetResolver {
private static final String TAG = "ScrollCaptureTargetRes";
- private static final boolean DEBUG = true;
private final Object mLock = new Object();
@@ -86,18 +85,11 @@ public class ScrollCaptureTargetResolver {
* Binary operator which selects the best {@link ScrollCaptureTarget}.
*/
private static ScrollCaptureTarget chooseTarget(ScrollCaptureTarget a, ScrollCaptureTarget b) {
- Log.d(TAG, "chooseTarget: " + a + " or " + b);
- // Nothing plus nothing is still nothing.
if (a == null && b == null) {
- Log.d(TAG, "chooseTarget: (both null) return " + null);
return null;
- }
- // Prefer non-null.
- if (a == null || b == null) {
+ } else if (a == null || b == null) {
ScrollCaptureTarget c = (a == null) ? b : a;
- Log.d(TAG, "chooseTarget: (other is null) return " + c);
return c;
-
}
boolean emptyScrollBoundsA = nullOrEmpty(a.getScrollBounds());
@@ -155,8 +147,7 @@ public class ScrollCaptureTargetResolver {
*
* @param targets a list of {@link ScrollCaptureTarget} as collected by {@link
* View#dispatchScrollCaptureSearch}.
- * @param uiHandler the UI thread handler for the view tree
- * @see #start(long, Consumer)
+ * @see #start(Handler, long, Consumer)
*/
public ScrollCaptureTargetResolver(Queue<ScrollCaptureTarget> targets) {
mTargets = targets;
@@ -184,7 +175,6 @@ public class ScrollCaptureTargetResolver {
return mResult;
}
-
private void supplyResult(ScrollCaptureTarget target) {
checkThread();
if (mFinished) {
@@ -232,12 +222,11 @@ public class ScrollCaptureTargetResolver {
return;
}
mStarted = true;
- uiHandler.post(() -> run(timeLimitMillis, resultConsumer));
+ uiHandler.post(this::run);
}
}
-
- private void run(long timeLimitMillis, Consumer<ScrollCaptureTarget> resultConsumer) {
+ private void run() {
checkThread();
mPendingBoundsRequests = mTargets.size();
@@ -248,15 +237,11 @@ public class ScrollCaptureTargetResolver {
mHandler.postAtTime(mTimeoutRunnable, mDeadlineMillis);
}
- private final Runnable mTimeoutRunnable = new Runnable() {
- @Override
- public void run() {
- checkThread();
- supplyResult(null);
- }
+ private final Runnable mTimeoutRunnable = () -> {
+ checkThread();
+ supplyResult(null);
};
-
/**
* Adds a target to the list and requests {@link ScrollCaptureCallback#onScrollCaptureSearch}
* scrollBounds} from it. Results are returned by a call to {@link #onScrollBoundsProvided}.
@@ -274,7 +259,6 @@ public class ScrollCaptureTargetResolver {
// Queue and consume on the UI thread
((scrollBounds) -> mHandler.post(
() -> onScrollBoundsProvided(target, scrollBounds)))));
-
}
@UiThread
@@ -300,14 +284,8 @@ public class ScrollCaptureTargetResolver {
supplyResult(target);
}
- System.err.println("mPendingBoundsRequests: " + mPendingBoundsRequests);
- System.err.println("mDeadlineMillis: " + mDeadlineMillis);
- System.err.println("SystemClock.elapsedRealtime(): " + SystemClock.elapsedRealtime());
-
if (!mFinished) {
// Reschedule the timeout.
- System.err.println(
- "We think we're NOT done yet and will check back at " + mDeadlineMillis);
mHandler.postAtTime(mTimeoutRunnable, mDeadlineMillis);
}
}
@@ -334,44 +312,17 @@ public class ScrollCaptureTargetResolver {
return otherParent == view;
}
- private static int findRelation(@NonNull View a, @NonNull View b) {
- if (a == b) {
- return 0;
- }
-
- ViewParent parentA = a.getParent();
- ViewParent parentB = b.getParent();
-
- while (parentA != null || parentB != null) {
- if (parentA == parentB) {
- return 0;
- }
- if (parentA == b) {
- return 1; // A is descendant of B
- }
- if (parentB == a) {
- return -1; // B is descendant of A
- }
- if (parentA != null) {
- parentA = parentA.getParent();
- }
- if (parentB != null) {
- parentB = parentB.getParent();
- }
- }
- return 0;
- }
-
/**
* A safe wrapper for a consumer callbacks intended to accept a single value. It ensures
* that the receiver of the consumer does not retain a reference to {@code target} after use nor
* cause race conditions by invoking {@link Consumer#accept accept} more than once.
- *
- * @param target the target consumer
*/
static class SingletonConsumer<T> implements Consumer<T> {
final AtomicReference<Consumer<T>> mAtomicRef;
+ /**
+ * @param target the target consumer
+ **/
SingletonConsumer(Consumer<T> target) {
mAtomicRef = new AtomicReference<>(target);
}
diff --git a/core/java/android/view/SurfaceControl.java b/core/java/android/view/SurfaceControl.java
index bbdd7d339507..6d6fabb16b72 100644
--- a/core/java/android/view/SurfaceControl.java
+++ b/core/java/android/view/SurfaceControl.java
@@ -1623,6 +1623,16 @@ public final class SurfaceControl implements Parcelable {
/**
* @hide
*/
+ public void setBackgroundBlurRadius(int blur) {
+ checkNotReleased();
+ synchronized (SurfaceControl.class) {
+ sGlobalTransaction.setBackgroundBlurRadius(this, blur);
+ }
+ }
+
+ /**
+ * @hide
+ */
public void setMatrix(float dsdx, float dtdx, float dtdy, float dsdy) {
checkNotReleased();
synchronized(SurfaceControl.class) {
diff --git a/core/java/android/view/SurfaceView.java b/core/java/android/view/SurfaceView.java
index 7b6a4f877d02..432d9279c48d 100644
--- a/core/java/android/view/SurfaceView.java
+++ b/core/java/android/view/SurfaceView.java
@@ -1849,7 +1849,7 @@ public class SurfaceView extends View implements ViewRootImpl.SurfaceChangedCall
// If developers explicitly set the important mode for it, don't change the mode.
// Only change the mode to important when this SurfaceView isn't explicitly set and has
// an embedded hierarchy.
- if (!mRemoteAccessibilityController.connected()
+ if ((mRemoteAccessibilityController!= null && !mRemoteAccessibilityController.connected())
|| mode != IMPORTANT_FOR_ACCESSIBILITY_AUTO) {
return mode;
}
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index cf5ca56eb188..667f0b9511d0 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -6150,6 +6150,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
* was set.
*/
@NonNull
+ @SuppressWarnings("AndroidFrameworkEfficientCollections")
public Map<Integer, Integer> getAttributeSourceResourceMap() {
HashMap<Integer, Integer> map = new HashMap<>();
if (!sDebugViewAttributes || mAttributeSourceResId == null) {
@@ -14861,15 +14862,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
*/
public void getWindowVisibleDisplayFrame(Rect outRect) {
if (mAttachInfo != null) {
- mAttachInfo.mViewRootImpl.getDisplayFrame(outRect);
- // XXX This is really broken, and probably all needs to be done
- // in the window manager, and we need to know more about whether
- // we want the area behind or in front of the IME.
- final Rect insets = mAttachInfo.mVisibleInsets;
- outRect.left += insets.left;
- outRect.top += insets.top;
- outRect.right -= insets.right;
- outRect.bottom -= insets.bottom;
+ mAttachInfo.mViewRootImpl.getWindowVisibleDisplayFrame(outRect);
return;
}
// The view is not attached to a display so we don't have a context.
diff --git a/core/java/android/view/ViewGroup.java b/core/java/android/view/ViewGroup.java
index fd7c2d896b09..eb6c49549100 100644
--- a/core/java/android/view/ViewGroup.java
+++ b/core/java/android/view/ViewGroup.java
@@ -50,6 +50,7 @@ import android.os.Bundle;
import android.os.Parcelable;
import android.os.SystemClock;
import android.util.AttributeSet;
+import android.util.IntArray;
import android.util.Log;
import android.util.Pools;
import android.util.Pools.SynchronizedPool;
@@ -611,7 +612,7 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager
private int mNestedScrollAxes;
// Used to manage the list of transient views, added by addTransientView()
- private List<Integer> mTransientIndices = null;
+ private IntArray mTransientIndices = null;
private List<View> mTransientViews = null;
/**
@@ -4853,7 +4854,7 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager
}
if (mTransientIndices == null) {
- mTransientIndices = new ArrayList<Integer>();
+ mTransientIndices = new IntArray();
mTransientViews = new ArrayList<View>();
}
final int oldSize = mTransientIndices.size();
diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java
index 80f5c0fb8257..9bc07702feee 100644
--- a/core/java/android/view/ViewRootImpl.java
+++ b/core/java/android/view/ViewRootImpl.java
@@ -562,6 +562,9 @@ public final class ViewRootImpl implements ViewParent,
= new ViewTreeObserver.InternalInsetsInfo();
private WindowInsets mLastWindowInsets;
+ private final Rect mSystemInsetsCache = new Rect();
+ private final Rect mVisibleInsetsCache = new Rect();
+ private final Rect mStableInsetsCache = new Rect();
// Insets types hidden by legacy window flags or system UI flags.
private @InsetsType int mTypesHiddenByFlags = 0;
@@ -649,7 +652,7 @@ public final class ViewRootImpl implements ViewParent,
private final InsetsController mInsetsController;
private final ImeFocusController mImeFocusController;
- private ScrollCaptureClient mScrollCaptureClient;
+ private ScrollCaptureConnection mScrollCaptureConnection;
/**
* @return {@link ImeFocusController} for this instance.
@@ -659,10 +662,10 @@ public final class ViewRootImpl implements ViewParent,
return mImeFocusController;
}
- /** @return The current {@link ScrollCaptureClient} for this instance, if any is active. */
+ /** @return The current {@link ScrollCaptureConnection} for this instance, if any is active. */
@Nullable
- public ScrollCaptureClient getScrollCaptureClient() {
- return mScrollCaptureClient;
+ public ScrollCaptureConnection getScrollCaptureConnection() {
+ return mScrollCaptureConnection;
}
private final GestureExclusionTracker mGestureExclusionTracker = new GestureExclusionTracker();
@@ -1025,9 +1028,12 @@ public final class ViewRootImpl implements ViewParent,
res = mWindowSession.addToDisplayAsUser(mWindow, mWindowAttributes,
getHostVisibility(), mDisplay.getDisplayId(), userId,
mInsetsController.getRequestedVisibility(), mTmpFrames.frame,
- mAttachInfo.mContentInsets, mAttachInfo.mStableInsets,
mAttachInfo.mDisplayCutout, inputChannel,
mTempInsets, mTempControls);
+ if (mTranslator != null) {
+ mTranslator.translateRectInScreenToAppWindow(mTmpFrames.frame);
+ mTranslator.translateInsetsStateInScreenToAppWindow(mTempInsets);
+ }
setFrame(mTmpFrames.frame);
} catch (RemoteException e) {
mAdded = false;
@@ -1044,9 +1050,6 @@ public final class ViewRootImpl implements ViewParent,
}
}
- if (mTranslator != null) {
- mTranslator.translateRectInScreenToAppWindow(mAttachInfo.mContentInsets);
- }
mPendingDisplayCutout.set(mAttachInfo.mDisplayCutout);
mAttachInfo.mAlwaysConsumeSystemBars =
(res & WindowManagerGlobal.ADD_FLAG_ALWAYS_CONSUME_SYSTEM_BARS) != 0;
@@ -2313,12 +2316,10 @@ public final class ViewRootImpl implements ViewParent,
(mWindowAttributes.systemUiVisibility
| mWindowAttributes.subtreeSystemUiVisibility));
- Rect visibleInsets = mInsetsController.calculateVisibleInsets(
- mWindowAttributes.softInputMode);
-
- mAttachInfo.mVisibleInsets.set(visibleInsets);
- mAttachInfo.mContentInsets.set(mLastWindowInsets.getSystemWindowInsets().toRect());
- mAttachInfo.mStableInsets.set(mLastWindowInsets.getStableInsets().toRect());
+ mSystemInsetsCache.set(mLastWindowInsets.getSystemWindowInsets().toRect());
+ mStableInsetsCache.set(mLastWindowInsets.getStableInsets().toRect());
+ mVisibleInsetsCache.set(mInsetsController.calculateVisibleInsets(
+ mWindowAttributes.softInputMode));
}
return mLastWindowInsets;
}
@@ -2826,8 +2827,7 @@ public final class ViewRootImpl implements ViewParent,
&& mWinFrame.height() == mPendingBackDropFrame.height();
// TODO: Need cutout?
startDragResizing(mPendingBackDropFrame, !backdropSizeMatchesFrame,
- mLastWindowInsets.getSystemWindowInsets().toRect(),
- mLastWindowInsets.getStableInsets().toRect(), mResizeMode);
+ mSystemInsetsCache, mStableInsetsCache, mResizeMode);
} else {
// We shouldn't come here, but if we come we should end the resize.
endDragResizing();
@@ -3234,9 +3234,6 @@ public final class ViewRootImpl implements ViewParent,
final boolean windowMoved = mAttachInfo.mWindowLeft != frame.left
|| mAttachInfo.mWindowTop != frame.top;
if (windowMoved) {
- if (mTranslator != null) {
- mTranslator.translateRectInScreenToAppWinFrame(frame);
- }
mAttachInfo.mWindowLeft = frame.left;
mAttachInfo.mWindowTop = frame.top;
}
@@ -4450,8 +4447,8 @@ public final class ViewRootImpl implements ViewParent,
}
boolean scrollToRectOrFocus(Rect rectangle, boolean immediate) {
- final Rect ci = getWindowInsets(false).getSystemWindowInsetsAsRect();
- final Rect vi = mAttachInfo.mVisibleInsets;
+ final Rect ci = mSystemInsetsCache;
+ final Rect vi = mVisibleInsetsCache;
int scrollY = 0;
boolean handled = false;
@@ -5192,7 +5189,7 @@ public final class ViewRootImpl implements ViewParent,
updateLocationInParentDisplay(msg.arg1, msg.arg2);
} break;
case MSG_REQUEST_SCROLL_CAPTURE:
- handleScrollCaptureRequest((IScrollCaptureController) msg.obj);
+ handleScrollCaptureRequest((IScrollCaptureCallbacks) msg.obj);
break;
}
}
@@ -7516,7 +7513,8 @@ public final class ViewRootImpl implements ViewParent,
}
if (mTranslator != null) {
- mTranslator.translateRectInScreenToAppWinFrame(mTmpFrames.frame);
+ mTranslator.translateRectInScreenToAppWindow(mTmpFrames.frame);
+ mTranslator.translateInsetsStateInScreenToAppWindow(mTempInsets);
}
setFrame(mTmpFrames.frame);
mInsetsController.onStateChanged(mTempInsets);
@@ -7538,6 +7536,22 @@ public final class ViewRootImpl implements ViewParent,
}
/**
+ * Gets the current display size in which the window is being laid out, accounting for screen
+ * decorations around it.
+ */
+ void getWindowVisibleDisplayFrame(Rect outFrame) {
+ outFrame.set(mTmpFrames.displayFrame);
+ // XXX This is really broken, and probably all needs to be done
+ // in the window manager, and we need to know more about whether
+ // we want the area behind or in front of the IME.
+ final Rect insets = mVisibleInsetsCache;
+ outFrame.left += insets.left;
+ outFrame.top += insets.top;
+ outFrame.right -= insets.right;
+ outFrame.bottom -= insets.bottom;
+ }
+
+ /**
* {@inheritDoc}
*/
@Override
@@ -7856,13 +7870,8 @@ public final class ViewRootImpl implements ViewParent,
MergedConfiguration mergedConfiguration, boolean forceLayout,
boolean alwaysConsumeSystemBars, int displayId) {
final Rect frame = frames.frame;
- final Rect contentInsets = frames.contentInsets;
- final Rect visibleInsets = frames.visibleInsets;
- final Rect stableInsets = frames.stableInsets;
final Rect backDropFrame = frames.backdropFrame;
if (DEBUG_LAYOUT) Log.v(mTag, "Resizing " + this + ": frame=" + frame.toShortString()
- + " contentInsets=" + contentInsets.toShortString()
- + " visibleInsets=" + visibleInsets.toShortString()
+ " reportDraw=" + reportDraw
+ " backDropFrame=" + backDropFrame);
@@ -7873,7 +7882,7 @@ public final class ViewRootImpl implements ViewParent,
synchronized (mWindowCallbacks) {
for (int i = mWindowCallbacks.size() - 1; i >= 0; i--) {
mWindowCallbacks.get(i).onWindowSizeIsChanging(backDropFrame, fullscreen,
- visibleInsets, stableInsets);
+ mVisibleInsetsCache, mStableInsetsCache);
}
}
}
@@ -7881,8 +7890,6 @@ public final class ViewRootImpl implements ViewParent,
Message msg = mHandler.obtainMessage(reportDraw ? MSG_RESIZED_REPORT : MSG_RESIZED);
if (mTranslator != null) {
mTranslator.translateRectInScreenToAppWindow(frame);
- mTranslator.translateRectInScreenToAppWindow(contentInsets);
- mTranslator.translateRectInScreenToAppWindow(visibleInsets);
}
SomeArgs args = SomeArgs.obtain();
final boolean sameProcessCall = (Binder.getCallingPid() == android.os.Process.myPid());
@@ -7900,6 +7907,9 @@ public final class ViewRootImpl implements ViewParent,
if (Binder.getCallingPid() == android.os.Process.myPid()) {
insetsState = new InsetsState(insetsState, true /* copySource */);
}
+ if (mTranslator != null) {
+ mTranslator.translateInsetsStateInScreenToAppWindow(insetsState);
+ }
mHandler.obtainMessage(MSG_INSETS_CHANGED, insetsState).sendToTarget();
}
@@ -7913,6 +7923,9 @@ public final class ViewRootImpl implements ViewParent,
}
}
}
+ if (mTranslator != null) {
+ mTranslator.translateInsetsStateInScreenToAppWindow(insetsState);
+ }
SomeArgs args = SomeArgs.obtain();
args.arg1 = insetsState;
args.arg2 = activeControls;
@@ -8979,10 +8992,10 @@ public final class ViewRootImpl implements ViewParent,
/**
* Dispatches a scroll capture request to the view hierarchy on the ui thread.
*
- * @param controller the controller to receive replies
+ * @param callbacks for replies
*/
- public void dispatchScrollCaptureRequest(@NonNull IScrollCaptureController controller) {
- mHandler.obtainMessage(MSG_REQUEST_SCROLL_CAPTURE, controller).sendToTarget();
+ public void dispatchScrollCaptureRequest(@NonNull IScrollCaptureCallbacks callbacks) {
+ mHandler.obtainMessage(MSG_REQUEST_SCROLL_CAPTURE, callbacks).sendToTarget();
}
/**
@@ -9007,14 +9020,14 @@ public final class ViewRootImpl implements ViewParent,
* Handles an inbound request for scroll capture from the system. If a client is not already
* active, a search will be dispatched through the view tree to locate scrolling content.
* <p>
- * Either {@link IScrollCaptureController#onClientConnected(IScrollCaptureClient, Rect,
- * Point)} or {@link IScrollCaptureController#onClientUnavailable()} will be returned
+ * Either {@link IScrollCaptureCallbacks#onClientConnected(IScrollCaptureConnection, Rect,
+ * Point)} or {@link IScrollCaptureCallbacks#onUnavailable()} will be returned
* depending on the results of the search.
*
- * @param controller the interface to the system controller
+ * @param callbacks to receive responses
* @see ScrollCaptureTargetResolver
*/
- private void handleScrollCaptureRequest(@NonNull IScrollCaptureController controller) {
+ private void handleScrollCaptureRequest(@NonNull IScrollCaptureCallbacks callbacks) {
LinkedList<ScrollCaptureTarget> targetList = new LinkedList<>();
// Window (root) level callbacks
@@ -9029,7 +9042,7 @@ public final class ViewRootImpl implements ViewParent,
// No-op path. Scroll capture not offered for this window.
if (targetList.isEmpty()) {
- dispatchScrollCaptureSearchResult(controller, null);
+ dispatchScrollCaptureSearchResult(callbacks, null);
return;
}
@@ -9037,12 +9050,12 @@ public final class ViewRootImpl implements ViewParent,
// Continues with the consumer once all responses are consumed, or the timeout expires.
ScrollCaptureTargetResolver resolver = new ScrollCaptureTargetResolver(targetList);
resolver.start(mHandler, 1000,
- (selected) -> dispatchScrollCaptureSearchResult(controller, selected));
+ (selected) -> dispatchScrollCaptureSearchResult(callbacks, selected));
}
/** Called by {@link #handleScrollCaptureRequest} when a result is returned */
private void dispatchScrollCaptureSearchResult(
- @NonNull IScrollCaptureController controller,
+ @NonNull IScrollCaptureCallbacks callbacks,
@Nullable ScrollCaptureTarget selectedTarget) {
// If timeout or no eligible targets found.
@@ -9051,31 +9064,31 @@ public final class ViewRootImpl implements ViewParent,
if (DEBUG_SCROLL_CAPTURE) {
Log.d(TAG, "scrollCaptureSearch returned no targets available.");
}
- controller.onClientUnavailable();
+ callbacks.onUnavailable();
} catch (RemoteException e) {
if (DEBUG_SCROLL_CAPTURE) {
- Log.w(TAG, "Failed to notify controller of scroll capture search result.", e);
+ Log.w(TAG, "Failed to send scroll capture search result.", e);
}
}
return;
}
// Create a client instance and return it to the caller
- mScrollCaptureClient = new ScrollCaptureClient(selectedTarget, controller);
+ mScrollCaptureConnection = new ScrollCaptureConnection(selectedTarget, callbacks);
try {
if (DEBUG_SCROLL_CAPTURE) {
- Log.d(TAG, "scrollCaptureSearch returning client: " + getScrollCaptureClient());
+ Log.d(TAG, "scrollCaptureSearch returning client: " + getScrollCaptureConnection());
}
- controller.onClientConnected(
- mScrollCaptureClient,
+ callbacks.onConnected(
+ mScrollCaptureConnection,
selectedTarget.getScrollBounds(),
selectedTarget.getPositionInWindow());
} catch (RemoteException e) {
if (DEBUG_SCROLL_CAPTURE) {
- Log.w(TAG, "Failed to notify controller of scroll capture search result.", e);
+ Log.w(TAG, "Failed to send scroll capture search result.", e);
}
- mScrollCaptureClient.disconnect();
- mScrollCaptureClient = null;
+ mScrollCaptureConnection.disconnect();
+ mScrollCaptureConnection = null;
}
}
@@ -9373,10 +9386,10 @@ public final class ViewRootImpl implements ViewParent,
}
@Override
- public void requestScrollCapture(IScrollCaptureController controller) {
+ public void requestScrollCapture(IScrollCaptureCallbacks callbacks) {
final ViewRootImpl viewAncestor = mViewAncestor.get();
if (viewAncestor != null) {
- viewAncestor.dispatchScrollCaptureRequest(controller);
+ viewAncestor.dispatchScrollCaptureRequest(callbacks);
}
}
}
diff --git a/core/java/android/view/ViewRootInsetsControllerHost.java b/core/java/android/view/ViewRootInsetsControllerHost.java
index 8f58df466ee3..514fb29029d0 100644
--- a/core/java/android/view/ViewRootInsetsControllerHost.java
+++ b/core/java/android/view/ViewRootInsetsControllerHost.java
@@ -21,6 +21,7 @@ import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_APPEARANCE_CO
import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_BEHAVIOR_CONTROLLED;
import android.annotation.NonNull;
+import android.content.res.CompatibilityInfo;
import android.os.Handler;
import android.os.IBinder;
import android.os.RemoteException;
@@ -251,4 +252,12 @@ public class ViewRootInsetsControllerHost implements InsetsController.Host {
}
return view.getWindowToken();
}
+
+ @Override
+ public CompatibilityInfo.Translator getTranslator() {
+ if (mViewRoot != null) {
+ return mViewRoot.mTranslator;
+ }
+ return null;
+ }
}
diff --git a/core/java/android/view/Window.java b/core/java/android/view/Window.java
index 1dbf37aca689..5331a1b8d538 100644
--- a/core/java/android/view/Window.java
+++ b/core/java/android/view/Window.java
@@ -2560,19 +2560,20 @@ public abstract class Window {
/**
* System request to begin scroll capture.
*
- * @param controller the controller to receive responses
+ * @param callbacks to receive responses
* @hide
*/
- public void requestScrollCapture(IScrollCaptureController controller) {
+ public void requestScrollCapture(IScrollCaptureCallbacks callbacks) {
}
/**
- * Registers a {@link ScrollCaptureCallback} with the root of this window.
+ * Used to provide scroll capture support for an arbitrary window. This registeres the given
+ * callback with the root view of the window.
*
* @param callback the callback to add
* @hide
*/
- public void addScrollCaptureCallback(@NonNull ScrollCaptureCallback callback) {
+ public void registerScrollCaptureCallback(@NonNull ScrollCaptureCallback callback) {
}
/**
@@ -2581,7 +2582,7 @@ public abstract class Window {
* @param callback the callback to remove
* @hide
*/
- public void removeScrollCaptureCallback(@NonNull ScrollCaptureCallback callback) {
+ public void unregisterScrollCaptureCallback(@NonNull ScrollCaptureCallback callback) {
}
/** @hide */
diff --git a/core/java/android/view/WindowInsets.java b/core/java/android/view/WindowInsets.java
index 94c518483429..8b0cf3bb86dc 100644
--- a/core/java/android/view/WindowInsets.java
+++ b/core/java/android/view/WindowInsets.java
@@ -924,6 +924,15 @@ public final class WindowInsets {
Preconditions.checkArgumentNonnegative(right);
Preconditions.checkArgumentNonnegative(bottom);
+ return insetUnchecked(left, top, right, bottom);
+ }
+
+ /**
+ * @see #inset(int, int, int, int)
+ * @hide
+ */
+ @NonNull
+ public WindowInsets insetUnchecked(int left, int top, int right, int bottom) {
return new WindowInsets(
mSystemWindowInsetsConsumed
? null
diff --git a/core/java/android/view/WindowManager.java b/core/java/android/view/WindowManager.java
index e96e98b437a1..9336872f29d8 100644
--- a/core/java/android/view/WindowManager.java
+++ b/core/java/android/view/WindowManager.java
@@ -224,12 +224,6 @@ public interface WindowManager extends ViewManager {
int TRANSIT_ACTIVITY_RELAUNCH = 18;
/**
- * A task is being docked from recents.
- * @hide
- */
- int TRANSIT_DOCK_TASK_FROM_RECENTS = 19;
-
- /**
* Keyguard is going away.
* @hide
*/
@@ -278,13 +272,6 @@ public interface WindowManager extends ViewManager {
int TRANSIT_TASK_CHANGE_WINDOWING_MODE = 27;
/**
- * A display which can only contain one task is being shown because the first activity is
- * started or it's being turned on.
- * @hide
- */
- int TRANSIT_SHOW_SINGLE_TASK_DISPLAY = 28;
-
- /**
* @hide
*/
@IntDef(prefix = { "TRANSIT_" }, value = {
@@ -302,7 +289,6 @@ public interface WindowManager extends ViewManager {
TRANSIT_WALLPAPER_INTRA_CLOSE,
TRANSIT_TASK_OPEN_BEHIND,
TRANSIT_ACTIVITY_RELAUNCH,
- TRANSIT_DOCK_TASK_FROM_RECENTS,
TRANSIT_KEYGUARD_GOING_AWAY,
TRANSIT_KEYGUARD_GOING_AWAY_ON_WALLPAPER,
TRANSIT_KEYGUARD_OCCLUDE,
@@ -310,8 +296,7 @@ public interface WindowManager extends ViewManager {
TRANSIT_TRANSLUCENT_ACTIVITY_OPEN,
TRANSIT_TRANSLUCENT_ACTIVITY_CLOSE,
TRANSIT_CRASHING_ACTIVITY_CLOSE,
- TRANSIT_TASK_CHANGE_WINDOWING_MODE,
- TRANSIT_SHOW_SINGLE_TASK_DISPLAY
+ TRANSIT_TASK_CHANGE_WINDOWING_MODE
})
@Retention(RetentionPolicy.SOURCE)
@interface TransitionType {}
@@ -2939,6 +2924,13 @@ public interface WindowManager extends ViewManager {
public boolean preferMinimalPostProcessing = false;
/**
+ * Indicates that this window wants to have blurred content behind it.
+ *
+ * @hide
+ */
+ public int backgroundBlurRadius = 0;
+
+ /**
* The color mode requested by this window. The target display may
* not be able to honor the request. When the color mode is not set
* to {@link ActivityInfo#COLOR_MODE_DEFAULT}, it might override the
@@ -3262,6 +3254,7 @@ public interface WindowManager extends ViewManager {
out.writeInt(mFitInsetsSides);
out.writeBoolean(mFitInsetsIgnoringVisibility);
out.writeBoolean(preferMinimalPostProcessing);
+ out.writeInt(backgroundBlurRadius);
if (providesInsetsTypes != null) {
out.writeInt(providesInsetsTypes.length);
out.writeIntArray(providesInsetsTypes);
@@ -3329,6 +3322,7 @@ public interface WindowManager extends ViewManager {
mFitInsetsSides = in.readInt();
mFitInsetsIgnoringVisibility = in.readBoolean();
preferMinimalPostProcessing = in.readBoolean();
+ backgroundBlurRadius = in.readInt();
int insetsTypesLength = in.readInt();
if (insetsTypesLength > 0) {
providesInsetsTypes = new int[insetsTypesLength];
@@ -3381,6 +3375,8 @@ public interface WindowManager extends ViewManager {
public static final int INSET_FLAGS_CHANGED = 1 << 27;
/** {@hide} */
public static final int MINIMAL_POST_PROCESSING_PREFERENCE_CHANGED = 1 << 28;
+ /** {@hide} */
+ public static final int BACKGROUND_BLUR_RADIUS_CHANGED = 1 << 29;
// internal buffer to backup/restore parameters under compatibility mode.
private int[] mCompatibilityParamsBackup = null;
@@ -3566,6 +3562,11 @@ public interface WindowManager extends ViewManager {
changes |= MINIMAL_POST_PROCESSING_PREFERENCE_CHANGED;
}
+ if (backgroundBlurRadius != o.backgroundBlurRadius) {
+ backgroundBlurRadius = o.backgroundBlurRadius;
+ changes |= BACKGROUND_BLUR_RADIUS_CHANGED;
+ }
+
// This can't change, it's only set at window creation time.
hideTimeoutMilliseconds = o.hideTimeoutMilliseconds;
@@ -3729,6 +3730,10 @@ public interface WindowManager extends ViewManager {
sb.append(" preferMinimalPostProcessing=");
sb.append(preferMinimalPostProcessing);
}
+ if (backgroundBlurRadius != 0) {
+ sb.append(" backgroundBlurRadius=");
+ sb.append(backgroundBlurRadius);
+ }
sb.append(System.lineSeparator());
sb.append(prefix).append(" fl=").append(
ViewDebug.flagsToString(LayoutParams.class, "flags", flags));
diff --git a/core/java/android/view/WindowManagerImpl.java b/core/java/android/view/WindowManagerImpl.java
index 59e022645544..7dfae002b554 100644
--- a/core/java/android/view/WindowManagerImpl.java
+++ b/core/java/android/view/WindowManagerImpl.java
@@ -262,14 +262,11 @@ public final class WindowManagerImpl implements WindowManager {
private WindowInsets getWindowInsetsFromServer(WindowManager.LayoutParams attrs, Rect bounds) {
try {
- final Rect systemWindowInsets = new Rect();
- final Rect stableInsets = new Rect();
final DisplayCutout.ParcelableWrapper displayCutout =
new DisplayCutout.ParcelableWrapper();
final InsetsState insetsState = new InsetsState();
final boolean alwaysConsumeSystemBars = WindowManagerGlobal.getWindowManagerService()
- .getWindowInsets(attrs, mContext.getDisplayId(), systemWindowInsets,
- stableInsets, displayCutout, insetsState);
+ .getWindowInsets(attrs, mContext.getDisplayId(), displayCutout, insetsState);
final Configuration config = mContext.getResources().getConfiguration();
final boolean isScreenRound = config.isScreenRound();
final int windowingMode = config.windowConfiguration.getWindowingMode();
diff --git a/core/java/android/view/WindowlessWindowManager.java b/core/java/android/view/WindowlessWindowManager.java
index 814787347b75..5e5d14f55240 100644
--- a/core/java/android/view/WindowlessWindowManager.java
+++ b/core/java/android/view/WindowlessWindowManager.java
@@ -131,7 +131,6 @@ public class WindowlessWindowManager implements IWindowSession {
@Override
public int addToDisplay(IWindow window, WindowManager.LayoutParams attrs,
int viewVisibility, int displayId, InsetsState requestedVisibility, Rect outFrame,
- Rect outContentInsets, Rect outStableInsets,
DisplayCutout.ParcelableWrapper outDisplayCutout, InputChannel outInputChannel,
InsetsState outInsetsState, InsetsSourceControl[] outActiveControls) {
final SurfaceControl.Builder b = new SurfaceControl.Builder(mSurfaceSession)
@@ -167,18 +166,16 @@ public class WindowlessWindowManager implements IWindowSession {
@Override
public int addToDisplayAsUser(IWindow window, WindowManager.LayoutParams attrs,
int viewVisibility, int displayId, int userId, InsetsState requestedVisibility,
- Rect outFrame, Rect outContentInsets, Rect outStableInsets,
- DisplayCutout.ParcelableWrapper outDisplayCutout, InputChannel outInputChannel,
- InsetsState outInsetsState, InsetsSourceControl[] outActiveControls) {
+ Rect outFrame, DisplayCutout.ParcelableWrapper outDisplayCutout,
+ InputChannel outInputChannel, InsetsState outInsetsState,
+ InsetsSourceControl[] outActiveControls) {
return addToDisplay(window, attrs, viewVisibility, displayId, requestedVisibility,
- outFrame, outContentInsets, outStableInsets, outDisplayCutout, outInputChannel,
- outInsetsState, outActiveControls);
+ outFrame, outDisplayCutout, outInputChannel, outInsetsState, outActiveControls);
}
@Override
public int addToDisplayWithoutInputChannel(android.view.IWindow window,
android.view.WindowManager.LayoutParams attrs, int viewVisibility, int layerStackId,
- android.graphics.Rect outContentInsets, android.graphics.Rect outStableInsets,
android.view.InsetsState insetsState) {
return 0;
}
diff --git a/core/java/android/view/accessibility/AccessibilityManager.java b/core/java/android/view/accessibility/AccessibilityManager.java
index aed9b89747d0..a9e8d5498a57 100644
--- a/core/java/android/view/accessibility/AccessibilityManager.java
+++ b/core/java/android/view/accessibility/AccessibilityManager.java
@@ -1249,7 +1249,6 @@ public final class AccessibilityManager {
* @hide
*/
@SystemApi
- @TestApi
@RequiresPermission(Manifest.permission.MANAGE_ACCESSIBILITY)
public void performAccessibilityShortcut() {
performAccessibilityShortcut(null);
@@ -1294,7 +1293,6 @@ public final class AccessibilityManager {
* @hide
*/
@SystemApi
- @TestApi
@RequiresPermission(Manifest.permission.MANAGE_ACCESSIBILITY)
public void registerSystemAction(@NonNull RemoteAction action, int actionId) {
final IAccessibilityManager service;
@@ -1322,7 +1320,6 @@ public final class AccessibilityManager {
* @hide
*/
@SystemApi
- @TestApi
@RequiresPermission(Manifest.permission.MANAGE_ACCESSIBILITY)
public void unregisterSystemAction(int actionId) {
final IAccessibilityManager service;
diff --git a/core/java/android/view/autofill/AutofillManager.java b/core/java/android/view/autofill/AutofillManager.java
index 9ba886aba81a..fb66b5298839 100644
--- a/core/java/android/view/autofill/AutofillManager.java
+++ b/core/java/android/view/autofill/AutofillManager.java
@@ -2076,7 +2076,6 @@ public final class AutofillManager {
* @hide
*/
@SystemApi
- @TestApi
public void setAugmentedAutofillWhitelist(@Nullable Set<String> packages,
@Nullable Set<ComponentName> activities) {
if (!hasAutofillFeature()) {
diff --git a/core/java/android/view/autofill/AutofillValue.java b/core/java/android/view/autofill/AutofillValue.java
index be1a2f221587..e92c30fcbc3b 100644
--- a/core/java/android/view/autofill/AutofillValue.java
+++ b/core/java/android/view/autofill/AutofillValue.java
@@ -65,7 +65,7 @@ public final class AutofillValue implements Parcelable {
* @throws IllegalStateException if the value is not a text value
*/
@NonNull public CharSequence getTextValue() {
- Preconditions.checkState(isText(), "value must be a text value, not type=" + mType);
+ Preconditions.checkState(isText(), "value must be a text value, not type=%d", mType);
return (CharSequence) mValue;
}
@@ -86,7 +86,7 @@ public final class AutofillValue implements Parcelable {
* @throws IllegalStateException if the value is not a toggle value
*/
public boolean getToggleValue() {
- Preconditions.checkState(isToggle(), "value must be a toggle value, not type=" + mType);
+ Preconditions.checkState(isToggle(), "value must be a toggle value, not type=%d", mType);
return (Boolean) mValue;
}
@@ -107,7 +107,7 @@ public final class AutofillValue implements Parcelable {
* @throws IllegalStateException if the value is not a list value
*/
public int getListValue() {
- Preconditions.checkState(isList(), "value must be a list value, not type=" + mType);
+ Preconditions.checkState(isList(), "value must be a list value, not type=%d", mType);
return (Integer) mValue;
}
@@ -128,7 +128,7 @@ public final class AutofillValue implements Parcelable {
* @throws IllegalStateException if the value is not a date value
*/
public long getDateValue() {
- Preconditions.checkState(isDate(), "value must be a date value, not type=" + mType);
+ Preconditions.checkState(isDate(), "value must be a date value, not type=%d", mType);
return (Long) mValue;
}
@@ -150,7 +150,7 @@ public final class AutofillValue implements Parcelable {
*/
public @NonNull ClipData getRichContentValue() {
Preconditions.checkState(isRichContent(),
- "value must be a rich content value, not type=" + mType);
+ "value must be a rich content value, not type=%d", mType);
return (ClipData) mValue;
}
diff --git a/core/java/android/view/contentcapture/ContentCaptureContext.java b/core/java/android/view/contentcapture/ContentCaptureContext.java
index b84cb88ccd84..9bf3626fe868 100644
--- a/core/java/android/view/contentcapture/ContentCaptureContext.java
+++ b/core/java/android/view/contentcapture/ContentCaptureContext.java
@@ -21,7 +21,6 @@ import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.SystemApi;
-import android.annotation.TestApi;
import android.app.TaskInfo;
import android.content.ComponentName;
import android.content.Context;
@@ -58,7 +57,6 @@ public final class ContentCaptureContext implements Parcelable {
* @hide
*/
@SystemApi
- @TestApi
public static final int FLAG_DISABLED_BY_APP = 0x1;
/**
@@ -69,7 +67,6 @@ public final class ContentCaptureContext implements Parcelable {
* @hide
*/
@SystemApi
- @TestApi
public static final int FLAG_DISABLED_BY_FLAG_SECURE = 0x2;
/**
@@ -79,7 +76,6 @@ public final class ContentCaptureContext implements Parcelable {
* @hide
*/
@SystemApi
- @TestApi
public static final int FLAG_RECONNECTED = 0x4;
/** @hide */
@@ -173,7 +169,6 @@ public final class ContentCaptureContext implements Parcelable {
* @hide
*/
@SystemApi
- @TestApi
public int getTaskId() {
return mTaskId;
}
@@ -184,7 +179,6 @@ public final class ContentCaptureContext implements Parcelable {
* @hide
*/
@SystemApi
- @TestApi
public @Nullable ComponentName getActivityComponent() {
return mComponentName;
}
@@ -197,7 +191,6 @@ public final class ContentCaptureContext implements Parcelable {
* @hide
*/
@SystemApi
- @TestApi
public @Nullable ContentCaptureSessionId getParentSessionId() {
return mParentSessionId == NO_SESSION_ID ? null
: new ContentCaptureSessionId(mParentSessionId);
@@ -215,7 +208,6 @@ public final class ContentCaptureContext implements Parcelable {
* @hide
*/
@SystemApi
- @TestApi
public int getDisplayId() {
return mDisplayId;
}
@@ -229,7 +221,6 @@ public final class ContentCaptureContext implements Parcelable {
* @hide
*/
@SystemApi
- @TestApi
public @ContextCreationFlags int getFlags() {
return mFlags;
}
diff --git a/core/java/android/view/contentcapture/ContentCaptureEvent.java b/core/java/android/view/contentcapture/ContentCaptureEvent.java
index f49b1beee8ad..2b12230510bf 100644
--- a/core/java/android/view/contentcapture/ContentCaptureEvent.java
+++ b/core/java/android/view/contentcapture/ContentCaptureEvent.java
@@ -22,7 +22,6 @@ import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.SystemApi;
-import android.annotation.TestApi;
import android.graphics.Insets;
import android.os.Parcel;
import android.os.Parcelable;
@@ -39,7 +38,6 @@ import java.util.List;
/** @hide */
@SystemApi
-@TestApi
public final class ContentCaptureEvent implements Parcelable {
private static final String TAG = ContentCaptureEvent.class.getSimpleName();
diff --git a/core/java/android/view/contentcapture/ContentCaptureManager.java b/core/java/android/view/contentcapture/ContentCaptureManager.java
index 029552d4902e..10f6c610d5d3 100644
--- a/core/java/android/view/contentcapture/ContentCaptureManager.java
+++ b/core/java/android/view/contentcapture/ContentCaptureManager.java
@@ -644,7 +644,6 @@ public final class ContentCaptureManager {
* @hide
*/
@SystemApi
- @TestApi
public boolean isContentCaptureFeatureEnabled() {
final SyncResultReceiver resultReceiver = syncRun(
(r) -> mService.isContentCaptureFeatureEnabled(r));
diff --git a/core/java/android/view/contentcapture/ViewNode.java b/core/java/android/view/contentcapture/ViewNode.java
index e035c620d1fd..e731d4b76fb9 100644
--- a/core/java/android/view/contentcapture/ViewNode.java
+++ b/core/java/android/view/contentcapture/ViewNode.java
@@ -42,7 +42,6 @@ import com.android.internal.util.Preconditions;
// instead
/** @hide */
@SystemApi
-@TestApi
public final class ViewNode extends AssistStructure.ViewNode {
private static final String TAG = ViewNode.class.getSimpleName();
diff --git a/core/java/android/widget/Editor.java b/core/java/android/widget/Editor.java
index eaa738d59577..f2955ac554fc 100644
--- a/core/java/android/widget/Editor.java
+++ b/core/java/android/widget/Editor.java
@@ -206,6 +206,10 @@ public class Editor {
int TEXT_LINK = 2;
}
+ // Default content insertion handler.
+ private final TextViewOnReceiveContentCallback mDefaultOnReceiveContentCallback =
+ new TextViewOnReceiveContentCallback();
+
// Each Editor manages its own undo stack.
private final UndoManager mUndoManager = new UndoManager();
private UndoOwner mUndoOwner = mUndoManager.getOwner(UNDO_OWNER_TAG, this);
@@ -584,6 +588,11 @@ public class Editor {
mUndoOwner = mUndoManager.getOwner(UNDO_OWNER_TAG, this);
}
+ @VisibleForTesting
+ public @NonNull TextViewOnReceiveContentCallback getDefaultOnReceiveContentCallback() {
+ return mDefaultOnReceiveContentCallback;
+ }
+
/**
* Forgets all undo and redo operations for this Editor.
*/
@@ -709,6 +718,8 @@ public class Editor {
hideCursorAndSpanControllers();
stopTextActionModeWithPreservingSelection();
+
+ mDefaultOnReceiveContentCallback.clearInputConnectionInfo();
}
private void discardTextDisplayLists() {
diff --git a/core/java/android/widget/TextView.java b/core/java/android/widget/TextView.java
index 52a3f4145e7e..7bb2b7e92a00 100644
--- a/core/java/android/widget/TextView.java
+++ b/core/java/android/widget/TextView.java
@@ -80,6 +80,7 @@ import android.os.AsyncTask;
import android.os.Build;
import android.os.Build.VERSION_CODES;
import android.os.Bundle;
+import android.os.Handler;
import android.os.LocaleList;
import android.os.Parcel;
import android.os.Parcelable;
@@ -890,13 +891,6 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
@UnsupportedAppUsage
private Editor mEditor;
- /**
- * The default content insertion callback used by {@link TextView}. See
- * {@link #setOnReceiveContentCallback} for more info.
- */
- private static final TextViewOnReceiveContentCallback DEFAULT_ON_RECEIVE_CONTENT_CALLBACK =
- new TextViewOnReceiveContentCallback();
-
private static final int DEVICE_PROVISIONED_UNKNOWN = 0;
private static final int DEVICE_PROVISIONED_NO = 1;
private static final int DEVICE_PROVISIONED_YES = 2;
@@ -13723,6 +13717,23 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
}
}
+ /** @hide */
+ @Override
+ public void onInputConnectionOpenedInternal(@NonNull InputConnection ic,
+ @NonNull EditorInfo editorInfo, @Nullable Handler handler) {
+ if (mEditor != null) {
+ mEditor.getDefaultOnReceiveContentCallback().setInputConnectionInfo(ic, editorInfo);
+ }
+ }
+
+ /** @hide */
+ @Override
+ public void onInputConnectionClosedInternal() {
+ if (mEditor != null) {
+ mEditor.getDefaultOnReceiveContentCallback().clearInputConnectionInfo();
+ }
+ }
+
/**
* Returns the callback used for handling insertion of content into this view. See
* {@link #setOnReceiveContentCallback} for more info.
@@ -13773,8 +13784,8 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
ClipDescription description = payload.getClip().getDescription();
if (receiver != null && receiver.supports(this, description)) {
receiver.onReceiveContent(this, payload);
- } else {
- DEFAULT_ON_RECEIVE_CONTENT_CALLBACK.onReceiveContent(this, payload);
+ } else if (mEditor != null) {
+ mEditor.getDefaultOnReceiveContentCallback().onReceiveContent(this, payload);
}
}
diff --git a/core/java/android/widget/TextViewOnReceiveContentCallback.java b/core/java/android/widget/TextViewOnReceiveContentCallback.java
index 35618cb3d2a5..d7c95b7eae86 100644
--- a/core/java/android/widget/TextViewOnReceiveContentCallback.java
+++ b/core/java/android/widget/TextViewOnReceiveContentCallback.java
@@ -16,24 +16,44 @@
package android.widget;
+import static android.content.ContentResolver.SCHEME_CONTENT;
import static android.view.OnReceiveContentCallback.Payload.FLAG_CONVERT_TO_PLAIN_TEXT;
import static android.view.OnReceiveContentCallback.Payload.SOURCE_AUTOFILL;
import static android.view.OnReceiveContentCallback.Payload.SOURCE_DRAG_AND_DROP;
+import static java.util.Collections.singleton;
+
import android.annotation.NonNull;
+import android.annotation.Nullable;
import android.annotation.SuppressLint;
+import android.compat.Compatibility;
+import android.compat.annotation.ChangeId;
+import android.compat.annotation.EnabledAfter;
import android.content.ClipData;
+import android.content.ClipDescription;
import android.content.Context;
+import android.net.Uri;
+import android.os.Build;
+import android.os.Bundle;
import android.text.Editable;
import android.text.Selection;
import android.text.SpannableStringBuilder;
import android.text.Spanned;
+import android.util.ArraySet;
import android.util.Log;
import android.view.OnReceiveContentCallback;
import android.view.OnReceiveContentCallback.Payload.Flags;
import android.view.OnReceiveContentCallback.Payload.Source;
+import android.view.View;
+import android.view.inputmethod.EditorInfo;
+import android.view.inputmethod.InputConnection;
+import android.view.inputmethod.InputContentInfo;
+
+import com.android.internal.annotations.VisibleForTesting;
-import java.util.Collections;
+import java.lang.ref.WeakReference;
+import java.util.ArrayList;
+import java.util.Arrays;
import java.util.Set;
/**
@@ -46,19 +66,26 @@ import java.util.Set;
public class TextViewOnReceiveContentCallback implements OnReceiveContentCallback<TextView> {
private static final String LOG_TAG = "OnReceiveContent";
- private static final Set<String> MIME_TYPES_ALL_TEXT = Collections.singleton("text/*");
+ private static final String MIME_TYPE_ALL_TEXT = "text/*";
+ private static final Set<String> MIME_TYPES_ALL_TEXT = singleton(MIME_TYPE_ALL_TEXT);
+
+ @Nullable private InputConnectionInfo mInputConnectionInfo;
+ @Nullable private ArraySet<String> mCachedSupportedMimeTypes;
@SuppressLint("CallbackMethodName")
@NonNull
@Override
public Set<String> getSupportedMimeTypes(@NonNull TextView view) {
- return MIME_TYPES_ALL_TEXT;
+ if (!isUsageOfImeCommitContentEnabled(view)) {
+ return MIME_TYPES_ALL_TEXT;
+ }
+ return getSupportedMimeTypesAugmentedWithImeCommitContentMimeTypes();
}
@Override
public boolean onReceiveContent(@NonNull TextView view, @NonNull Payload payload) {
if (Log.isLoggable(LOG_TAG, Log.DEBUG)) {
- Log.d(LOG_TAG, "onReceive:" + payload);
+ Log.d(LOG_TAG, "onReceive: " + payload);
}
ClipData clip = payload.getClip();
@Source int source = payload.getSource();
@@ -109,13 +136,22 @@ public class TextViewOnReceiveContentCallback implements OnReceiveContentCallbac
editable.replace(start, end, replacement);
}
- private static boolean onReceiveForAutofill(@NonNull TextView textView, @NonNull ClipData clip,
+ private boolean onReceiveForAutofill(@NonNull TextView view, @NonNull ClipData clip,
@Flags int flags) {
- final CharSequence text = coerceToText(clip, textView.getContext(), flags);
+ if (isUsageOfImeCommitContentEnabled(view)) {
+ clip = handleNonTextViaImeCommitContent(clip);
+ if (clip == null) {
+ if (Log.isLoggable(LOG_TAG, Log.VERBOSE)) {
+ Log.v(LOG_TAG, "onReceive: Handled via IME");
+ }
+ return true;
+ }
+ }
+ final CharSequence text = coerceToText(clip, view.getContext(), flags);
// First autofill it...
- textView.setText(text);
+ view.setText(text);
// ...then move cursor to the end.
- final Editable editable = (Editable) textView.getText();
+ final Editable editable = (Editable) view.getText();
Selection.setSelection(editable, editable.length());
return true;
}
@@ -146,4 +182,250 @@ public class TextViewOnReceiveContentCallback implements OnReceiveContentCallbac
}
return ssb;
}
+
+ /**
+ * On Android S and above, the platform can provide non-text suggestions (e.g. images) via the
+ * augmented autofill framework (see
+ * <a href="/guide/topics/text/autofill-services">autofill services</a>). In order for an app to
+ * be able to handle these suggestions, it must normally implement the
+ * {@link android.view.OnReceiveContentCallback} API. To make the adoption of this smoother for
+ * apps that have previously implemented the
+ * {@link android.view.inputmethod.InputConnection#commitContent(InputContentInfo, int, Bundle)}
+ * API, we reuse that API as a fallback if {@link android.view.OnReceiveContentCallback} is not
+ * yet implemented by the app. This fallback is only enabled on Android S. This change ID
+ * disables the fallback, such that apps targeting Android T and above must implement the
+ * {@link android.view.OnReceiveContentCallback} API in order to accept non-text suggestions.
+ */
+ @ChangeId
+ @EnabledAfter(targetSdkVersion = Build.VERSION_CODES.S) // Enabled on Android T and higher
+ private static final long AUTOFILL_NON_TEXT_REQUIRES_ON_RECEIVE_CONTENT_CALLBACK = 163400105L;
+
+ /**
+ * Returns true if we can use the IME {@link InputConnection#commitContent} API in order handle
+ * non-text content.
+ */
+ private static boolean isUsageOfImeCommitContentEnabled(@NonNull View view) {
+ if (view.getOnReceiveContentCallback() != null) {
+ if (Log.isLoggable(LOG_TAG, Log.VERBOSE)) {
+ Log.v(LOG_TAG, "Fallback to commitContent disabled (custom callback is set)");
+ }
+ return false;
+ }
+ if (Compatibility.isChangeEnabled(AUTOFILL_NON_TEXT_REQUIRES_ON_RECEIVE_CONTENT_CALLBACK)) {
+ if (Log.isLoggable(LOG_TAG, Log.VERBOSE)) {
+ Log.v(LOG_TAG, "Fallback to commitContent disabled (target SDK is above S)");
+ }
+ return false;
+ }
+ return true;
+ }
+
+ private static final class InputConnectionInfo {
+ @NonNull private final WeakReference<InputConnection> mInputConnection;
+ @NonNull private final String[] mEditorInfoContentMimeTypes;
+
+ private InputConnectionInfo(@NonNull InputConnection inputConnection,
+ @NonNull String[] editorInfoContentMimeTypes) {
+ mInputConnection = new WeakReference<>(inputConnection);
+ mEditorInfoContentMimeTypes = editorInfoContentMimeTypes;
+ }
+
+ @Override
+ public String toString() {
+ return "InputConnectionInfo{"
+ + "mimeTypes=" + Arrays.toString(mEditorInfoContentMimeTypes)
+ + ", ic=" + mInputConnection
+ + '}';
+ }
+ }
+
+ /**
+ * Invoked by the platform when an {@link InputConnection} is successfully created for the view
+ * that owns this callback instance.
+ */
+ void setInputConnectionInfo(@NonNull InputConnection ic, @NonNull EditorInfo editorInfo) {
+ if (Log.isLoggable(LOG_TAG, Log.VERBOSE)) {
+ Log.v(LOG_TAG, "setInputConnectionInfo: "
+ + Arrays.toString(editorInfo.contentMimeTypes));
+ }
+ String[] contentMimeTypes = editorInfo.contentMimeTypes;
+ if (contentMimeTypes == null || contentMimeTypes.length == 0) {
+ mInputConnectionInfo = null;
+ } else {
+ mInputConnectionInfo = new InputConnectionInfo(ic, contentMimeTypes);
+ }
+ }
+
+ /**
+ * Invoked by the platform when an {@link InputConnection} is closed for the view that owns this
+ * callback instance.
+ */
+ void clearInputConnectionInfo() {
+ if (Log.isLoggable(LOG_TAG, Log.VERBOSE)) {
+ Log.v(LOG_TAG, "clearInputConnectionInfo: " + mInputConnectionInfo);
+ }
+ mInputConnectionInfo = null;
+ }
+
+ private Set<String> getSupportedMimeTypesAugmentedWithImeCommitContentMimeTypes() {
+ InputConnectionInfo icInfo = mInputConnectionInfo;
+ if (icInfo == null) {
+ if (Log.isLoggable(LOG_TAG, Log.VERBOSE)) {
+ Log.v(LOG_TAG, "getSupportedMimeTypes: No usable EditorInfo/InputConnection");
+ }
+ return MIME_TYPES_ALL_TEXT;
+ }
+ String[] editorInfoContentMimeTypes = icInfo.mEditorInfoContentMimeTypes;
+ if (Log.isLoggable(LOG_TAG, Log.VERBOSE)) {
+ Log.v(LOG_TAG, "getSupportedMimeTypes: Augmenting with EditorInfo.contentMimeTypes: "
+ + Arrays.toString(editorInfoContentMimeTypes));
+ }
+ ArraySet<String> supportedMimeTypes = mCachedSupportedMimeTypes;
+ if (canReuse(supportedMimeTypes, editorInfoContentMimeTypes)) {
+ return supportedMimeTypes;
+ }
+ supportedMimeTypes = new ArraySet<>(editorInfoContentMimeTypes);
+ supportedMimeTypes.add(MIME_TYPE_ALL_TEXT);
+ mCachedSupportedMimeTypes = supportedMimeTypes;
+ return supportedMimeTypes;
+ }
+
+ /**
+ * We want to avoid creating a new set on every invocation of {@link #getSupportedMimeTypes}.
+ * This method will check if the cached set of MIME types matches the data in the given array
+ * from {@link EditorInfo} or if a new set should be created. The custom logic is needed for
+ * comparing the data because the set contains the additional "text/*" MIME type.
+ *
+ * @param cachedMimeTypes Previously cached set of MIME types.
+ * @param newEditorInfoMimeTypes MIME types from {@link EditorInfo}.
+ *
+ * @return Returns true if the data in the given cached set matches the data in the array.
+ *
+ * @hide
+ */
+ @VisibleForTesting
+ public static boolean canReuse(@Nullable ArraySet<String> cachedMimeTypes,
+ @NonNull String[] newEditorInfoMimeTypes) {
+ if (cachedMimeTypes == null) {
+ return false;
+ }
+ if (newEditorInfoMimeTypes.length != cachedMimeTypes.size()
+ && newEditorInfoMimeTypes.length != (cachedMimeTypes.size() - 1)) {
+ return false;
+ }
+ final boolean ignoreAllTextMimeType =
+ newEditorInfoMimeTypes.length == (cachedMimeTypes.size() - 1);
+ for (String mimeType : cachedMimeTypes) {
+ if (ignoreAllTextMimeType && mimeType.equals(MIME_TYPE_ALL_TEXT)) {
+ continue;
+ }
+ boolean present = false;
+ for (String editorInfoContentMimeType : newEditorInfoMimeTypes) {
+ if (editorInfoContentMimeType.equals(mimeType)) {
+ present = true;
+ break;
+ }
+ }
+ if (!present) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ /**
+ * Tries to insert the content in the clip into the app via the image keyboard API. If all the
+ * items in the clip are successfully inserted, returns null. If one or more of the items in the
+ * clip cannot be inserted, returns a non-null clip that contains the items that were not
+ * inserted.
+ */
+ @Nullable
+ private ClipData handleNonTextViaImeCommitContent(@NonNull ClipData clip) {
+ ClipDescription description = clip.getDescription();
+ if (!containsUri(clip) || containsOnlyText(clip)) {
+ if (Log.isLoggable(LOG_TAG, Log.VERBOSE)) {
+ Log.v(LOG_TAG, "onReceive: Clip doesn't contain any non-text URIs: "
+ + description);
+ }
+ return clip;
+ }
+
+ InputConnectionInfo icInfo = mInputConnectionInfo;
+ InputConnection inputConnection = (icInfo != null) ? icInfo.mInputConnection.get() : null;
+ if (inputConnection == null) {
+ if (Log.isLoggable(LOG_TAG, Log.DEBUG)) {
+ Log.d(LOG_TAG, "onReceive: No usable EditorInfo/InputConnection");
+ }
+ return clip;
+ }
+ String[] editorInfoContentMimeTypes = icInfo.mEditorInfoContentMimeTypes;
+ if (!isClipMimeTypeSupported(editorInfoContentMimeTypes, clip.getDescription())) {
+ if (Log.isLoggable(LOG_TAG, Log.DEBUG)) {
+ Log.d(LOG_TAG,
+ "onReceive: MIME type is not supported by the app's commitContent impl");
+ }
+ return clip;
+ }
+
+ if (Log.isLoggable(LOG_TAG, Log.VERBOSE)) {
+ Log.v(LOG_TAG, "onReceive: Trying to insert via IME: " + description);
+ }
+ ArrayList<ClipData.Item> remainingItems = new ArrayList<>(0);
+ for (int i = 0; i < clip.getItemCount(); i++) {
+ ClipData.Item item = clip.getItemAt(i);
+ Uri uri = item.getUri();
+ if (uri == null || !SCHEME_CONTENT.equals(uri.getScheme())) {
+ if (Log.isLoggable(LOG_TAG, Log.VERBOSE)) {
+ Log.v(LOG_TAG, "onReceive: No content URI in item: uri=" + uri);
+ }
+ remainingItems.add(item);
+ continue;
+ }
+ if (Log.isLoggable(LOG_TAG, Log.VERBOSE)) {
+ Log.v(LOG_TAG, "onReceive: Calling commitContent: uri=" + uri);
+ }
+ InputContentInfo contentInfo = new InputContentInfo(uri, description);
+ if (!inputConnection.commitContent(contentInfo, 0, null)) {
+ if (Log.isLoggable(LOG_TAG, Log.VERBOSE)) {
+ Log.v(LOG_TAG, "onReceive: Call to commitContent returned false: uri=" + uri);
+ }
+ remainingItems.add(item);
+ }
+ }
+ if (remainingItems.isEmpty()) {
+ return null;
+ }
+ return new ClipData(description, remainingItems);
+ }
+
+ private static boolean isClipMimeTypeSupported(@NonNull String[] supportedMimeTypes,
+ @NonNull ClipDescription description) {
+ for (String imeSupportedMimeType : supportedMimeTypes) {
+ if (description.hasMimeType(imeSupportedMimeType)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ private static boolean containsUri(@NonNull ClipData clip) {
+ for (int i = 0; i < clip.getItemCount(); i++) {
+ ClipData.Item item = clip.getItemAt(i);
+ if (item.getUri() != null) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ private static boolean containsOnlyText(@NonNull ClipData clip) {
+ ClipDescription description = clip.getDescription();
+ for (int i = 0; i < description.getMimeTypeCount(); i++) {
+ String mimeType = description.getMimeType(i);
+ if (!mimeType.startsWith("text/")) {
+ return false;
+ }
+ }
+ return true;
+ }
}
diff --git a/core/java/android/window/ClientWindowFrames.java b/core/java/android/window/ClientWindowFrames.java
index 0523e64f3e7a..5d7025b57f91 100644
--- a/core/java/android/window/ClientWindowFrames.java
+++ b/core/java/android/window/ClientWindowFrames.java
@@ -42,19 +42,11 @@ public class ClientWindowFrames implements Parcelable {
/** The area cut from the display. */
public final @NonNull DisplayCutout.ParcelableWrapper displayCutout;
- // TODO(b/149813814): Remove legacy insets.
- public final Rect contentInsets;
- public final Rect visibleInsets;
- public final Rect stableInsets;
-
public ClientWindowFrames() {
frame = new Rect();
displayFrame = new Rect();
backdropFrame = new Rect();
displayCutout = new DisplayCutout.ParcelableWrapper();
- contentInsets = new Rect();
- visibleInsets = new Rect();
- stableInsets = new Rect();
}
public ClientWindowFrames(ClientWindowFrames other) {
@@ -62,9 +54,6 @@ public class ClientWindowFrames implements Parcelable {
displayFrame = new Rect(other.displayFrame);
backdropFrame = new Rect(other.backdropFrame);
displayCutout = new DisplayCutout.ParcelableWrapper(other.displayCutout.get());
- contentInsets = new Rect(other.contentInsets);
- visibleInsets = new Rect(other.visibleInsets);
- stableInsets = new Rect(other.stableInsets);
}
private ClientWindowFrames(Parcel in) {
@@ -72,9 +61,6 @@ public class ClientWindowFrames implements Parcelable {
displayFrame = Rect.CREATOR.createFromParcel(in);
backdropFrame = Rect.CREATOR.createFromParcel(in);
displayCutout = DisplayCutout.ParcelableWrapper.CREATOR.createFromParcel(in);
- contentInsets = Rect.CREATOR.createFromParcel(in);
- visibleInsets = Rect.CREATOR.createFromParcel(in);
- stableInsets = Rect.CREATOR.createFromParcel(in);
}
/** Needed for AIDL out parameters. */
@@ -83,9 +69,6 @@ public class ClientWindowFrames implements Parcelable {
displayFrame.set(Rect.CREATOR.createFromParcel(in));
backdropFrame.set(Rect.CREATOR.createFromParcel(in));
displayCutout.set(DisplayCutout.ParcelableWrapper.CREATOR.createFromParcel(in));
- contentInsets.set(Rect.CREATOR.createFromParcel(in));
- visibleInsets.set(Rect.CREATOR.createFromParcel(in));
- stableInsets.set(Rect.CREATOR.createFromParcel(in));
}
@Override
@@ -94,9 +77,6 @@ public class ClientWindowFrames implements Parcelable {
displayFrame.writeToParcel(dest, flags);
backdropFrame.writeToParcel(dest, flags);
displayCutout.writeToParcel(dest, flags);
- contentInsets.writeToParcel(dest, flags);
- visibleInsets.writeToParcel(dest, flags);
- stableInsets.writeToParcel(dest, flags);
}
@Override
diff --git a/core/java/android/window/ITaskOrganizerController.aidl b/core/java/android/window/ITaskOrganizerController.aidl
index 3a84c1f98ce6..b5a11b1a8136 100644
--- a/core/java/android/window/ITaskOrganizerController.aidl
+++ b/core/java/android/window/ITaskOrganizerController.aidl
@@ -39,8 +39,12 @@ interface ITaskOrganizerController {
*/
void unregisterTaskOrganizer(ITaskOrganizer organizer);
- /** Creates a persistent root task in WM for a particular windowing-mode. */
- ActivityManager.RunningTaskInfo createRootTask(int displayId, int windowingMode);
+ /**
+ * Creates a persistent root task in WM for a particular windowing-mode.
+ * {@link TaskOrganizer#onTaskAppeared} won't be called since we are returning
+ * {@link TaskAppearedInfo} here.
+ */
+ TaskAppearedInfo createRootTask(int displayId, int windowingMode);
/** Deletes a persistent root task in WM */
boolean deleteRootTask(in WindowContainerToken task);
diff --git a/core/java/android/window/TaskOrganizer.java b/core/java/android/window/TaskOrganizer.java
index 909bb47bf1a5..5c86e1c124f7 100644
--- a/core/java/android/window/TaskOrganizer.java
+++ b/core/java/android/window/TaskOrganizer.java
@@ -99,7 +99,7 @@ public class TaskOrganizer extends WindowOrganizer {
/** Creates a persistent root task in WM for a particular windowing-mode. */
@RequiresPermission(android.Manifest.permission.MANAGE_ACTIVITY_STACKS)
@Nullable
- public ActivityManager.RunningTaskInfo createRootTask(int displayId, int windowingMode) {
+ public TaskAppearedInfo createRootTask(int displayId, int windowingMode) {
try {
return mTaskOrganizerController.createRootTask(displayId, windowingMode);
} catch (RemoteException e) {
diff --git a/core/java/android/window/VirtualDisplayTaskEmbedder.java b/core/java/android/window/VirtualDisplayTaskEmbedder.java
index db27d6255de7..be5d55af5e8a 100644
--- a/core/java/android/window/VirtualDisplayTaskEmbedder.java
+++ b/core/java/android/window/VirtualDisplayTaskEmbedder.java
@@ -63,12 +63,10 @@ public class VirtualDisplayTaskEmbedder extends TaskEmbedder {
// For Virtual Displays
private int mDisplayDensityDpi;
- private final boolean mSingleTaskInstance;
private final boolean mUsePublicVirtualDisplay;
private final boolean mUseTrustedDisplay;
private VirtualDisplay mVirtualDisplay;
private Insets mForwardedInsets;
- private DisplayMetrics mTmpDisplayMetrics;
private TaskStackListener mTaskStackListener;
/**
@@ -76,14 +74,10 @@ public class VirtualDisplayTaskEmbedder extends TaskEmbedder {
*
* @param context the context
* @param host the host for this embedded task
- * @param singleTaskInstance whether to apply a single-task constraint to this container,
- * only applicable if virtual displays are used
*/
public VirtualDisplayTaskEmbedder(Context context, VirtualDisplayTaskEmbedder.Host host,
- boolean singleTaskInstance, boolean usePublicVirtualDisplay,
- boolean useTrustedDisplay) {
+ boolean usePublicVirtualDisplay, boolean useTrustedDisplay) {
super(context, host);
- mSingleTaskInstance = singleTaskInstance;
mUsePublicVirtualDisplay = usePublicVirtualDisplay;
mUseTrustedDisplay = useTrustedDisplay;
}
@@ -128,10 +122,6 @@ public class VirtualDisplayTaskEmbedder extends TaskEmbedder {
WindowManagerGlobal.getWindowSession().reparentDisplayContent(
mHost.getWindow(), mSurfaceControl, displayId);
wm.dontOverrideDisplayInfo(displayId);
- if (mSingleTaskInstance) {
- mContext.getSystemService(ActivityTaskManager.class)
- .setDisplayToSingleTaskInstance(displayId);
- }
setForwardedInsets(mForwardedInsets);
mTaskStackListener = new TaskStackListenerImpl();
diff --git a/core/java/com/android/internal/BrightnessSynchronizer.java b/core/java/com/android/internal/BrightnessSynchronizer.java
index 6b8cf6361e91..c98477e8c343 100644
--- a/core/java/com/android/internal/BrightnessSynchronizer.java
+++ b/core/java/com/android/internal/BrightnessSynchronizer.java
@@ -246,10 +246,12 @@ public class BrightnessSynchronizer {
}
if (BRIGHTNESS_URI.equals(uri)) {
int currentBrightness = getScreenBrightnessInt(mContext);
+ mHandler.removeMessages(MSG_UPDATE_FLOAT);
mHandler.obtainMessage(MSG_UPDATE_FLOAT, currentBrightness, 0).sendToTarget();
} else if (BRIGHTNESS_FLOAT_URI.equals(uri)) {
float currentFloat = getScreenBrightnessFloat(mContext);
int toSend = Float.floatToIntBits(currentFloat);
+ mHandler.removeMessages(MSG_UPDATE_INT);
mHandler.obtainMessage(MSG_UPDATE_INT, toSend, 0).sendToTarget();
}
}
diff --git a/core/java/com/android/internal/compat/CompatibilityChangeInfo.java b/core/java/com/android/internal/compat/CompatibilityChangeInfo.java
index 9ba025988126..670ca9f6091e 100644
--- a/core/java/com/android/internal/compat/CompatibilityChangeInfo.java
+++ b/core/java/com/android/internal/compat/CompatibilityChangeInfo.java
@@ -28,7 +28,7 @@ import android.os.Parcelable;
public class CompatibilityChangeInfo implements Parcelable {
private final long mChangeId;
private final @Nullable String mName;
- private final int mEnableAfterTargetSdk;
+ private final int mEnableSinceTargetSdk;
private final boolean mDisabled;
private final boolean mLoggingOnly;
private final @Nullable String mDescription;
@@ -42,8 +42,8 @@ public class CompatibilityChangeInfo implements Parcelable {
return mName;
}
- public int getEnableAfterTargetSdk() {
- return mEnableAfterTargetSdk;
+ public int getEnableSinceTargetSdk() {
+ return mEnableSinceTargetSdk;
}
public boolean getDisabled() {
@@ -59,20 +59,37 @@ public class CompatibilityChangeInfo implements Parcelable {
}
public CompatibilityChangeInfo(
- Long changeId, String name, int enableAfterTargetSdk, boolean disabled,
- boolean loggingOnly, String description) {
+ Long changeId, String name, int enableAfterTargetSdk, int enableSinceTargetSdk,
+ boolean disabled, boolean loggingOnly, String description) {
this.mChangeId = changeId;
this.mName = name;
- this.mEnableAfterTargetSdk = enableAfterTargetSdk;
+ if (enableAfterTargetSdk > 0) {
+ // Need to maintain support for @EnabledAfter(X), but make it equivalent to
+ // @EnabledSince(X+1)
+ this.mEnableSinceTargetSdk = enableAfterTargetSdk + 1;
+ } else if (enableSinceTargetSdk > 0) {
+ this.mEnableSinceTargetSdk = enableSinceTargetSdk;
+ } else {
+ this.mEnableSinceTargetSdk = -1;
+ }
this.mDisabled = disabled;
this.mLoggingOnly = loggingOnly;
this.mDescription = description;
}
+ public CompatibilityChangeInfo(CompatibilityChangeInfo other) {
+ this.mChangeId = other.mChangeId;
+ this.mName = other.mName;
+ this.mEnableSinceTargetSdk = other.mEnableSinceTargetSdk;
+ this.mDisabled = other.mDisabled;
+ this.mLoggingOnly = other.mLoggingOnly;
+ this.mDescription = other.mDescription;
+ }
+
private CompatibilityChangeInfo(Parcel in) {
mChangeId = in.readLong();
mName = in.readString();
- mEnableAfterTargetSdk = in.readInt();
+ mEnableSinceTargetSdk = in.readInt();
mDisabled = in.readBoolean();
mLoggingOnly = in.readBoolean();
mDescription = in.readString();
@@ -87,7 +104,7 @@ public class CompatibilityChangeInfo implements Parcelable {
public void writeToParcel(Parcel dest, int flags) {
dest.writeLong(mChangeId);
dest.writeString(mName);
- dest.writeInt(mEnableAfterTargetSdk);
+ dest.writeInt(mEnableSinceTargetSdk);
dest.writeBoolean(mDisabled);
dest.writeBoolean(mLoggingOnly);
dest.writeString(mDescription);
@@ -100,8 +117,8 @@ public class CompatibilityChangeInfo implements Parcelable {
if (getName() != null) {
sb.append("; name=").append(getName());
}
- if (getEnableAfterTargetSdk() != -1) {
- sb.append("; enableAfterTargetSdk=").append(getEnableAfterTargetSdk());
+ if (getEnableSinceTargetSdk() != -1) {
+ sb.append("; enableSinceTargetSdk=").append(getEnableSinceTargetSdk());
}
if (getDisabled()) {
sb.append("; disabled");
@@ -123,7 +140,7 @@ public class CompatibilityChangeInfo implements Parcelable {
CompatibilityChangeInfo that = (CompatibilityChangeInfo) o;
return this.mChangeId == that.mChangeId
&& this.mName.equals(that.mName)
- && this.mEnableAfterTargetSdk == that.mEnableAfterTargetSdk
+ && this.mEnableSinceTargetSdk == that.mEnableSinceTargetSdk
&& this.mDisabled == that.mDisabled
&& this.mLoggingOnly == that.mLoggingOnly
&& this.mDescription.equals(that.mDescription);
diff --git a/core/java/com/android/internal/compat/IPlatformCompat.aidl b/core/java/com/android/internal/compat/IPlatformCompat.aidl
index 6408def7eeac..cc266d60465e 100644
--- a/core/java/com/android/internal/compat/IPlatformCompat.aidl
+++ b/core/java/com/android/internal/compat/IPlatformCompat.aidl
@@ -164,7 +164,7 @@ interface IPlatformCompat
boolean clearOverride(long changeId, String packageName);
/**
- * Enable all compatibility changes which have enabledAfterTargetSdk ==
+ * Enable all compatibility changes which have enabledSinceTargetSdk ==
* {@param targetSdkVersion} for an app, subject to the policy. Kills the app to allow the
* changes to take effect.
*
diff --git a/core/java/com/android/internal/config/sysui/SystemUiDeviceConfigFlags.java b/core/java/com/android/internal/config/sysui/SystemUiDeviceConfigFlags.java
index d23ea3c46695..a2af4d6cf456 100644
--- a/core/java/com/android/internal/config/sysui/SystemUiDeviceConfigFlags.java
+++ b/core/java/com/android/internal/config/sysui/SystemUiDeviceConfigFlags.java
@@ -132,6 +132,11 @@ public final class SystemUiDeviceConfigFlags {
*/
public static final String PROPERTY_MIC_CAMERA_ENABLED = "camera_mic_icons_enabled";
+ /**
+ * Whether to show app ops chip for location.
+ */
+ public static final String PROPERTY_LOCATION_INDICATORS_ENABLED = "location_indicators_enabled";
+
// Flags related to Assistant
/**
diff --git a/core/java/com/android/internal/os/AppIdToPackageMap.java b/core/java/com/android/internal/os/AppIdToPackageMap.java
index 65aa989bbb38..98cced89a174 100644
--- a/core/java/com/android/internal/os/AppIdToPackageMap.java
+++ b/core/java/com/android/internal/os/AppIdToPackageMap.java
@@ -16,25 +16,23 @@
package com.android.internal.os;
-
import android.app.AppGlobals;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.os.RemoteException;
import android.os.UserHandle;
+import android.util.SparseArray;
import com.android.internal.annotations.VisibleForTesting;
-import java.util.HashMap;
import java.util.List;
-import java.util.Map;
/** Maps AppIds to their package names. */
public final class AppIdToPackageMap {
- private final Map<Integer, String> mAppIdToPackageMap;
+ private final SparseArray<String> mAppIdToPackageMap;
@VisibleForTesting
- public AppIdToPackageMap(Map<Integer, String> appIdToPackageMap) {
+ public AppIdToPackageMap(SparseArray<String> appIdToPackageMap) {
mAppIdToPackageMap = appIdToPackageMap;
}
@@ -50,10 +48,10 @@ public final class AppIdToPackageMap {
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
- final Map<Integer, String> map = new HashMap<>();
+ final SparseArray<String> map = new SparseArray<>();
for (PackageInfo pkg : packages) {
final int uid = pkg.applicationInfo.uid;
- if (pkg.sharedUserId != null && map.containsKey(uid)) {
+ if (pkg.sharedUserId != null && map.indexOfKey(uid) >= 0) {
// Use sharedUserId string as package name if there are collisions
map.put(uid, "shared:" + pkg.sharedUserId);
} else {
diff --git a/core/java/com/android/internal/os/BatteryStatsImpl.java b/core/java/com/android/internal/os/BatteryStatsImpl.java
index dbe97964b0ca..b986463a62f7 100644
--- a/core/java/com/android/internal/os/BatteryStatsImpl.java
+++ b/core/java/com/android/internal/os/BatteryStatsImpl.java
@@ -195,7 +195,7 @@ public class BatteryStatsImpl extends BatteryStats {
static final int MSG_REPORT_POWER_CHANGE = 2;
static final int MSG_REPORT_CHARGING = 3;
static final int MSG_REPORT_RESET_STATS = 4;
- static final long DELAY_UPDATE_WAKELOCKS = 5*1000;
+ static final long DELAY_UPDATE_WAKELOCKS = 60 * 1000;
private static final double MILLISECONDS_IN_HOUR = 3600 * 1000;
private static final long MILLISECONDS_IN_YEAR = 365 * 24 * 3600 * 1000L;
diff --git a/core/java/com/android/internal/os/ZygoteInit.java b/core/java/com/android/internal/os/ZygoteInit.java
index 5948e7eab4ee..c762939faac2 100644
--- a/core/java/com/android/internal/os/ZygoteInit.java
+++ b/core/java/com/android/internal/os/ZygoteInit.java
@@ -385,7 +385,6 @@ public class ZygoteInit {
"/system/framework/android.hidl.manager-V1.0-java.jar", null /*packageName*/,
null /*codePaths*/, null /*name*/, 0 /*version*/, SharedLibraryInfo.TYPE_BUILTIN,
null /*declaringPackage*/, null /*dependentPackages*/, null /*dependencies*/);
- hidlManager.addDependency(hidlBase);
SharedLibraryInfo androidTestBase = new SharedLibraryInfo(
"/system/framework/android.test.base.jar", null /*packageName*/,
diff --git a/core/java/com/android/internal/policy/PhoneWindow.java b/core/java/com/android/internal/policy/PhoneWindow.java
index 50eed27976ad..e848da9b8ee3 100644
--- a/core/java/com/android/internal/policy/PhoneWindow.java
+++ b/core/java/com/android/internal/policy/PhoneWindow.java
@@ -77,7 +77,7 @@ import android.util.TypedValue;
import android.view.ContextThemeWrapper;
import android.view.Gravity;
import android.view.IRotationWatcher.Stub;
-import android.view.IScrollCaptureController;
+import android.view.IScrollCaptureCallbacks;
import android.view.IWindowManager;
import android.view.InputDevice;
import android.view.InputEvent;
@@ -1511,11 +1511,13 @@ public class PhoneWindow extends Window implements MenuBuilder.Callback {
if (drawable != mBackgroundDrawable) {
mBackgroundDrawable = drawable;
if (mDecor != null) {
+ mDecor.startChanging();
mDecor.setWindowBackground(drawable);
if (mBackgroundFallbackDrawable != null) {
mDecor.setBackgroundFallback(drawable != null ? null :
mBackgroundFallbackDrawable);
}
+ mDecor.finishChanging();
}
}
}
@@ -3910,12 +3912,12 @@ public class PhoneWindow extends Window implements MenuBuilder.Callback {
/**
* System request to begin scroll capture.
*
- * @param controller the controller to receive responses
+ * @param callbacks to receive responses
* @hide
*/
@Override
- public void requestScrollCapture(IScrollCaptureController controller) {
- getViewRootImpl().dispatchScrollCaptureRequest(controller);
+ public void requestScrollCapture(IScrollCaptureCallbacks callbacks) {
+ getViewRootImpl().dispatchScrollCaptureRequest(callbacks);
}
/**
@@ -3924,7 +3926,7 @@ public class PhoneWindow extends Window implements MenuBuilder.Callback {
* @param callback the callback to add
*/
@Override
- public void addScrollCaptureCallback(@NonNull ScrollCaptureCallback callback) {
+ public void registerScrollCaptureCallback(@NonNull ScrollCaptureCallback callback) {
getViewRootImpl().addScrollCaptureCallback(callback);
}
@@ -3934,7 +3936,7 @@ public class PhoneWindow extends Window implements MenuBuilder.Callback {
* @param callback the callback to remove
*/
@Override
- public void removeScrollCaptureCallback(@NonNull ScrollCaptureCallback callback) {
+ public void unregisterScrollCaptureCallback(@NonNull ScrollCaptureCallback callback) {
getViewRootImpl().removeScrollCaptureCallback(callback);
}
diff --git a/core/java/com/android/internal/util/LocalLog.java b/core/java/com/android/internal/util/LocalLog.java
index 39166917d521..057dc8fd477c 100644
--- a/core/java/com/android/internal/util/LocalLog.java
+++ b/core/java/com/android/internal/util/LocalLog.java
@@ -16,12 +16,12 @@
package com.android.internal.util;
-import java.io.PrintWriter;
-import java.util.ArrayList;
-
+import android.util.IndentingPrintWriter;
import android.util.Slog;
import android.util.proto.ProtoOutputStream;
+import java.util.ArrayList;
+
/**
* Helper class for logging serious issues, which also keeps a small
* snapshot of the logged events that can be printed later, such as part
@@ -47,20 +47,21 @@ public class LocalLog {
}
}
- public boolean dump(PrintWriter pw, String header, String prefix) {
+ public boolean dump(IndentingPrintWriter pw, String header) {
synchronized (mLines) {
if (mLines.size() <= 0) {
return false;
}
if (header != null) {
pw.println(header);
+ pw.increaseIndent();
}
for (int i=0; i<mLines.size(); i++) {
- if (prefix != null) {
- pw.print(prefix);
- }
pw.println(mLines.get(i));
}
+ if (header != null) {
+ pw.decreaseIndent();
+ }
return true;
}
}
diff --git a/core/java/com/android/internal/util/NotificationMessagingUtil.java b/core/java/com/android/internal/util/NotificationMessagingUtil.java
index 28994fd52126..c59647d264f6 100644
--- a/core/java/com/android/internal/util/NotificationMessagingUtil.java
+++ b/core/java/com/android/internal/util/NotificationMessagingUtil.java
@@ -26,7 +26,7 @@ import android.os.Looper;
import android.os.UserHandle;
import android.provider.Settings;
import android.service.notification.StatusBarNotification;
-import android.util.ArrayMap;
+import android.util.SparseArray;
import java.util.Collection;
import java.util.Objects;
@@ -39,7 +39,7 @@ public class NotificationMessagingUtil {
private static final String DEFAULT_SMS_APP_SETTING = Settings.Secure.SMS_DEFAULT_APPLICATION;
private final Context mContext;
- private ArrayMap<Integer, String> mDefaultSmsApp = new ArrayMap<>();
+ private SparseArray<String> mDefaultSmsApp = new SparseArray<>();
public NotificationMessagingUtil(Context context) {
mContext = context;
diff --git a/core/java/com/android/internal/util/Preconditions.java b/core/java/com/android/internal/util/Preconditions.java
index e80e5454f40e..4d441cd98a96 100644
--- a/core/java/com/android/internal/util/Preconditions.java
+++ b/core/java/com/android/internal/util/Preconditions.java
@@ -262,6 +262,25 @@ public class Preconditions {
}
/**
+ * Ensures the truth of an expression involving whether the calling identity is authorized to
+ * call the calling method.
+ *
+ * @param expression a boolean expression
+ * @param messageTemplate a printf-style message template to use if the check fails; will
+ * be converted to a string using {@link String#format(String, Object...)}
+ * @param messageArgs arguments for {@code messageTemplate}
+ * @throws SecurityException if {@code expression} is false
+ */
+ public static void checkCallAuthorization(
+ final boolean expression,
+ final @NonNull String messageTemplate,
+ final Object... messageArgs) {
+ if (!expression) {
+ throw new SecurityException(String.format(messageTemplate, messageArgs));
+ }
+ }
+
+ /**
* Ensures the truth of an expression involving whether the calling user is authorized to
* call the calling method.
*
@@ -694,7 +713,7 @@ public class Preconditions {
*/
public static float[] checkArrayElementsInRange(float[] value, float lower, float upper,
String valueName) {
- checkNotNull(value, valueName + " must not be null");
+ checkNotNull(value, "%s must not be null", valueName);
for (int i = 0; i < value.length; ++i) {
float v = value[i];
@@ -730,7 +749,7 @@ public class Preconditions {
*/
public static int[] checkArrayElementsInRange(int[] value, int lower, int upper,
String valueName) {
- checkNotNull(value, valueName + " must not be null");
+ checkNotNull(value, "%s must not be null", valueName);
for (int i = 0; i < value.length; ++i) {
int v = value[i];
diff --git a/core/java/com/android/internal/util/XmlUtils.java b/core/java/com/android/internal/util/XmlUtils.java
index c1be33a215b8..bd6b950623eb 100644
--- a/core/java/com/android/internal/util/XmlUtils.java
+++ b/core/java/com/android/internal/util/XmlUtils.java
@@ -1416,19 +1416,19 @@ public class XmlUtils {
if (tagName.equals("null")) {
res = null;
} else if (tagName.equals("string")) {
- String value = "";
+ final StringBuilder value = new StringBuilder();
int eventType;
while ((eventType = parser.next()) != parser.END_DOCUMENT) {
if (eventType == parser.END_TAG) {
if (parser.getName().equals("string")) {
name[0] = valueName;
//System.out.println("Returning value for " + valueName + ": " + value);
- return value;
+ return value.toString();
}
throw new XmlPullParserException(
"Unexpected end tag in <string>: " + parser.getName());
} else if (eventType == parser.TEXT) {
- value += parser.getText();
+ value.append(parser.getText());
} else if (eventType == parser.START_TAG) {
throw new XmlPullParserException(
"Unexpected start tag in <string>: " + parser.getName());
diff --git a/core/java/com/android/internal/view/BaseIWindow.java b/core/java/com/android/internal/view/BaseIWindow.java
index fff9ac9e49b7..8962dc3d59da 100644
--- a/core/java/com/android/internal/view/BaseIWindow.java
+++ b/core/java/com/android/internal/view/BaseIWindow.java
@@ -24,7 +24,7 @@ import android.os.ParcelFileDescriptor;
import android.os.RemoteException;
import android.util.MergedConfiguration;
import android.view.DragEvent;
-import android.view.IScrollCaptureController;
+import android.view.IScrollCaptureCallbacks;
import android.view.IWindow;
import android.view.IWindowSession;
import android.view.InsetsSourceControl;
@@ -162,9 +162,9 @@ public class BaseIWindow extends IWindow.Stub {
}
@Override
- public void requestScrollCapture(IScrollCaptureController controller) {
+ public void requestScrollCapture(IScrollCaptureCallbacks callbacks) {
try {
- controller.onClientUnavailable();
+ callbacks.onUnavailable();
} catch (RemoteException ex) {
// ignore
}
diff --git a/core/java/com/android/internal/widget/CachingIconView.java b/core/java/com/android/internal/widget/CachingIconView.java
index 84cde1b84e14..0bf323f8f493 100644
--- a/core/java/com/android/internal/widget/CachingIconView.java
+++ b/core/java/com/android/internal/widget/CachingIconView.java
@@ -16,12 +16,15 @@
package com.android.internal.widget;
+import static com.android.internal.widget.ColoredIconHelper.applyGrayTint;
+
import android.annotation.DrawableRes;
import android.annotation.Nullable;
import android.compat.annotation.UnsupportedAppUsage;
import android.content.Context;
import android.content.res.Configuration;
import android.graphics.Bitmap;
+import android.graphics.PorterDuff;
import android.graphics.drawable.Drawable;
import android.graphics.drawable.Icon;
import android.net.Uri;
@@ -48,6 +51,7 @@ public class CachingIconView extends ImageView {
private Consumer<Integer> mOnVisibilityChangedListener;
private Consumer<Boolean> mOnForceHiddenChangedListener;
private int mIconColor;
+ private int mBackgroundColor;
private boolean mWillBeForceHidden;
@UnsupportedAppUsage
@@ -230,9 +234,55 @@ public class CachingIconView extends ImageView {
return mForceHidden;
}
+ /**
+ * Provides the notification's background color to the icon. This is only used when the icon
+ * is "inverted". This should be called before calling {@link #setOriginalIconColor(int)}.
+ */
+ @RemotableViewMethod
+ public void setBackgroundColor(int color) {
+ mBackgroundColor = color;
+ }
+
+ /**
+ * Sets the icon color. If COLOR_INVALID is set, the icon's color filter will
+ * not be altered. If there is a background drawable, this method uses the value from
+ * {@link #setBackgroundColor(int)} which must have been already called.
+ */
@RemotableViewMethod
public void setOriginalIconColor(int color) {
mIconColor = color;
+ Drawable background = getBackground();
+ Drawable icon = getDrawable();
+ boolean hasColor = color != ColoredIconHelper.COLOR_INVALID;
+ if (background == null) {
+ // This is the pre-S style -- colored icon with no background.
+ if (hasColor) {
+ icon.mutate().setColorFilter(color, PorterDuff.Mode.SRC_ATOP);
+ }
+ } else {
+ // When there is a background drawable, color it with the foreground color and
+ // colorize the icon itself with the background color, creating an inverted effect.
+ if (hasColor) {
+ background.mutate().setColorFilter(color, PorterDuff.Mode.SRC_ATOP);
+ icon.mutate().setColorFilter(mBackgroundColor, PorterDuff.Mode.SRC_ATOP);
+ } else {
+ background.mutate().setColorFilter(mBackgroundColor, PorterDuff.Mode.SRC_ATOP);
+ }
+ }
+ }
+
+ /**
+ * Set the icon's color filter: to gray if true, otherwise colored.
+ * If this icon has no original color, this has no effect.
+ */
+ public void setGrayedOut(boolean grayedOut) {
+ // If there is a background drawable, then it has the foreground color and the image
+ // drawable has the background color, creating an inverted efffect.
+ Drawable drawable = getBackground();
+ if (drawable == null) {
+ drawable = getDrawable();
+ }
+ applyGrayTint(mContext, drawable, grayedOut, mIconColor);
}
public int getOriginalIconColor() {
diff --git a/core/java/com/android/internal/widget/ColoredIconHelper.java b/core/java/com/android/internal/widget/ColoredIconHelper.java
new file mode 100644
index 000000000000..97e5e86d9e60
--- /dev/null
+++ b/core/java/com/android/internal/widget/ColoredIconHelper.java
@@ -0,0 +1,57 @@
+/*
+ * 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.internal.widget;
+
+import android.annotation.ColorInt;
+import android.app.Notification;
+import android.content.Context;
+import android.content.res.Configuration;
+import android.graphics.PorterDuff;
+import android.graphics.drawable.Drawable;
+
+import com.android.internal.util.ContrastColorUtil;
+
+/** Helpers for colored icons */
+final class ColoredIconHelper {
+
+ @ColorInt
+ static final int COLOR_INVALID = Notification.COLOR_INVALID;
+
+ private ColoredIconHelper() {
+ }
+
+ /**
+ * Apply a gray tint or the original color to a drawable, accounting for the night mode in
+ * selecting the gray.
+ */
+ static void applyGrayTint(Context ctx, Drawable drawable, boolean apply, int originalColor) {
+ if (originalColor == COLOR_INVALID) {
+ return;
+ }
+ if (apply) {
+ // lets gray it out
+ Configuration config = ctx.getResources().getConfiguration();
+ boolean inNightMode = (config.uiMode & Configuration.UI_MODE_NIGHT_MASK)
+ == Configuration.UI_MODE_NIGHT_YES;
+ int grey = ContrastColorUtil.resolveColor(ctx, Notification.COLOR_DEFAULT, inNightMode);
+ drawable.mutate().setColorFilter(grey, PorterDuff.Mode.SRC_ATOP);
+ } else {
+ // lets reset it
+ drawable.mutate().setColorFilter(originalColor, PorterDuff.Mode.SRC_ATOP);
+ }
+ }
+}
diff --git a/core/java/com/android/internal/widget/NotificationExpandButton.java b/core/java/com/android/internal/widget/NotificationExpandButton.java
index a49980696e6b..986412d2ce5d 100644
--- a/core/java/com/android/internal/widget/NotificationExpandButton.java
+++ b/core/java/com/android/internal/widget/NotificationExpandButton.java
@@ -16,6 +16,8 @@
package com.android.internal.widget;
+import static com.android.internal.widget.ColoredIconHelper.applyGrayTint;
+
import android.annotation.Nullable;
import android.content.Context;
import android.graphics.Rect;
@@ -26,12 +28,15 @@ import android.widget.Button;
import android.widget.ImageView;
import android.widget.RemoteViews;
+import com.android.internal.R;
+
/**
* An expand button in a notification
*/
@RemoteViews.RemoteView
public class NotificationExpandButton extends ImageView {
+ private boolean mExpanded;
private int mOriginalNotificationColor;
public NotificationExpandButton(Context context) {
@@ -67,6 +72,14 @@ public class NotificationExpandButton extends ImageView {
return mOriginalNotificationColor;
}
+ /**
+ * Set the button's color filter: to gray if true, otherwise colored.
+ * If this button has no original color, this has no effect.
+ */
+ public void setGrayedOut(boolean shouldApply) {
+ applyGrayTint(mContext, getDrawable(), shouldApply, mOriginalNotificationColor);
+ }
+
private void extendRectToMinTouchSize(Rect rect) {
int touchTargetSize = (int) (getResources().getDisplayMetrics().density * 48);
rect.left = rect.centerX() - touchTargetSize / 2;
@@ -80,4 +93,28 @@ public class NotificationExpandButton extends ImageView {
super.onInitializeAccessibilityNodeInfo(info);
info.setClassName(Button.class.getName());
}
+
+ /**
+ * Update the button's drawable, content description, and color for the given expanded state.
+ */
+ @RemotableViewMethod
+ public void setExpanded(boolean expanded) {
+ mExpanded = expanded;
+ updateExpandButton();
+ }
+
+ private void updateExpandButton() {
+ int drawableId;
+ int contentDescriptionId;
+ if (mExpanded) {
+ drawableId = R.drawable.ic_collapse_notification;
+ contentDescriptionId = R.string.expand_button_content_description_expanded;
+ } else {
+ drawableId = R.drawable.ic_expand_notification;
+ contentDescriptionId = R.string.expand_button_content_description_collapsed;
+ }
+ setImageDrawable(getContext().getDrawable(drawableId));
+ setColorFilter(mOriginalNotificationColor);
+ setContentDescription(mContext.getText(contentDescriptionId));
+ }
}
diff --git a/core/java/com/android/server/SystemConfig.java b/core/java/com/android/server/SystemConfig.java
index ed663cfeb613..a761b4c6af91 100644
--- a/core/java/com/android/server/SystemConfig.java
+++ b/core/java/com/android/server/SystemConfig.java
@@ -250,7 +250,7 @@ public class SystemConfig {
// partition that is used to verify if an overlay package fulfills
// the 'config_signature' policy by comparing their signatures:
// if the overlay package is signed with the same certificate as
- // the package declared in 'config-signature' tag, then the
+ // the package declared in 'overlay-config-signature' tag, then the
// overlay package fulfills the 'config_signature' policy.
private String mOverlayConfigSignaturePackage;
diff --git a/core/jni/android_graphics_BLASTBufferQueue.cpp b/core/jni/android_graphics_BLASTBufferQueue.cpp
index b07c29307339..0fc0451c6d4b 100644
--- a/core/jni/android_graphics_BLASTBufferQueue.cpp
+++ b/core/jni/android_graphics_BLASTBufferQueue.cpp
@@ -55,7 +55,7 @@ static void nativeDestroy(JNIEnv* env, jclass clazz, jlong ptr) {
static jobject nativeGetSurface(JNIEnv* env, jclass clazz, jlong ptr) {
sp<BLASTBufferQueue> queue = reinterpret_cast<BLASTBufferQueue*>(ptr);
- return android_view_Surface_createFromIGraphicBufferProducer(env, queue->getIGraphicBufferProducer());
+ return android_view_Surface_createFromSurface(env, queue->getSurface());
}
static void nativeSetNextTransaction(JNIEnv* env, jclass clazz, jlong ptr, jlong transactionPtr) {
diff --git a/core/jni/android_opengl_GLES10.cpp b/core/jni/android_opengl_GLES10.cpp
index e4d138d92621..d65b498404fa 100644
--- a/core/jni/android_opengl_GLES10.cpp
+++ b/core/jni/android_opengl_GLES10.cpp
@@ -640,7 +640,7 @@ android_glCompressedTexImage2D__IIIIIIILjava_nio_Buffer_2
exit:
if (_array) {
- releasePointer(_env, _array, data, JNI_FALSE);
+ releasePointer(_env, _array, (void *)((char *)data - _bufferOffset), JNI_FALSE);
}
if (_exception) {
jniThrowException(_env, _exceptionType, _exceptionMessage);
@@ -684,7 +684,7 @@ android_glCompressedTexSubImage2D__IIIIIIIILjava_nio_Buffer_2
exit:
if (_array) {
- releasePointer(_env, _array, data, JNI_FALSE);
+ releasePointer(_env, _array, (void *)((char *)data - _bufferOffset), JNI_FALSE);
}
if (_exception) {
jniThrowException(_env, _exceptionType, _exceptionMessage);
@@ -929,7 +929,7 @@ android_glDrawElements__IIILjava_nio_Buffer_2
exit:
if (_array) {
- releasePointer(_env, _array, indices, JNI_FALSE);
+ releasePointer(_env, _array, (void *)((char *)indices - _bufferOffset), JNI_FALSE);
}
if (_exception) {
jniThrowException(_env, _exceptionType, _exceptionMessage);
@@ -2801,7 +2801,8 @@ android_glReadPixels__IIIIIILjava_nio_Buffer_2
exit:
if (_array) {
- releasePointer(_env, _array, pixels, _exception ? JNI_FALSE : JNI_TRUE);
+ releasePointer(_env, _array, (void *)((char *)pixels - _bufferOffset),
+ _exception ? JNI_FALSE : JNI_TRUE);
}
if (_exception) {
jniThrowException(_env, _exceptionType, _exceptionMessage);
@@ -3241,7 +3242,7 @@ android_glTexImage2D__IIIIIIIILjava_nio_Buffer_2
(GLvoid *)pixels
);
if (_array) {
- releasePointer(_env, _array, pixels, JNI_FALSE);
+ releasePointer(_env, _array, (void *)((char *)pixels - _bufferOffset), JNI_FALSE);
}
if (_exception) {
jniThrowException(_env, _exceptionType, _exceptionMessage);
@@ -3301,7 +3302,7 @@ android_glTexSubImage2D__IIIIIIIILjava_nio_Buffer_2
(GLvoid *)pixels
);
if (_array) {
- releasePointer(_env, _array, pixels, JNI_FALSE);
+ releasePointer(_env, _array, (void *)((char *)pixels - _bufferOffset), JNI_FALSE);
}
if (_exception) {
jniThrowException(_env, _exceptionType, _exceptionMessage);
diff --git a/core/jni/android_opengl_GLES11.cpp b/core/jni/android_opengl_GLES11.cpp
index 1069a1d3acb1..9724e6c2a5dd 100644
--- a/core/jni/android_opengl_GLES11.cpp
+++ b/core/jni/android_opengl_GLES11.cpp
@@ -464,7 +464,7 @@ android_glBufferData__IILjava_nio_Buffer_2I
exit:
if (_array) {
- releasePointer(_env, _array, data, JNI_FALSE);
+ releasePointer(_env, _array, (void *)((char *)data - _bufferOffset), JNI_FALSE);
}
if (_exception) {
jniThrowException(_env, _exceptionType, _exceptionMessage);
@@ -509,7 +509,7 @@ android_glBufferSubData__IIILjava_nio_Buffer_2
exit:
if (_array) {
- releasePointer(_env, _array, data, JNI_FALSE);
+ releasePointer(_env, _array, (void *)((char *)data - _bufferOffset), JNI_FALSE);
}
if (_exception) {
jniThrowException(_env, _exceptionType, _exceptionMessage);
diff --git a/core/jni/android_opengl_GLES11Ext.cpp b/core/jni/android_opengl_GLES11Ext.cpp
index 86d7ecdce44d..1ffa4ec67ae1 100644
--- a/core/jni/android_opengl_GLES11Ext.cpp
+++ b/core/jni/android_opengl_GLES11Ext.cpp
@@ -893,7 +893,8 @@ android_glEGLImageTargetTexture2DOES__ILjava_nio_Buffer_2
exit:
if (_array) {
- releasePointer(_env, _array, image, _exception ? JNI_FALSE : JNI_TRUE);
+ releasePointer(_env, _array, (void *)((char *)image - _bufferOffset),
+ _exception ? JNI_FALSE : JNI_TRUE);
}
if (_exception) {
jniThrowException(_env, _exceptionType, _exceptionMessage);
@@ -930,7 +931,8 @@ android_glEGLImageTargetRenderbufferStorageOES__ILjava_nio_Buffer_2
exit:
if (_array) {
- releasePointer(_env, _array, image, _exception ? JNI_FALSE : JNI_TRUE);
+ releasePointer(_env, _array, (void *)((char *)image - _bufferOffset),
+ _exception ? JNI_FALSE : JNI_TRUE);
}
if (_exception) {
jniThrowException(_env, _exceptionType, _exceptionMessage);
diff --git a/core/jni/android_opengl_GLES20.cpp b/core/jni/android_opengl_GLES20.cpp
index 49baa51f2342..d832558aa368 100644
--- a/core/jni/android_opengl_GLES20.cpp
+++ b/core/jni/android_opengl_GLES20.cpp
@@ -599,7 +599,7 @@ android_glBufferData__IILjava_nio_Buffer_2I
exit:
if (_array) {
- releasePointer(_env, _array, data, JNI_FALSE);
+ releasePointer(_env, _array, (void *)((char *)data - _bufferOffset), JNI_FALSE);
}
if (_exception) {
jniThrowException(_env, _exceptionType, _exceptionMessage);
@@ -644,7 +644,7 @@ android_glBufferSubData__IIILjava_nio_Buffer_2
exit:
if (_array) {
- releasePointer(_env, _array, data, JNI_FALSE);
+ releasePointer(_env, _array, (void *)((char *)data - _bufferOffset), JNI_FALSE);
}
if (_exception) {
jniThrowException(_env, _exceptionType, _exceptionMessage);
@@ -758,7 +758,7 @@ android_glCompressedTexImage2D__IIIIIIILjava_nio_Buffer_2
exit:
if (_array) {
- releasePointer(_env, _array, data, JNI_FALSE);
+ releasePointer(_env, _array, (void *)((char *)data - _bufferOffset), JNI_FALSE);
}
if (_exception) {
jniThrowException(_env, _exceptionType, _exceptionMessage);
@@ -802,7 +802,7 @@ android_glCompressedTexSubImage2D__IIIIIIIILjava_nio_Buffer_2
exit:
if (_array) {
- releasePointer(_env, _array, data, JNI_FALSE);
+ releasePointer(_env, _array, (void *)((char *)data - _bufferOffset), JNI_FALSE);
}
if (_exception) {
jniThrowException(_env, _exceptionType, _exceptionMessage);
@@ -1379,7 +1379,7 @@ android_glDrawElements__IIILjava_nio_Buffer_2
exit:
if (_array) {
- releasePointer(_env, _array, indices, JNI_FALSE);
+ releasePointer(_env, _array, (void *)((char *)indices - _bufferOffset), JNI_FALSE);
}
if (_exception) {
jniThrowException(_env, _exceptionType, _exceptionMessage);
@@ -4273,7 +4273,8 @@ android_glReadPixels__IIIIIILjava_nio_Buffer_2
exit:
if (_array) {
- releasePointer(_env, _array, pixels, _exception ? JNI_FALSE : JNI_TRUE);
+ releasePointer(_env, _array, (void *)((char *)pixels - _bufferOffset),
+ _exception ? JNI_FALSE : JNI_TRUE);
}
if (_exception) {
jniThrowException(_env, _exceptionType, _exceptionMessage);
@@ -4380,7 +4381,7 @@ android_glShaderBinary__I_3IIILjava_nio_Buffer_2I
exit:
if (_array) {
- releasePointer(_env, _array, binary, JNI_FALSE);
+ releasePointer(_env, _array, (void *)((char *)binary - _bufferOffset), JNI_FALSE);
}
if (shaders_base) {
_env->ReleaseIntArrayElements(shaders_ref, (jint*)shaders_base,
@@ -4445,7 +4446,8 @@ android_glShaderBinary__ILjava_nio_IntBuffer_2ILjava_nio_Buffer_2I
exit:
if (_binaryArray) {
- releasePointer(_env, _binaryArray, binary, JNI_FALSE);
+ releasePointer(_env, _binaryArray, (void *)((char *)binary - _binaryBufferOffset),
+ JNI_FALSE);
}
if (_shadersArray) {
_env->ReleaseIntArrayElements(_shadersArray, (jint*)shaders, JNI_ABORT);
@@ -4568,7 +4570,7 @@ android_glTexImage2D__IIIIIIIILjava_nio_Buffer_2
(GLvoid *)pixels
);
if (_array) {
- releasePointer(_env, _array, pixels, JNI_FALSE);
+ releasePointer(_env, _array, (void *)((char *)pixels - _bufferOffset), JNI_FALSE);
}
if (_exception) {
jniThrowException(_env, _exceptionType, _exceptionMessage);
@@ -4816,7 +4818,7 @@ android_glTexSubImage2D__IIIIIIIILjava_nio_Buffer_2
(GLvoid *)pixels
);
if (_array) {
- releasePointer(_env, _array, pixels, JNI_FALSE);
+ releasePointer(_env, _array, (void *)((char *)pixels - _bufferOffset), JNI_FALSE);
}
if (_exception) {
jniThrowException(_env, _exceptionType, _exceptionMessage);
diff --git a/core/jni/android_opengl_GLES30.cpp b/core/jni/android_opengl_GLES30.cpp
index 32a2a24c2d2d..719c6b32fec6 100644
--- a/core/jni/android_opengl_GLES30.cpp
+++ b/core/jni/android_opengl_GLES30.cpp
@@ -463,7 +463,7 @@ android_glDrawRangeElements__IIIIILjava_nio_Buffer_2
exit:
if (_array) {
- releasePointer(_env, _array, indices, JNI_FALSE);
+ releasePointer(_env, _array, (void *)((char *)indices - _bufferOffset), JNI_FALSE);
}
if (_exception) {
jniThrowException(_env, _exceptionType, _exceptionMessage);
@@ -516,7 +516,7 @@ android_glTexImage3D__IIIIIIIIILjava_nio_Buffer_2
(GLvoid *)pixels
);
if (_array) {
- releasePointer(_env, _array, pixels, JNI_FALSE);
+ releasePointer(_env, _array, (void *)((char *)pixels - _bufferOffset), JNI_FALSE);
}
if (_exception) {
jniThrowException(_env, _exceptionType, _exceptionMessage);
@@ -580,7 +580,7 @@ android_glTexSubImage3D__IIIIIIIIIILjava_nio_Buffer_2
exit:
if (_array) {
- releasePointer(_env, _array, pixels, JNI_FALSE);
+ releasePointer(_env, _array, (void *)((char *)pixels - _bufferOffset), JNI_FALSE);
}
if (_exception) {
jniThrowException(_env, _exceptionType, _exceptionMessage);
@@ -660,7 +660,7 @@ android_glCompressedTexImage3D__IIIIIIIILjava_nio_Buffer_2
exit:
if (_array) {
- releasePointer(_env, _array, data, JNI_FALSE);
+ releasePointer(_env, _array, (void *)((char *)data - _bufferOffset), JNI_FALSE);
}
if (_exception) {
jniThrowException(_env, _exceptionType, _exceptionMessage);
@@ -723,7 +723,7 @@ android_glCompressedTexSubImage3D__IIIIIIIIIILjava_nio_Buffer_2
exit:
if (_array) {
- releasePointer(_env, _array, data, JNI_FALSE);
+ releasePointer(_env, _array, (void *)((char *)data - _bufferOffset), JNI_FALSE);
}
if (_exception) {
jniThrowException(_env, _exceptionType, _exceptionMessage);
@@ -5445,7 +5445,8 @@ android_glGetProgramBinary__II_3II_3IILjava_nio_Buffer_2
exit:
if (_array) {
- releasePointer(_env, _array, binary, _exception ? JNI_FALSE : JNI_TRUE);
+ releasePointer(_env, _array, (void *)((char *)binary - _bufferOffset),
+ _exception ? JNI_FALSE : JNI_TRUE);
}
if (binaryFormat_base) {
_env->ReleaseIntArrayElements(binaryFormat_ref, (jint*)binaryFormat_base,
@@ -5519,7 +5520,8 @@ android_glGetProgramBinary__IILjava_nio_IntBuffer_2Ljava_nio_IntBuffer_2Ljava_ni
exit:
if (_binaryArray) {
- releasePointer(_env, _binaryArray, binary, _exception ? JNI_FALSE : JNI_TRUE);
+ releasePointer(_env, _binaryArray, (void *)((char *)binary - _binaryBufferOffset),
+ _exception ? JNI_FALSE : JNI_TRUE);
}
if (_binaryFormatArray) {
_env->ReleaseIntArrayElements(_binaryFormatArray, (jint*)binaryFormat, _exception ? JNI_ABORT : 0);
@@ -5564,7 +5566,7 @@ android_glProgramBinary__IILjava_nio_Buffer_2I
exit:
if (_array) {
- releasePointer(_env, _array, binary, JNI_FALSE);
+ releasePointer(_env, _array, (void *)((char *)binary - _bufferOffset), JNI_FALSE);
}
if (_exception) {
jniThrowException(_env, _exceptionType, _exceptionMessage);
diff --git a/core/jni/android_opengl_GLES32.cpp b/core/jni/android_opengl_GLES32.cpp
index 07a794d0ef19..7ed754850ea3 100644
--- a/core/jni/android_opengl_GLES32.cpp
+++ b/core/jni/android_opengl_GLES32.cpp
@@ -863,7 +863,7 @@ android_glDrawElementsBaseVertex__IIILjava_nio_Buffer_2I
exit:
if (_array) {
- releasePointer(_env, _array, indices, JNI_FALSE);
+ releasePointer(_env, _array, (void *)((char *)indices - _bufferOffset), JNI_FALSE);
}
if (_exception) {
jniThrowException(_env, _exceptionType, _exceptionMessage);
@@ -911,7 +911,7 @@ android_glDrawRangeElementsBaseVertex__IIIIILjava_nio_Buffer_2I
exit:
if (_array) {
- releasePointer(_env, _array, indices, JNI_FALSE);
+ releasePointer(_env, _array, (void *)((char *)indices - _bufferOffset), JNI_FALSE);
}
if (_exception) {
jniThrowException(_env, _exceptionType, _exceptionMessage);
@@ -1048,7 +1048,8 @@ android_glReadnPixels__IIIIIIILjava_nio_Buffer_2
exit:
if (_array) {
- releasePointer(_env, _array, data, _exception ? JNI_FALSE : JNI_TRUE);
+ releasePointer(_env, _array, (void *)((char *)data - _bufferOffset),
+ _exception ? JNI_FALSE : JNI_TRUE);
}
if (_exception) {
jniThrowException(_env, _exceptionType, _exceptionMessage);
diff --git a/core/jni/android_util_Binder.cpp b/core/jni/android_util_Binder.cpp
index e1180384fcc9..32b8fa61c8a0 100644
--- a/core/jni/android_util_Binder.cpp
+++ b/core/jni/android_util_Binder.cpp
@@ -960,17 +960,8 @@ static jlong android_os_Binder_clearCallingIdentity()
return IPCThreadState::self()->clearCallingIdentity();
}
-static void android_os_Binder_restoreCallingIdentity(JNIEnv* env, jobject clazz, jlong token)
+static void android_os_Binder_restoreCallingIdentity(jlong token)
{
- // XXX temporary validation check to debug crashes.
- int uid = (int)(token>>32);
- if (uid > 0 && uid < 999) {
- // In Android currently there are no uids in this range.
- char buf[128];
- sprintf(buf, "Restoring bad calling ident: 0x%" PRIx64, token);
- jniThrowException(env, "java/lang/IllegalStateException", buf);
- return;
- }
IPCThreadState::self()->restoreCallingIdentity(token);
}
@@ -1064,6 +1055,7 @@ static const JNINativeMethod gBinderMethods[] = {
{ "isHandlingTransaction", "()Z", (void*)android_os_Binder_isHandlingTransaction },
// @CriticalNative
{ "clearCallingIdentity", "()J", (void*)android_os_Binder_clearCallingIdentity },
+ // @CriticalNative
{ "restoreCallingIdentity", "(J)V", (void*)android_os_Binder_restoreCallingIdentity },
// @CriticalNative
{ "setThreadStrictModePolicy", "(I)V", (void*)android_os_Binder_setThreadStrictModePolicy },
diff --git a/core/jni/android_view_Surface.cpp b/core/jni/android_view_Surface.cpp
index 6a07cf7bbf40..5c87f1973bed 100644
--- a/core/jni/android_view_Surface.cpp
+++ b/core/jni/android_view_Surface.cpp
@@ -313,7 +313,7 @@ static jlong nativeGetFromBlastBufferQueue(JNIEnv* env, jclass clazz, jlong nati
return nativeObject;
}
- sp<Surface> surface(new Surface(bufferProducer, true));
+ sp<Surface> surface = queue->getSurface();
if (surface != NULL) {
surface->incStrong(&sRefBaseOwner);
}
diff --git a/core/jni/com_google_android_gles_jni_GLImpl.cpp b/core/jni/com_google_android_gles_jni_GLImpl.cpp
index ffc1ddc03355..21de72397384 100644
--- a/core/jni/com_google_android_gles_jni_GLImpl.cpp
+++ b/core/jni/com_google_android_gles_jni_GLImpl.cpp
@@ -424,7 +424,7 @@ android_glCompressedTexImage2D__IIIIIIILjava_nio_Buffer_2
exit:
if (_array) {
- releasePointer(_env, _array, data, JNI_FALSE);
+ releasePointer(_env, _array, (void *)((char *)data - _bufferOffset), JNI_FALSE);
}
if (_exception) {
jniThrowException(_env, _exceptionType, _exceptionMessage);
@@ -468,7 +468,7 @@ android_glCompressedTexSubImage2D__IIIIIIIILjava_nio_Buffer_2
exit:
if (_array) {
- releasePointer(_env, _array, data, JNI_FALSE);
+ releasePointer(_env, _array, (void *)((char *)data - _bufferOffset), JNI_FALSE);
}
if (_exception) {
jniThrowException(_env, _exceptionType, _exceptionMessage);
@@ -713,7 +713,7 @@ android_glDrawElements__IIILjava_nio_Buffer_2
exit:
if (_array) {
- releasePointer(_env, _array, indices, JNI_FALSE);
+ releasePointer(_env, _array, (void *)((char *)indices - _bufferOffset), JNI_FALSE);
}
if (_exception) {
jniThrowException(_env, _exceptionType, _exceptionMessage);
@@ -3488,7 +3488,8 @@ android_glReadPixels__IIIIIILjava_nio_Buffer_2
exit:
if (_array) {
- releasePointer(_env, _array, pixels, _exception ? JNI_FALSE : JNI_TRUE);
+ releasePointer(_env, _array, (void *)((char *)pixels - _bufferOffset),
+ _exception ? JNI_FALSE : JNI_TRUE);
}
if (_exception) {
jniThrowException(_env, _exceptionType, _exceptionMessage);
@@ -3972,7 +3973,7 @@ android_glTexImage2D__IIIIIIIILjava_nio_Buffer_2
(GLvoid *)pixels
);
if (_array) {
- releasePointer(_env, _array, pixels, JNI_FALSE);
+ releasePointer(_env, _array, (void *)((char *)pixels - _bufferOffset), JNI_FALSE);
}
if (_exception) {
jniThrowException(_env, _exceptionType, _exceptionMessage);
@@ -4032,7 +4033,7 @@ android_glTexSubImage2D__IIIIIIIILjava_nio_Buffer_2
(GLvoid *)pixels
);
if (_array) {
- releasePointer(_env, _array, pixels, JNI_FALSE);
+ releasePointer(_env, _array, (void *)((char *)pixels - _bufferOffset), JNI_FALSE);
}
if (_exception) {
jniThrowException(_env, _exceptionType, _exceptionMessage);
@@ -4299,7 +4300,7 @@ android_glBufferData__IILjava_nio_Buffer_2I
exit:
if (_array) {
- releasePointer(_env, _array, data, JNI_FALSE);
+ releasePointer(_env, _array, (void *)((char *)data - _bufferOffset), JNI_FALSE);
}
if (_exception) {
jniThrowException(_env, _exceptionType, _exceptionMessage);
@@ -4344,7 +4345,7 @@ android_glBufferSubData__IIILjava_nio_Buffer_2
exit:
if (_array) {
- releasePointer(_env, _array, data, JNI_FALSE);
+ releasePointer(_env, _array, (void *)((char *)data - _bufferOffset), JNI_FALSE);
}
if (_exception) {
jniThrowException(_env, _exceptionType, _exceptionMessage);
diff --git a/core/jni/core_jni_helpers.h b/core/jni/core_jni_helpers.h
index 013c65faa241..526804998896 100644
--- a/core/jni/core_jni_helpers.h
+++ b/core/jni/core_jni_helpers.h
@@ -47,7 +47,7 @@ static inline jclass FindClassOrDie(JNIEnv* env, const char* class_name) {
static inline jfieldID GetFieldIDOrDie(JNIEnv* env, jclass clazz, const char* field_name,
const char* field_signature) {
jfieldID res = env->GetFieldID(clazz, field_name, field_signature);
- LOG_ALWAYS_FATAL_IF(res == NULL, "Unable to find static field %s with signature %s", field_name,
+ LOG_ALWAYS_FATAL_IF(res == NULL, "Unable to find field %s with signature %s", field_name,
field_signature);
return res;
}
diff --git a/core/proto/android/server/windowmanagerservice.proto b/core/proto/android/server/windowmanagerservice.proto
index 0affcea99706..ce52a352e10b 100644
--- a/core/proto/android/server/windowmanagerservice.proto
+++ b/core/proto/android/server/windowmanagerservice.proto
@@ -195,7 +195,7 @@ message DisplayContentProto {
repeated WindowTokenProto overlay_windows = 20 [deprecated=true];
optional DisplayAreaProto root_display_area = 21;
- optional bool single_task_instance = 22;
+ optional bool single_task_instance = 22 [deprecated=true];
optional int32 focused_root_task_id = 23;
optional .com.android.server.wm.IdentifierProto resumed_activity = 24;
repeated TaskProto tasks = 25 [deprecated=true];
diff --git a/core/proto/android/service/package.proto b/core/proto/android/service/package.proto
index d289e00d3467..55671091687c 100644
--- a/core/proto/android/service/package.proto
+++ b/core/proto/android/service/package.proto
@@ -129,6 +129,16 @@ message PackageProto {
optional bool is_loading = 2;
}
+ // TODO (b/170263003) refactor to permissiongr
+ // Runtime permission state that are granted for users.
+ message UserPermissionsProto {
+ option (android.msg_privacy).dest = DEST_AUTOMATIC;
+ // User id.
+ optional int32 id = 1;
+ // Pre-granted Android permissions.
+ repeated string granted_permissions = 2;
+ }
+
// Name of package. e.g. "com.android.providers.telephony".
optional string name = 1;
// UID for this package as assigned by Android OS.
@@ -152,4 +162,6 @@ message PackageProto {
optional InstallSourceProto install_source = 10;
// Whether the package is startable or is still loading
optional StatesProto states = 11;
+ // Granted runtime permissions for users.
+ repeated UserPermissionsProto user_permissions = 12;
}
diff --git a/core/proto/android/telephony/enums.proto b/core/proto/android/telephony/enums.proto
index d2c0ed4e4736..d2c02769aa78 100644
--- a/core/proto/android/telephony/enums.proto
+++ b/core/proto/android/telephony/enums.proto
@@ -91,6 +91,14 @@ enum NetworkTypeEnum {
NETWORK_TYPE_NR = 20;
}
+// Roaming type enums, see android.telephony.ServiceState.RoamingType for definitions.
+enum RoamingTypeEnum {
+ ROAMING_TYPE_NOT_ROAMING = 0;
+ ROAMING_TYPE_ROAMING = 1;
+ ROAMING_TYPE_ROAMING_DOMESTIC = 2;
+ ROAMING_TYPE_ROAMING_INTERNATIONAL = 3;
+}
+
// Signal strength levels, primarily used by android/telephony/SignalStrength.java.
enum SignalStrengthEnum {
SIGNAL_STRENGTH_NONE_OR_UNKNOWN = 0;
@@ -220,3 +228,43 @@ enum SmsSendResultEnum {
// Error over IMS, retry on CS
SMS_SEND_RESULT_ERROR_FALLBACK = 4;
}
+
+// Data profile of the data call. From
+// frameworks/base/telephony/java/com/android/internal/telephony/RILConstants.java
+enum DataProfileEnum {
+ DATA_PROFILE_INVALID = -1;
+ DATA_PROFILE_DEFAULT = 0;
+ DATA_PROFILE_TETHERED = 1;
+ DATA_PROFILE_IMS = 2;
+ DATA_PROFILE_FOTA = 3;
+ DATA_PROFILE_CBS = 4;
+ DATA_PROFILE_OEM_BASE = 1000;
+}
+
+// Reason of data call deactivation. From
+// frameworks/base/telephony/java/android/telephony/data/DataService.java#DeactivateDataReason
+enum DataDeactivateReasonEnum {
+ DEACTIVATE_REASON_UNKNOWN = 0;
+ DEACTIVATE_REASON_NORMAL = 1;
+ DEACTIVATE_REASON_RADIO_OFF = 2;
+ DEACTIVATE_REASON_HANDOVER = 3;
+}
+
+// IP type of the data call
+// see frameworks/base/telephony/java/android/telephony/data/ApnSetting.java#ProtocolType
+enum ApnProtocolEnum {
+ APN_PROTOCOL_IPV4 = 0;
+ APN_PROTOCOL_IPV6 = 1;
+ APN_PROTOCOL_IPV4V6 = 2;
+ APN_PROTOCOL_PPP = 3;
+}
+
+// Action taken to recover a data call that is stalled. From
+// frameworks/opt/telephony/src/java/com/android/internal/telephony/dataconnection/DcTracker.java
+// #RecoveryAction
+enum DataStallRecoveryActionEnum {
+ RECOVERY_ACTION_GET_DATA_CALL_LIST = 0;
+ RECOVERY_ACTION_CLEANUP = 1;
+ RECOVERY_ACTION_REREGISTER = 2;
+ RECOVERY_ACTION_RADIO_RESTART = 3;
+} \ No newline at end of file
diff --git a/core/proto/android/view/enums.proto b/core/proto/android/view/enums.proto
index 0172e7899a18..a601abee17f6 100644
--- a/core/proto/android/view/enums.proto
+++ b/core/proto/android/view/enums.proto
@@ -60,7 +60,7 @@ enum TransitionTypeEnum {
TRANSIT_TASK_OPEN_BEHIND = 16;
TRANSIT_TASK_IN_PLACE = 17;
TRANSIT_ACTIVITY_RELAUNCH = 18;
- TRANSIT_DOCK_TASK_FROM_RECENTS = 19;
+ TRANSIT_DOCK_TASK_FROM_RECENTS = 19 [deprecated=true];
TRANSIT_KEYGUARD_GOING_AWAY = 20;
TRANSIT_KEYGUARD_GOING_AWAY_ON_WALLPAPER = 21;
TRANSIT_KEYGUARD_OCCLUDE = 22;
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index 0a1b8e093e71..01954510ee08 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -2539,8 +2539,7 @@
<permission android:name="android.permission.START_ANY_ACTIVITY"
android:protectionLevel="signature" />
- <!-- Allows an application to start activities from background
- @hide -->
+ <!-- @SystemApi @hide Allows an application to start activities from background -->
<permission android:name="android.permission.START_ACTIVITIES_FROM_BACKGROUND"
android:protectionLevel="signature|privileged|vendorPrivileged|oem|verifier" />
diff --git a/core/res/res/layout/notification_material_media_transfer_action.xml b/core/res/res/layout/notification_material_media_transfer_action.xml
deleted file mode 100644
index 98d8f1eee8c9..000000000000
--- a/core/res/res/layout/notification_material_media_transfer_action.xml
+++ /dev/null
@@ -1,39 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
- ~ Copyright (C) 2019 The Android Open Source Project
- ~
- ~ Licensed under the Apache License, Version 2.0 (the "License");
- ~ you may not use this file except in compliance with the License.
- ~ You may obtain a copy of the License at
- ~
- ~ http://www.apache.org/licenses/LICENSE-2.0
- ~
- ~ Unless required by applicable law or agreed to in writing, software
- ~ distributed under the License is distributed on an "AS IS" BASIS,
- ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- ~ See the License for the specific language governing permissions and
- ~ limitations under the License
- -->
-<LinearLayout
- xmlns:android="http://schemas.android.com/apk/res/android"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:orientation="horizontal"
- android:visibility="gone"
- android:padding="4dp"
- android:layout_marginStart="10dp"
- android:gravity="center"
- android:background="@drawable/media_seamless_background">
- <ImageView
- android:layout_width="?attr/notificationHeaderIconSize"
- android:layout_height="?attr/notificationHeaderIconSize"
- android:src="@drawable/ic_media_seamless"
- android:id="@+id/media_seamless_image" />
- <TextView
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:textAppearance="?attr/notificationHeaderTextAppearance"
- android:text="@string/ext_media_seamless_action"
- android:id="@+id/media_seamless_text"
- android:paddingEnd="2dp" />
-</LinearLayout> \ No newline at end of file
diff --git a/core/res/res/layout/notification_template_header.xml b/core/res/res/layout/notification_template_header.xml
index 9a1b592c895a..88493c9505ed 100644
--- a/core/res/res/layout/notification_template_header.xml
+++ b/core/res/res/layout/notification_template_header.xml
@@ -160,9 +160,5 @@
android:visibility="gone"
android:contentDescription="@string/notification_work_profile_content_description"
/>
- <include
- layout="@layout/notification_material_media_transfer_action"
- android:id="@+id/media_seamless"
- />
</NotificationHeaderView>
diff --git a/core/res/res/values-af/strings.xml b/core/res/res/values-af/strings.xml
index 20ebbd816fe7..bd81519e93b3 100644
--- a/core/res/res/values-af/strings.xml
+++ b/core/res/res/values-af/strings.xml
@@ -1654,8 +1654,6 @@
<string name="leave_accessibility_shortcut_on" msgid="6543362062336990814">"Gebruik kortpad"</string>
<string name="color_inversion_feature_name" msgid="326050048927789012">"Kleuromkering"</string>
<string name="color_correction_feature_name" msgid="3655077237805422597">"Kleurkorreksie"</string>
- <!-- no translation found for reduce_bright_colors_feature_name (6722364385073799185) -->
- <skip />
<string name="accessibility_shortcut_enabling_service" msgid="5473495203759847687">"Het volumesleutels ingehou. <xliff:g id="SERVICE_NAME">%1$s</xliff:g> aangeskakel."</string>
<string name="accessibility_shortcut_disabling_service" msgid="8675244165062700619">"Het volumesleutels ingehou. <xliff:g id="SERVICE_NAME">%1$s</xliff:g> is afgeskakel"</string>
<string name="accessibility_shortcut_spoken_feedback" msgid="4228997042855695090">"Druk en hou albei volumesleutels drie sekondes lank om <xliff:g id="SERVICE_NAME">%1$s</xliff:g> te gebruik"</string>
diff --git a/core/res/res/values-am/strings.xml b/core/res/res/values-am/strings.xml
index d534758b34a8..0bbe23262c92 100644
--- a/core/res/res/values-am/strings.xml
+++ b/core/res/res/values-am/strings.xml
@@ -1654,8 +1654,6 @@
<string name="leave_accessibility_shortcut_on" msgid="6543362062336990814">"አቋራጭ ይጠቀሙ"</string>
<string name="color_inversion_feature_name" msgid="326050048927789012">"ተቃራኒ ቀለም"</string>
<string name="color_correction_feature_name" msgid="3655077237805422597">"የቀለም ማስተካከያ"</string>
- <!-- no translation found for reduce_bright_colors_feature_name (6722364385073799185) -->
- <skip />
<string name="accessibility_shortcut_enabling_service" msgid="5473495203759847687">"የድምፅ ቁልፎችን ይዟል። <xliff:g id="SERVICE_NAME">%1$s</xliff:g> በርቷል።"</string>
<string name="accessibility_shortcut_disabling_service" msgid="8675244165062700619">"የድምፅ ቁልፎችን ይዟል። <xliff:g id="SERVICE_NAME">%1$s</xliff:g> ጠፍተዋል።"</string>
<string name="accessibility_shortcut_spoken_feedback" msgid="4228997042855695090">"<xliff:g id="SERVICE_NAME">%1$s</xliff:g>ን ለመጠቀም ለሦስት ሰከንዶች ሁለቱንም የድምፅ ቁልፎች ተጭነው ይያዙ"</string>
diff --git a/core/res/res/values-ar/strings.xml b/core/res/res/values-ar/strings.xml
index 86ed7378d679..8868fb67ccc8 100644
--- a/core/res/res/values-ar/strings.xml
+++ b/core/res/res/values-ar/strings.xml
@@ -1742,8 +1742,6 @@
<string name="leave_accessibility_shortcut_on" msgid="6543362062336990814">"استخدام الاختصار"</string>
<string name="color_inversion_feature_name" msgid="326050048927789012">"قلب الألوان"</string>
<string name="color_correction_feature_name" msgid="3655077237805422597">"تصحيح الألوان"</string>
- <!-- no translation found for reduce_bright_colors_feature_name (6722364385073799185) -->
- <skip />
<string name="accessibility_shortcut_enabling_service" msgid="5473495203759847687">"تم الضغط مع الاستمرار على مفتاحَي التحكّم في مستوى الصوت. تم تفعيل <xliff:g id="SERVICE_NAME">%1$s</xliff:g>."</string>
<string name="accessibility_shortcut_disabling_service" msgid="8675244165062700619">"تم الضغط مع الاستمرار على مفتاحَي التحكّم في مستوى الصوت. تم إيقاف <xliff:g id="SERVICE_NAME">%1$s</xliff:g>."</string>
<string name="accessibility_shortcut_spoken_feedback" msgid="4228997042855695090">"اضغط مع الاستمرار على مفتاحي مستوى الصوت لمدة 3 ثوانٍ لاستخدام <xliff:g id="SERVICE_NAME">%1$s</xliff:g>."</string>
diff --git a/core/res/res/values-as/strings.xml b/core/res/res/values-as/strings.xml
index da99576418ba..619666b9bf0d 100644
--- a/core/res/res/values-as/strings.xml
+++ b/core/res/res/values-as/strings.xml
@@ -1654,8 +1654,6 @@
<string name="leave_accessibility_shortcut_on" msgid="6543362062336990814">"শ্বৰ্টকাট ব্যৱহাৰ কৰক"</string>
<string name="color_inversion_feature_name" msgid="326050048927789012">"ৰং বিপৰীতকৰণ"</string>
<string name="color_correction_feature_name" msgid="3655077237805422597">"ৰং শুধৰণী"</string>
- <!-- no translation found for reduce_bright_colors_feature_name (6722364385073799185) -->
- <skip />
<string name="accessibility_shortcut_enabling_service" msgid="5473495203759847687">"ভলিউম কীসমূহ ধৰি ৰাখক। <xliff:g id="SERVICE_NAME">%1$s</xliff:g> অন কৰা হ\'ল।"</string>
<string name="accessibility_shortcut_disabling_service" msgid="8675244165062700619">"ভলিউম কী ধৰি ৰাখিছিল। <xliff:g id="SERVICE_NAME">%1$s</xliff:g> অফ কৰা হ\'ল।"</string>
<string name="accessibility_shortcut_spoken_feedback" msgid="4228997042855695090">"<xliff:g id="SERVICE_NAME">%1$s</xliff:g> ব্যৱহাৰ কৰিবলৈ দুয়োটা ভলিউম বুটাম তিনি ছেকেণ্ডৰ বাবে হেঁচি ৰাখক"</string>
diff --git a/core/res/res/values-az/strings.xml b/core/res/res/values-az/strings.xml
index bc3f14651e21..ed708cce9856 100644
--- a/core/res/res/values-az/strings.xml
+++ b/core/res/res/values-az/strings.xml
@@ -1654,8 +1654,6 @@
<string name="leave_accessibility_shortcut_on" msgid="6543362062336990814">"Qısayol İstifadə edin"</string>
<string name="color_inversion_feature_name" msgid="326050048927789012">"Rəng İnversiyası"</string>
<string name="color_correction_feature_name" msgid="3655077237805422597">"Rəng korreksiyası"</string>
- <!-- no translation found for reduce_bright_colors_feature_name (6722364385073799185) -->
- <skip />
<string name="accessibility_shortcut_enabling_service" msgid="5473495203759847687">"Səs səviyyəsi düymələrinə basıb saxlayın. <xliff:g id="SERVICE_NAME">%1$s</xliff:g> aktiv edildi."</string>
<string name="accessibility_shortcut_disabling_service" msgid="8675244165062700619">"Səs səviyyəsi düymələrinə basılaraq saxlanıb. <xliff:g id="SERVICE_NAME">%1$s</xliff:g> deaktiv edilib."</string>
<string name="accessibility_shortcut_spoken_feedback" msgid="4228997042855695090">"<xliff:g id="SERVICE_NAME">%1$s</xliff:g> istifadə etmək üçün hər iki səs düyməsini üç saniyə basıb saxlayın"</string>
diff --git a/core/res/res/values-b+sr+Latn/strings.xml b/core/res/res/values-b+sr+Latn/strings.xml
index f6dfe6ed2e36..0b215456b150 100644
--- a/core/res/res/values-b+sr+Latn/strings.xml
+++ b/core/res/res/values-b+sr+Latn/strings.xml
@@ -1676,8 +1676,6 @@
<string name="leave_accessibility_shortcut_on" msgid="6543362062336990814">"Koristi prečicu"</string>
<string name="color_inversion_feature_name" msgid="326050048927789012">"Inverzija boja"</string>
<string name="color_correction_feature_name" msgid="3655077237805422597">"Korekcija boja"</string>
- <!-- no translation found for reduce_bright_colors_feature_name (6722364385073799185) -->
- <skip />
<string name="accessibility_shortcut_enabling_service" msgid="5473495203759847687">"Držali ste tastere za jačinu zvuka. Usluga <xliff:g id="SERVICE_NAME">%1$s</xliff:g> je uključena."</string>
<string name="accessibility_shortcut_disabling_service" msgid="8675244165062700619">"Držali ste tastere za jačinu zvuka. Usluga <xliff:g id="SERVICE_NAME">%1$s</xliff:g> je isključena."</string>
<string name="accessibility_shortcut_spoken_feedback" msgid="4228997042855695090">"Pritisnite i zadržite oba tastera za jačinu zvuka tri sekunde da biste koristili <xliff:g id="SERVICE_NAME">%1$s</xliff:g>"</string>
diff --git a/core/res/res/values-be/strings.xml b/core/res/res/values-be/strings.xml
index f761cbabf389..6a0ad98d759d 100644
--- a/core/res/res/values-be/strings.xml
+++ b/core/res/res/values-be/strings.xml
@@ -1698,8 +1698,6 @@
<string name="leave_accessibility_shortcut_on" msgid="6543362062336990814">"Выкарыстоўваць камбінацыю хуткага доступу"</string>
<string name="color_inversion_feature_name" msgid="326050048927789012">"Інверсія колеру"</string>
<string name="color_correction_feature_name" msgid="3655077237805422597">"Карэкцыя колеру"</string>
- <!-- no translation found for reduce_bright_colors_feature_name (6722364385073799185) -->
- <skip />
<string name="accessibility_shortcut_enabling_service" msgid="5473495203759847687">"Клавішы гучнасці ўтрымліваліся націснутымі. Уключана служба \"<xliff:g id="SERVICE_NAME">%1$s</xliff:g>\"."</string>
<string name="accessibility_shortcut_disabling_service" msgid="8675244165062700619">"Клавішы гучнасці ўтрымліваліся націснутымі. Служба \"<xliff:g id="SERVICE_NAME">%1$s</xliff:g>\" выключана."</string>
<string name="accessibility_shortcut_spoken_feedback" msgid="4228997042855695090">"Каб карыстацца сэрвісам \"<xliff:g id="SERVICE_NAME">%1$s</xliff:g>\", націсніце і ўтрымлівайце на працягу трох секунд абедзве клавішы гучнасці"</string>
diff --git a/core/res/res/values-bg/strings.xml b/core/res/res/values-bg/strings.xml
index 56ca128d5a04..cdd0ec04df0f 100644
--- a/core/res/res/values-bg/strings.xml
+++ b/core/res/res/values-bg/strings.xml
@@ -1654,7 +1654,6 @@
<string name="leave_accessibility_shortcut_on" msgid="6543362062336990814">"Използване на пряк път"</string>
<string name="color_inversion_feature_name" msgid="326050048927789012">"Инвертиране на цветовете"</string>
<string name="color_correction_feature_name" msgid="3655077237805422597">"Коригиране на цветовете"</string>
- <string name="reduce_bright_colors_feature_name" msgid="6722364385073799185">"Намаляване на ярките цветове"</string>
<string name="accessibility_shortcut_enabling_service" msgid="5473495203759847687">"Задържахте бутоните за силата на звука. Услугата <xliff:g id="SERVICE_NAME">%1$s</xliff:g> е включена."</string>
<string name="accessibility_shortcut_disabling_service" msgid="8675244165062700619">"Задържахте бутоните за силата на звука. Услугата <xliff:g id="SERVICE_NAME">%1$s</xliff:g> е изключена."</string>
<string name="accessibility_shortcut_spoken_feedback" msgid="4228997042855695090">"За да използвате <xliff:g id="SERVICE_NAME">%1$s</xliff:g>, натиснете двата бутона за силата на звука и ги задръжте за 3 секунди"</string>
diff --git a/core/res/res/values-bn/strings.xml b/core/res/res/values-bn/strings.xml
index ce0838c173fb..779fd3ef67e1 100644
--- a/core/res/res/values-bn/strings.xml
+++ b/core/res/res/values-bn/strings.xml
@@ -1654,8 +1654,6 @@
<string name="leave_accessibility_shortcut_on" msgid="6543362062336990814">"শর্টকাট ব্যবহার করুন"</string>
<string name="color_inversion_feature_name" msgid="326050048927789012">"রঙ উল্টানো"</string>
<string name="color_correction_feature_name" msgid="3655077237805422597">"রঙ সংশোধন"</string>
- <!-- no translation found for reduce_bright_colors_feature_name (6722364385073799185) -->
- <skip />
<string name="accessibility_shortcut_enabling_service" msgid="5473495203759847687">"ভলিউম কী ধরে ছিলেন। <xliff:g id="SERVICE_NAME">%1$s</xliff:g> চালু করা হয়েছে।"</string>
<string name="accessibility_shortcut_disabling_service" msgid="8675244165062700619">"ভলিউম কী ধরে ছিলেন। <xliff:g id="SERVICE_NAME">%1$s</xliff:g> বন্ধ করা হয়েছে।"</string>
<string name="accessibility_shortcut_spoken_feedback" msgid="4228997042855695090">"<xliff:g id="SERVICE_NAME">%1$s</xliff:g> ব্যবহার করতে ভলিউম কী বোতাম ৩ সেকেন্ডের জন্য চেপে ধরে রাখুন"</string>
diff --git a/core/res/res/values-bs/strings.xml b/core/res/res/values-bs/strings.xml
index 95e688233842..fab6c912d3fe 100644
--- a/core/res/res/values-bs/strings.xml
+++ b/core/res/res/values-bs/strings.xml
@@ -1676,8 +1676,6 @@
<string name="leave_accessibility_shortcut_on" msgid="6543362062336990814">"Koristi prečicu"</string>
<string name="color_inversion_feature_name" msgid="326050048927789012">"Inverzija boja"</string>
<string name="color_correction_feature_name" msgid="3655077237805422597">"Ispravka boja"</string>
- <!-- no translation found for reduce_bright_colors_feature_name (6722364385073799185) -->
- <skip />
<string name="accessibility_shortcut_enabling_service" msgid="5473495203759847687">"Držali ste tipke za jačinu zvuka. Usluga <xliff:g id="SERVICE_NAME">%1$s</xliff:g> je uključena."</string>
<string name="accessibility_shortcut_disabling_service" msgid="8675244165062700619">"Držali ste tipke za jačinu zvuka. Usluga <xliff:g id="SERVICE_NAME">%1$s</xliff:g> je isključena."</string>
<string name="accessibility_shortcut_spoken_feedback" msgid="4228997042855695090">"Pritisnite obje tipke za podešavanje jačine zvuka i držite ih pritisnutim tri sekunde da koristite uslugu <xliff:g id="SERVICE_NAME">%1$s</xliff:g>"</string>
diff --git a/core/res/res/values-ca/strings.xml b/core/res/res/values-ca/strings.xml
index d115bde9d120..96c6b6a85736 100644
--- a/core/res/res/values-ca/strings.xml
+++ b/core/res/res/values-ca/strings.xml
@@ -1654,8 +1654,6 @@
<string name="leave_accessibility_shortcut_on" msgid="6543362062336990814">"Utilitza la drecera"</string>
<string name="color_inversion_feature_name" msgid="326050048927789012">"Inversió de colors"</string>
<string name="color_correction_feature_name" msgid="3655077237805422597">"Correcció de color"</string>
- <!-- no translation found for reduce_bright_colors_feature_name (6722364385073799185) -->
- <skip />
<string name="accessibility_shortcut_enabling_service" msgid="5473495203759847687">"S\'han mantingut premudes les tecles de volum. S\'ha activat <xliff:g id="SERVICE_NAME">%1$s</xliff:g>."</string>
<string name="accessibility_shortcut_disabling_service" msgid="8675244165062700619">"S\'han mantingut premudes les tecles de volum. S\'ha desactivat <xliff:g id="SERVICE_NAME">%1$s</xliff:g>."</string>
<string name="accessibility_shortcut_spoken_feedback" msgid="4228997042855695090">"Mantén premudes les dues tecles de volum durant 3 segons per fer servir <xliff:g id="SERVICE_NAME">%1$s</xliff:g>"</string>
diff --git a/core/res/res/values-cs/strings.xml b/core/res/res/values-cs/strings.xml
index 60fe94cbb314..9a5f069c8afb 100644
--- a/core/res/res/values-cs/strings.xml
+++ b/core/res/res/values-cs/strings.xml
@@ -1698,8 +1698,6 @@
<string name="leave_accessibility_shortcut_on" msgid="6543362062336990814">"Použít zkratku"</string>
<string name="color_inversion_feature_name" msgid="326050048927789012">"Převrácení barev"</string>
<string name="color_correction_feature_name" msgid="3655077237805422597">"Oprava barev"</string>
- <!-- no translation found for reduce_bright_colors_feature_name (6722364385073799185) -->
- <skip />
<string name="accessibility_shortcut_enabling_service" msgid="5473495203759847687">"Byla podržena tlačítka hlasitosti. Služba <xliff:g id="SERVICE_NAME">%1$s</xliff:g> je zapnutá."</string>
<string name="accessibility_shortcut_disabling_service" msgid="8675244165062700619">"Byla podržena tlačítka hlasitosti. Služba <xliff:g id="SERVICE_NAME">%1$s</xliff:g> byla vypnuta."</string>
<string name="accessibility_shortcut_spoken_feedback" msgid="4228997042855695090">"Chcete-li používat službu <xliff:g id="SERVICE_NAME">%1$s</xliff:g>, tři sekundy podržte stisknutá obě tlačítka hlasitosti"</string>
diff --git a/core/res/res/values-da/strings.xml b/core/res/res/values-da/strings.xml
index a8641d36f6bb..480e87cfff2a 100644
--- a/core/res/res/values-da/strings.xml
+++ b/core/res/res/values-da/strings.xml
@@ -1654,8 +1654,6 @@
<string name="leave_accessibility_shortcut_on" msgid="6543362062336990814">"Brug genvej"</string>
<string name="color_inversion_feature_name" msgid="326050048927789012">"Ombytning af farver"</string>
<string name="color_correction_feature_name" msgid="3655077237805422597">"Korriger farve"</string>
- <!-- no translation found for reduce_bright_colors_feature_name (6722364385073799185) -->
- <skip />
<string name="accessibility_shortcut_enabling_service" msgid="5473495203759847687">"Lydstyrkeknapperne blev holdt nede. <xliff:g id="SERVICE_NAME">%1$s</xliff:g> er aktiveret."</string>
<string name="accessibility_shortcut_disabling_service" msgid="8675244165062700619">"Lydstyrkeknapperne blev holdt nede. <xliff:g id="SERVICE_NAME">%1$s</xliff:g> er deaktiveret."</string>
<string name="accessibility_shortcut_spoken_feedback" msgid="4228997042855695090">"Hold begge lydstyrkeknapper nede i tre sekunder for at bruge <xliff:g id="SERVICE_NAME">%1$s</xliff:g>"</string>
diff --git a/core/res/res/values-de/strings.xml b/core/res/res/values-de/strings.xml
index 68749c6ecb96..ac9a597a71b4 100644
--- a/core/res/res/values-de/strings.xml
+++ b/core/res/res/values-de/strings.xml
@@ -1654,8 +1654,6 @@
<string name="leave_accessibility_shortcut_on" msgid="6543362062336990814">"Verknüpfung verwenden"</string>
<string name="color_inversion_feature_name" msgid="326050048927789012">"Farbumkehr"</string>
<string name="color_correction_feature_name" msgid="3655077237805422597">"Farbkorrektur"</string>
- <!-- no translation found for reduce_bright_colors_feature_name (6722364385073799185) -->
- <skip />
<string name="accessibility_shortcut_enabling_service" msgid="5473495203759847687">"Lautstärketasten wurden gedrückt gehalten. <xliff:g id="SERVICE_NAME">%1$s</xliff:g> ist aktiviert."</string>
<string name="accessibility_shortcut_disabling_service" msgid="8675244165062700619">"Lautstärketasten wurden gedrückt gehalten. <xliff:g id="SERVICE_NAME">%1$s</xliff:g> ist deaktiviert."</string>
<string name="accessibility_shortcut_spoken_feedback" msgid="4228997042855695090">"Halten Sie beide Lautstärketasten drei Sekunden lang gedrückt, um <xliff:g id="SERVICE_NAME">%1$s</xliff:g> zu verwenden"</string>
diff --git a/core/res/res/values-el/strings.xml b/core/res/res/values-el/strings.xml
index 88edddf37413..6f03f80e04cc 100644
--- a/core/res/res/values-el/strings.xml
+++ b/core/res/res/values-el/strings.xml
@@ -1654,8 +1654,6 @@
<string name="leave_accessibility_shortcut_on" msgid="6543362062336990814">"Χρήση συντόμευσης"</string>
<string name="color_inversion_feature_name" msgid="326050048927789012">"Αντιστροφή χρωμάτων"</string>
<string name="color_correction_feature_name" msgid="3655077237805422597">"Διόρθωση χρωμάτων"</string>
- <!-- no translation found for reduce_bright_colors_feature_name (6722364385073799185) -->
- <skip />
<string name="accessibility_shortcut_enabling_service" msgid="5473495203759847687">"Τα πλήκτρα έντασης είναι πατημένα. <xliff:g id="SERVICE_NAME">%1$s</xliff:g> ενεργοποιήθηκε."</string>
<string name="accessibility_shortcut_disabling_service" msgid="8675244165062700619">"Τα πλήκτρα έντασης είναι πατημένα. <xliff:g id="SERVICE_NAME">%1$s</xliff:g>: απενεργοποιημένο"</string>
<string name="accessibility_shortcut_spoken_feedback" msgid="4228997042855695090">"Πατήστε παρατεταμένα και τα δύο κουμπιά έντασης ήχου για τρία δευτερόλεπτα, ώστε να χρησιμοποιήσετε την υπηρεσία <xliff:g id="SERVICE_NAME">%1$s</xliff:g>"</string>
diff --git a/core/res/res/values-en-rAU/strings.xml b/core/res/res/values-en-rAU/strings.xml
index d439a7f6f4ea..fac2f2223c99 100644
--- a/core/res/res/values-en-rAU/strings.xml
+++ b/core/res/res/values-en-rAU/strings.xml
@@ -1654,7 +1654,6 @@
<string name="leave_accessibility_shortcut_on" msgid="6543362062336990814">"Use Shortcut"</string>
<string name="color_inversion_feature_name" msgid="326050048927789012">"Colour Inversion"</string>
<string name="color_correction_feature_name" msgid="3655077237805422597">"Colour correction"</string>
- <string name="reduce_bright_colors_feature_name" msgid="6722364385073799185">"Reduce bright colours"</string>
<string name="accessibility_shortcut_enabling_service" msgid="5473495203759847687">"Held volume keys. <xliff:g id="SERVICE_NAME">%1$s</xliff:g> turned on."</string>
<string name="accessibility_shortcut_disabling_service" msgid="8675244165062700619">"Held volume keys. <xliff:g id="SERVICE_NAME">%1$s</xliff:g> turned off."</string>
<string name="accessibility_shortcut_spoken_feedback" msgid="4228997042855695090">"Press and hold both volume keys for three seconds to use <xliff:g id="SERVICE_NAME">%1$s</xliff:g>"</string>
diff --git a/core/res/res/values-en-rCA/strings.xml b/core/res/res/values-en-rCA/strings.xml
index 8052ced1ad29..8497658c52bb 100644
--- a/core/res/res/values-en-rCA/strings.xml
+++ b/core/res/res/values-en-rCA/strings.xml
@@ -1654,7 +1654,6 @@
<string name="leave_accessibility_shortcut_on" msgid="6543362062336990814">"Use Shortcut"</string>
<string name="color_inversion_feature_name" msgid="326050048927789012">"Colour inversion"</string>
<string name="color_correction_feature_name" msgid="3655077237805422597">"Colour correction"</string>
- <string name="reduce_bright_colors_feature_name" msgid="6722364385073799185">"Reduce bright colours"</string>
<string name="accessibility_shortcut_enabling_service" msgid="5473495203759847687">"Held volume keys. <xliff:g id="SERVICE_NAME">%1$s</xliff:g> turned on."</string>
<string name="accessibility_shortcut_disabling_service" msgid="8675244165062700619">"Held volume keys. <xliff:g id="SERVICE_NAME">%1$s</xliff:g> turned off."</string>
<string name="accessibility_shortcut_spoken_feedback" msgid="4228997042855695090">"Press and hold both volume keys for three seconds to use <xliff:g id="SERVICE_NAME">%1$s</xliff:g>"</string>
diff --git a/core/res/res/values-en-rGB/strings.xml b/core/res/res/values-en-rGB/strings.xml
index 45e15c9d22a1..12881e7e70f1 100644
--- a/core/res/res/values-en-rGB/strings.xml
+++ b/core/res/res/values-en-rGB/strings.xml
@@ -1654,7 +1654,6 @@
<string name="leave_accessibility_shortcut_on" msgid="6543362062336990814">"Use Shortcut"</string>
<string name="color_inversion_feature_name" msgid="326050048927789012">"Colour Inversion"</string>
<string name="color_correction_feature_name" msgid="3655077237805422597">"Colour correction"</string>
- <string name="reduce_bright_colors_feature_name" msgid="6722364385073799185">"Reduce bright colours"</string>
<string name="accessibility_shortcut_enabling_service" msgid="5473495203759847687">"Held volume keys. <xliff:g id="SERVICE_NAME">%1$s</xliff:g> turned on."</string>
<string name="accessibility_shortcut_disabling_service" msgid="8675244165062700619">"Held volume keys. <xliff:g id="SERVICE_NAME">%1$s</xliff:g> turned off."</string>
<string name="accessibility_shortcut_spoken_feedback" msgid="4228997042855695090">"Press and hold both volume keys for three seconds to use <xliff:g id="SERVICE_NAME">%1$s</xliff:g>"</string>
diff --git a/core/res/res/values-en-rIN/strings.xml b/core/res/res/values-en-rIN/strings.xml
index 952792147c1a..cb2eb7ab17ca 100644
--- a/core/res/res/values-en-rIN/strings.xml
+++ b/core/res/res/values-en-rIN/strings.xml
@@ -1654,7 +1654,6 @@
<string name="leave_accessibility_shortcut_on" msgid="6543362062336990814">"Use Shortcut"</string>
<string name="color_inversion_feature_name" msgid="326050048927789012">"Colour Inversion"</string>
<string name="color_correction_feature_name" msgid="3655077237805422597">"Color correction"</string>
- <string name="reduce_bright_colors_feature_name" msgid="6722364385073799185">"Reduce bright colours"</string>
<string name="accessibility_shortcut_enabling_service" msgid="5473495203759847687">"Held volume keys. <xliff:g id="SERVICE_NAME">%1$s</xliff:g> turned on."</string>
<string name="accessibility_shortcut_disabling_service" msgid="8675244165062700619">"Held volume keys. <xliff:g id="SERVICE_NAME">%1$s</xliff:g> turned off."</string>
<string name="accessibility_shortcut_spoken_feedback" msgid="4228997042855695090">"Press and hold both volume keys for three seconds to use <xliff:g id="SERVICE_NAME">%1$s</xliff:g>"</string>
diff --git a/core/res/res/values-en-rXC/strings.xml b/core/res/res/values-en-rXC/strings.xml
index 0bb10572ddec..5750e50476b8 100644
--- a/core/res/res/values-en-rXC/strings.xml
+++ b/core/res/res/values-en-rXC/strings.xml
@@ -1654,7 +1654,6 @@
<string name="leave_accessibility_shortcut_on" msgid="6543362062336990814">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‏‏‎‏‎‏‏‎‎‏‏‏‎‏‎‏‏‎‎‎‏‎‎‏‎‎‎‎‎‏‎‏‎‎‎‏‎‎‏‎‏‏‏‎‏‎‎‎‏‏‏‏‎‎‏‎‏‏‏‏‎‎Use Shortcut‎‏‎‎‏‎"</string>
<string name="color_inversion_feature_name" msgid="326050048927789012">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‎‏‏‏‎‎‏‎‎‎‎‏‏‎‎‏‎‏‏‏‎‎‏‏‎‎‏‎‏‎‏‏‎‎‎‎‎‏‎‏‎‏‎‏‏‎‏‏‏‎‏‏‏‏‏‏‎‏‎‏‎‎‎Color Inversion‎‏‎‎‏‎"</string>
<string name="color_correction_feature_name" msgid="3655077237805422597">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‏‎‎‏‎‏‎‏‏‏‎‎‏‎‏‏‏‎‎‎‏‎‏‏‎‎‎‎‏‏‏‏‎‎‎‏‎‎‎‎‎‎‎‏‎‎‎‎‏‏‎‎‎‎‎‎‎‎‏‎‏‎Color Correction‎‏‎‎‏‎"</string>
- <string name="reduce_bright_colors_feature_name" msgid="6722364385073799185">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‏‏‏‎‏‎‏‎‎‏‎‏‎‏‎‏‎‎‎‏‎‏‏‎‎‏‎‏‎‏‎‏‎‎‏‏‏‎‎‎‎‏‏‏‏‏‎‏‎‎‎‎‎‎‎‎‏‎‎‎‏‎Reduce Bright Colors‎‏‎‎‏‎"</string>
<string name="accessibility_shortcut_enabling_service" msgid="5473495203759847687">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‎‏‎‏‏‏‏‏‏‎‏‎‏‏‏‎‎‎‎‏‎‏‏‏‎‎‎‏‏‎‏‎‏‎‎‏‏‏‏‏‎‏‎‎‎‏‏‏‏‏‎‎‏‎‎‎‎‎‏‏‏‎Held volume keys. ‎‏‎‎‏‏‎<xliff:g id="SERVICE_NAME">%1$s</xliff:g>‎‏‎‎‏‏‏‎ turned on.‎‏‎‎‏‎"</string>
<string name="accessibility_shortcut_disabling_service" msgid="8675244165062700619">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‏‏‎‎‎‎‏‏‎‎‏‎‎‏‎‏‎‏‎‎‎‏‎‎‏‏‎‏‎‏‏‎‎‏‏‏‎‎‏‎‏‎‏‏‏‏‎‏‎‏‏‏‎‎‏‎‎‏‎‏‏‎Held volume keys. ‎‏‎‎‏‏‎<xliff:g id="SERVICE_NAME">%1$s</xliff:g>‎‏‎‎‏‏‏‎ turned off.‎‏‎‎‏‎"</string>
<string name="accessibility_shortcut_spoken_feedback" msgid="4228997042855695090">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‏‏‎‏‎‏‎‏‏‎‎‎‎‎‏‏‎‏‎‏‎‎‏‏‎‎‏‏‏‎‏‏‏‏‏‏‏‏‎‎‏‎‏‏‏‎‏‎‏‎‎‏‎‏‏‏‏‎‎‏‎‎Press and hold both volume keys for three seconds to use ‎‏‎‎‏‏‎<xliff:g id="SERVICE_NAME">%1$s</xliff:g>‎‏‎‎‏‏‏‎‎‏‎‎‏‎"</string>
diff --git a/core/res/res/values-es-rUS/strings.xml b/core/res/res/values-es-rUS/strings.xml
index 85e5b96928e3..8e7d1a33b98d 100644
--- a/core/res/res/values-es-rUS/strings.xml
+++ b/core/res/res/values-es-rUS/strings.xml
@@ -1654,8 +1654,6 @@
<string name="leave_accessibility_shortcut_on" msgid="6543362062336990814">"Usar acceso directo"</string>
<string name="color_inversion_feature_name" msgid="326050048927789012">"Inversión de color"</string>
<string name="color_correction_feature_name" msgid="3655077237805422597">"Corrección de color"</string>
- <!-- no translation found for reduce_bright_colors_feature_name (6722364385073799185) -->
- <skip />
<string name="accessibility_shortcut_enabling_service" msgid="5473495203759847687">"Como mantuviste presionadas las teclas de volumen, se activó <xliff:g id="SERVICE_NAME">%1$s</xliff:g>."</string>
<string name="accessibility_shortcut_disabling_service" msgid="8675244165062700619">"Se presionaron las teclas de volumen. Se desactivó <xliff:g id="SERVICE_NAME">%1$s</xliff:g>."</string>
<string name="accessibility_shortcut_spoken_feedback" msgid="4228997042855695090">"Mantén presionadas ambas teclas de volumen durante tres segundos para usar <xliff:g id="SERVICE_NAME">%1$s</xliff:g>"</string>
diff --git a/core/res/res/values-es/strings.xml b/core/res/res/values-es/strings.xml
index 39e04bd78917..b9f0f584dc82 100644
--- a/core/res/res/values-es/strings.xml
+++ b/core/res/res/values-es/strings.xml
@@ -1654,8 +1654,6 @@
<string name="leave_accessibility_shortcut_on" msgid="6543362062336990814">"Utilizar acceso directo"</string>
<string name="color_inversion_feature_name" msgid="326050048927789012">"Inversión de color"</string>
<string name="color_correction_feature_name" msgid="3655077237805422597">"Corrección de color"</string>
- <!-- no translation found for reduce_bright_colors_feature_name (6722364385073799185) -->
- <skip />
<string name="accessibility_shortcut_enabling_service" msgid="5473495203759847687">"Al mantener pulsadas las teclas de volumen, se ha activado <xliff:g id="SERVICE_NAME">%1$s</xliff:g>."</string>
<string name="accessibility_shortcut_disabling_service" msgid="8675244165062700619">"Se han mantenido pulsadas las teclas de volumen. Se ha desactivado <xliff:g id="SERVICE_NAME">%1$s</xliff:g>."</string>
<string name="accessibility_shortcut_spoken_feedback" msgid="4228997042855695090">"Para utilizar <xliff:g id="SERVICE_NAME">%1$s</xliff:g>, mantén pulsadas ambas teclas de volumen durante 3 segundos"</string>
diff --git a/core/res/res/values-et/strings.xml b/core/res/res/values-et/strings.xml
index 7883db30d476..d825429032bb 100644
--- a/core/res/res/values-et/strings.xml
+++ b/core/res/res/values-et/strings.xml
@@ -1654,8 +1654,6 @@
<string name="leave_accessibility_shortcut_on" msgid="6543362062336990814">"Kasuta otseteed"</string>
<string name="color_inversion_feature_name" msgid="326050048927789012">"Värvide ümberpööramine"</string>
<string name="color_correction_feature_name" msgid="3655077237805422597">"Värvide korrigeerimine"</string>
- <!-- no translation found for reduce_bright_colors_feature_name (6722364385073799185) -->
- <skip />
<string name="accessibility_shortcut_enabling_service" msgid="5473495203759847687">"Helitugevuse klahve hoiti all. <xliff:g id="SERVICE_NAME">%1$s</xliff:g> lülitati sisse."</string>
<string name="accessibility_shortcut_disabling_service" msgid="8675244165062700619">"Helitugevuse klahve hoiti all. <xliff:g id="SERVICE_NAME">%1$s</xliff:g> lülitati välja."</string>
<string name="accessibility_shortcut_spoken_feedback" msgid="4228997042855695090">"Teenuse <xliff:g id="SERVICE_NAME">%1$s</xliff:g> kasutamiseks hoidke kolm sekundit all mõlemat helitugevuse klahvi"</string>
diff --git a/core/res/res/values-eu/strings.xml b/core/res/res/values-eu/strings.xml
index 4b4414b78bb9..05d40509e996 100644
--- a/core/res/res/values-eu/strings.xml
+++ b/core/res/res/values-eu/strings.xml
@@ -1654,8 +1654,6 @@
<string name="leave_accessibility_shortcut_on" msgid="6543362062336990814">"Erabili lasterbidea"</string>
<string name="color_inversion_feature_name" msgid="326050048927789012">"Koloreen alderantzikatzea"</string>
<string name="color_correction_feature_name" msgid="3655077237805422597">"Koloreen zuzenketa"</string>
- <!-- no translation found for reduce_bright_colors_feature_name (6722364385073799185) -->
- <skip />
<string name="accessibility_shortcut_enabling_service" msgid="5473495203759847687">"Bolumen-botoiak sakatuta eduki direnez, <xliff:g id="SERVICE_NAME">%1$s</xliff:g> aktibatu egin da."</string>
<string name="accessibility_shortcut_disabling_service" msgid="8675244165062700619">"Bolumen-botoiak sakatuta eduki direnez, <xliff:g id="SERVICE_NAME">%1$s</xliff:g> desaktibatu egin da."</string>
<string name="accessibility_shortcut_spoken_feedback" msgid="4228997042855695090">"<xliff:g id="SERVICE_NAME">%1$s</xliff:g> erabiltzeko, eduki sakatuta bi bolumen-botoiak hiru segundoz"</string>
diff --git a/core/res/res/values-fa/strings.xml b/core/res/res/values-fa/strings.xml
index 414adddc8aa8..21465542092f 100644
--- a/core/res/res/values-fa/strings.xml
+++ b/core/res/res/values-fa/strings.xml
@@ -1654,8 +1654,6 @@
<string name="leave_accessibility_shortcut_on" msgid="6543362062336990814">"استفاده از میان‌بر"</string>
<string name="color_inversion_feature_name" msgid="326050048927789012">"وارونگی رنگ"</string>
<string name="color_correction_feature_name" msgid="3655077237805422597">"تصحیح رنگ"</string>
- <!-- no translation found for reduce_bright_colors_feature_name (6722364385073799185) -->
- <skip />
<string name="accessibility_shortcut_enabling_service" msgid="5473495203759847687">"کلیدهای میزان صدا پایین نگه داشته شد. <xliff:g id="SERVICE_NAME">%1$s</xliff:g> روشن شد."</string>
<string name="accessibility_shortcut_disabling_service" msgid="8675244165062700619">"کلیدهای میزان صدا پایین نگه داشته شد. <xliff:g id="SERVICE_NAME">%1$s</xliff:g> خاموش شد."</string>
<string name="accessibility_shortcut_spoken_feedback" msgid="4228997042855695090">"برای استفاده از <xliff:g id="SERVICE_NAME">%1$s</xliff:g>، هر دو کلید صدا را فشار دهید و سه ثانیه نگه دارید"</string>
diff --git a/core/res/res/values-fi/strings.xml b/core/res/res/values-fi/strings.xml
index dc40a026d1f0..e7bcf4867203 100644
--- a/core/res/res/values-fi/strings.xml
+++ b/core/res/res/values-fi/strings.xml
@@ -1654,8 +1654,6 @@
<string name="leave_accessibility_shortcut_on" msgid="6543362062336990814">"Käytä pikanäppäintä"</string>
<string name="color_inversion_feature_name" msgid="326050048927789012">"Käänteiset värit"</string>
<string name="color_correction_feature_name" msgid="3655077237805422597">"Värinkorjaus"</string>
- <!-- no translation found for reduce_bright_colors_feature_name (6722364385073799185) -->
- <skip />
<string name="accessibility_shortcut_enabling_service" msgid="5473495203759847687">"Äänenvoimakkuuspainikkeita painettiin pitkään. <xliff:g id="SERVICE_NAME">%1$s</xliff:g> laitettiin päälle."</string>
<string name="accessibility_shortcut_disabling_service" msgid="8675244165062700619">"Äänenvoimakkuuspainikkeita painettiin pitkään. <xliff:g id="SERVICE_NAME">%1$s</xliff:g> laitettiin pois päältä."</string>
<string name="accessibility_shortcut_spoken_feedback" msgid="4228997042855695090">"Voit käyttää palvelua <xliff:g id="SERVICE_NAME">%1$s</xliff:g> painamalla molempia äänenvoimakkuuspainikkeita kolmen sekunnin ajan"</string>
diff --git a/core/res/res/values-fr-rCA/strings.xml b/core/res/res/values-fr-rCA/strings.xml
index 582c96628612..aad574946036 100644
--- a/core/res/res/values-fr-rCA/strings.xml
+++ b/core/res/res/values-fr-rCA/strings.xml
@@ -1654,8 +1654,6 @@
<string name="leave_accessibility_shortcut_on" msgid="6543362062336990814">"Utiliser le raccourci"</string>
<string name="color_inversion_feature_name" msgid="326050048927789012">"Inversion des couleurs"</string>
<string name="color_correction_feature_name" msgid="3655077237805422597">"Correction des couleurs"</string>
- <!-- no translation found for reduce_bright_colors_feature_name (6722364385073799185) -->
- <skip />
<string name="accessibility_shortcut_enabling_service" msgid="5473495203759847687">"Touches de volume maintenues enfoncées. <xliff:g id="SERVICE_NAME">%1$s</xliff:g> activé."</string>
<string name="accessibility_shortcut_disabling_service" msgid="8675244165062700619">"Touches de volume maintenues enfoncées. Service <xliff:g id="SERVICE_NAME">%1$s</xliff:g> désactivé."</string>
<string name="accessibility_shortcut_spoken_feedback" msgid="4228997042855695090">"Maintenez enfoncées les deux touches de volume pendant trois secondes pour utiliser <xliff:g id="SERVICE_NAME">%1$s</xliff:g>"</string>
diff --git a/core/res/res/values-fr/strings.xml b/core/res/res/values-fr/strings.xml
index 167249f77057..d2bdbbb6e360 100644
--- a/core/res/res/values-fr/strings.xml
+++ b/core/res/res/values-fr/strings.xml
@@ -1654,8 +1654,6 @@
<string name="leave_accessibility_shortcut_on" msgid="6543362062336990814">"Utiliser le raccourci"</string>
<string name="color_inversion_feature_name" msgid="326050048927789012">"Inversion des couleurs"</string>
<string name="color_correction_feature_name" msgid="3655077237805422597">"Correction des couleurs"</string>
- <!-- no translation found for reduce_bright_colors_feature_name (6722364385073799185) -->
- <skip />
<string name="accessibility_shortcut_enabling_service" msgid="5473495203759847687">"Touches de volume appuyées de manière prolongée. Service <xliff:g id="SERVICE_NAME">%1$s</xliff:g> activé."</string>
<string name="accessibility_shortcut_disabling_service" msgid="8675244165062700619">"Touches de volume appuyées de manière prolongée. Service <xliff:g id="SERVICE_NAME">%1$s</xliff:g> désactivé."</string>
<string name="accessibility_shortcut_spoken_feedback" msgid="4228997042855695090">"Appuyez de manière prolongée sur les deux touches de volume pendant trois secondes pour utiliser <xliff:g id="SERVICE_NAME">%1$s</xliff:g>"</string>
diff --git a/core/res/res/values-gl/strings.xml b/core/res/res/values-gl/strings.xml
index e78a0c833fac..79380d5398ca 100644
--- a/core/res/res/values-gl/strings.xml
+++ b/core/res/res/values-gl/strings.xml
@@ -1654,8 +1654,6 @@
<string name="leave_accessibility_shortcut_on" msgid="6543362062336990814">"Utilizar atallo"</string>
<string name="color_inversion_feature_name" msgid="326050048927789012">"Inversión de cor"</string>
<string name="color_correction_feature_name" msgid="3655077237805422597">"Corrección de cor"</string>
- <!-- no translation found for reduce_bright_colors_feature_name (6722364385073799185) -->
- <skip />
<string name="accessibility_shortcut_enabling_service" msgid="5473495203759847687">"Teclas de volume premidas. Activouse o servizo <xliff:g id="SERVICE_NAME">%1$s</xliff:g>."</string>
<string name="accessibility_shortcut_disabling_service" msgid="8675244165062700619">"Teclas de volume premidas. Desactivouse <xliff:g id="SERVICE_NAME">%1$s</xliff:g>."</string>
<string name="accessibility_shortcut_spoken_feedback" msgid="4228997042855695090">"Mantén premidas as teclas do volume durante tres segudos para usar <xliff:g id="SERVICE_NAME">%1$s</xliff:g>"</string>
diff --git a/core/res/res/values-gu/strings.xml b/core/res/res/values-gu/strings.xml
index e38096c41396..bf4d6c0b8a09 100644
--- a/core/res/res/values-gu/strings.xml
+++ b/core/res/res/values-gu/strings.xml
@@ -1654,8 +1654,6 @@
<string name="leave_accessibility_shortcut_on" msgid="6543362062336990814">"શૉર્ટકટનો ઉપયોગ કરો"</string>
<string name="color_inversion_feature_name" msgid="326050048927789012">"વિપરીત રંગમાં બદલવું"</string>
<string name="color_correction_feature_name" msgid="3655077237805422597">"રંગ સુધારણા"</string>
- <!-- no translation found for reduce_bright_colors_feature_name (6722364385073799185) -->
- <skip />
<string name="accessibility_shortcut_enabling_service" msgid="5473495203759847687">"વૉલ્યૂમ કી દબાવી રાખો. <xliff:g id="SERVICE_NAME">%1$s</xliff:g> ચાલુ કરી."</string>
<string name="accessibility_shortcut_disabling_service" msgid="8675244165062700619">"વૉલ્યૂમ કી દબાવી રાખો. <xliff:g id="SERVICE_NAME">%1$s</xliff:g> બંધ કરી."</string>
<string name="accessibility_shortcut_spoken_feedback" msgid="4228997042855695090">"<xliff:g id="SERVICE_NAME">%1$s</xliff:g>નો ઉપયોગ કરવા માટે બન્ને વૉલ્યૂમ કીને ત્રણ સેકન્ડ સુધી દબાવી રાખો"</string>
diff --git a/core/res/res/values-hi/strings.xml b/core/res/res/values-hi/strings.xml
index 59c2b2d03806..b867e9d04f7d 100644
--- a/core/res/res/values-hi/strings.xml
+++ b/core/res/res/values-hi/strings.xml
@@ -1654,8 +1654,6 @@
<string name="leave_accessibility_shortcut_on" msgid="6543362062336990814">"शॉर्टकट का उपयोग करें"</string>
<string name="color_inversion_feature_name" msgid="326050048927789012">"रंग बदलने की सुविधा"</string>
<string name="color_correction_feature_name" msgid="3655077237805422597">"रंग में सुधार करने की सुविधा"</string>
- <!-- no translation found for reduce_bright_colors_feature_name (6722364385073799185) -->
- <skip />
<string name="accessibility_shortcut_enabling_service" msgid="5473495203759847687">"आवाज़ कम-ज़्यादा करने वाले दोनों बटन दबाकर रखें. <xliff:g id="SERVICE_NAME">%1$s</xliff:g> को चालू कर दिया गया."</string>
<string name="accessibility_shortcut_disabling_service" msgid="8675244165062700619">"आवाज़ कम-ज़्यादा करने वाले दोनों बटन दबाकर रखें. <xliff:g id="SERVICE_NAME">%1$s</xliff:g> को बंद कर दिया गया."</string>
<string name="accessibility_shortcut_spoken_feedback" msgid="4228997042855695090">"<xliff:g id="SERVICE_NAME">%1$s</xliff:g> इस्तेमाल करने के लिए आवाज़ वाले दोनों बटन तीन सेकंड तक दबाकर रखें"</string>
diff --git a/core/res/res/values-hr/strings.xml b/core/res/res/values-hr/strings.xml
index c3edbf563288..dd2bdbeb74c3 100644
--- a/core/res/res/values-hr/strings.xml
+++ b/core/res/res/values-hr/strings.xml
@@ -1676,8 +1676,6 @@
<string name="leave_accessibility_shortcut_on" msgid="6543362062336990814">"Upotrijebi prečac"</string>
<string name="color_inversion_feature_name" msgid="326050048927789012">"Inverzija boja"</string>
<string name="color_correction_feature_name" msgid="3655077237805422597">"Korekcija boje"</string>
- <!-- no translation found for reduce_bright_colors_feature_name (6722364385073799185) -->
- <skip />
<string name="accessibility_shortcut_enabling_service" msgid="5473495203759847687">"Držali ste tipke za glasnoću. Uključila se usluga <xliff:g id="SERVICE_NAME">%1$s</xliff:g>."</string>
<string name="accessibility_shortcut_disabling_service" msgid="8675244165062700619">"Držali ste tipke za glasnoću. Isključila se usluga <xliff:g id="SERVICE_NAME">%1$s</xliff:g>."</string>
<string name="accessibility_shortcut_spoken_feedback" msgid="4228997042855695090">"Pritisnite i zadržite tipke za glasnoću na tri sekunde da biste koristili uslugu <xliff:g id="SERVICE_NAME">%1$s</xliff:g>"</string>
diff --git a/core/res/res/values-hu/strings.xml b/core/res/res/values-hu/strings.xml
index 47cf41b1c33b..9d1c2f491962 100644
--- a/core/res/res/values-hu/strings.xml
+++ b/core/res/res/values-hu/strings.xml
@@ -1654,8 +1654,6 @@
<string name="leave_accessibility_shortcut_on" msgid="6543362062336990814">"Billentyűparancs használata"</string>
<string name="color_inversion_feature_name" msgid="326050048927789012">"Színek invertálása"</string>
<string name="color_correction_feature_name" msgid="3655077237805422597">"Színkorrekció"</string>
- <!-- no translation found for reduce_bright_colors_feature_name (6722364385073799185) -->
- <skip />
<string name="accessibility_shortcut_enabling_service" msgid="5473495203759847687">"Nyomva tartotta a hangerőgombokat. <xliff:g id="SERVICE_NAME">%1$s</xliff:g> bekapcsolva."</string>
<string name="accessibility_shortcut_disabling_service" msgid="8675244165062700619">"Nyomva tartotta a hangerőgombokat. <xliff:g id="SERVICE_NAME">%1$s</xliff:g> kikapcsolva."</string>
<string name="accessibility_shortcut_spoken_feedback" msgid="4228997042855695090">"A(z) <xliff:g id="SERVICE_NAME">%1$s</xliff:g> használatához tartsa lenyomva három másodpercig a két hangerőgombot"</string>
diff --git a/core/res/res/values-hy/strings.xml b/core/res/res/values-hy/strings.xml
index 1e1d1f9529f5..6fade981b4e6 100644
--- a/core/res/res/values-hy/strings.xml
+++ b/core/res/res/values-hy/strings.xml
@@ -1654,8 +1654,6 @@
<string name="leave_accessibility_shortcut_on" msgid="6543362062336990814">"Օգտագործել դյուրանցումը"</string>
<string name="color_inversion_feature_name" msgid="326050048927789012">"Գունաշրջում"</string>
<string name="color_correction_feature_name" msgid="3655077237805422597">"Գունաշտկում"</string>
- <!-- no translation found for reduce_bright_colors_feature_name (6722364385073799185) -->
- <skip />
<string name="accessibility_shortcut_enabling_service" msgid="5473495203759847687">"Ձայնի կարգավորման կոճակները սեղմվեցին։ <xliff:g id="SERVICE_NAME">%1$s</xliff:g> ծառայությունը միացավ։"</string>
<string name="accessibility_shortcut_disabling_service" msgid="8675244165062700619">"Ձայնի կարգավորման կոճակները սեղմվեցին։ <xliff:g id="SERVICE_NAME">%1$s</xliff:g> ծառայությունն անջատվեց։"</string>
<string name="accessibility_shortcut_spoken_feedback" msgid="4228997042855695090">"«<xliff:g id="SERVICE_NAME">%1$s</xliff:g>» ծառայությունն օգտագործելու համար սեղմեք և 3 վայրկյան պահեք ձայնի ուժգնության երկու կոճակները"</string>
diff --git a/core/res/res/values-in/strings.xml b/core/res/res/values-in/strings.xml
index 8a09de41cb1b..202664f7caab 100644
--- a/core/res/res/values-in/strings.xml
+++ b/core/res/res/values-in/strings.xml
@@ -1654,8 +1654,6 @@
<string name="leave_accessibility_shortcut_on" msgid="6543362062336990814">"Gunakan Pintasan"</string>
<string name="color_inversion_feature_name" msgid="326050048927789012">"Inversi Warna"</string>
<string name="color_correction_feature_name" msgid="3655077237805422597">"Koreksi Warna"</string>
- <!-- no translation found for reduce_bright_colors_feature_name (6722364385073799185) -->
- <skip />
<string name="accessibility_shortcut_enabling_service" msgid="5473495203759847687">"Tombol volume ditahan. <xliff:g id="SERVICE_NAME">%1$s</xliff:g> diaktifkan."</string>
<string name="accessibility_shortcut_disabling_service" msgid="8675244165062700619">"Tombol volume ditahan. <xliff:g id="SERVICE_NAME">%1$s</xliff:g> dinonaktifkan."</string>
<string name="accessibility_shortcut_spoken_feedback" msgid="4228997042855695090">"Tekan dan tahan kedua tombol volume selama tiga detik untuk menggunakan <xliff:g id="SERVICE_NAME">%1$s</xliff:g>"</string>
diff --git a/core/res/res/values-is/strings.xml b/core/res/res/values-is/strings.xml
index 2c7ee6be9880..efb23d4db012 100644
--- a/core/res/res/values-is/strings.xml
+++ b/core/res/res/values-is/strings.xml
@@ -1654,8 +1654,6 @@
<string name="leave_accessibility_shortcut_on" msgid="6543362062336990814">"Nota flýtileið"</string>
<string name="color_inversion_feature_name" msgid="326050048927789012">"Umsnúningur lita"</string>
<string name="color_correction_feature_name" msgid="3655077237805422597">"Litaleiðrétting"</string>
- <!-- no translation found for reduce_bright_colors_feature_name (6722364385073799185) -->
- <skip />
<string name="accessibility_shortcut_enabling_service" msgid="5473495203759847687">"Hljóðstyrkstökkum haldið inni. Kveikt á <xliff:g id="SERVICE_NAME">%1$s</xliff:g>."</string>
<string name="accessibility_shortcut_disabling_service" msgid="8675244165062700619">"Hljóðstyrkstökkum haldið inni. Slökkt á <xliff:g id="SERVICE_NAME">%1$s</xliff:g>."</string>
<string name="accessibility_shortcut_spoken_feedback" msgid="4228997042855695090">"Haltu báðum hljóðstyrkstökkunum inni í þrjár sekúndur til að nota <xliff:g id="SERVICE_NAME">%1$s</xliff:g>"</string>
diff --git a/core/res/res/values-it/strings.xml b/core/res/res/values-it/strings.xml
index e32609a42e7c..ec446d7e2f57 100644
--- a/core/res/res/values-it/strings.xml
+++ b/core/res/res/values-it/strings.xml
@@ -1654,8 +1654,6 @@
<string name="leave_accessibility_shortcut_on" msgid="6543362062336990814">"Usa scorciatoia"</string>
<string name="color_inversion_feature_name" msgid="326050048927789012">"Inversione dei colori"</string>
<string name="color_correction_feature_name" msgid="3655077237805422597">"Correzione del colore"</string>
- <!-- no translation found for reduce_bright_colors_feature_name (6722364385073799185) -->
- <skip />
<string name="accessibility_shortcut_enabling_service" msgid="5473495203759847687">"Tieni premuti i tasti del volume. Servizio <xliff:g id="SERVICE_NAME">%1$s</xliff:g> attivato."</string>
<string name="accessibility_shortcut_disabling_service" msgid="8675244165062700619">"Tieni premuti i tasti del volume. Servizio <xliff:g id="SERVICE_NAME">%1$s</xliff:g> disattivato."</string>
<string name="accessibility_shortcut_spoken_feedback" msgid="4228997042855695090">"Tieni premuti entrambi i tasti del volume per tre secondi per utilizzare <xliff:g id="SERVICE_NAME">%1$s</xliff:g>"</string>
diff --git a/core/res/res/values-iw/strings.xml b/core/res/res/values-iw/strings.xml
index 2edfa4d59928..874d5770c32e 100644
--- a/core/res/res/values-iw/strings.xml
+++ b/core/res/res/values-iw/strings.xml
@@ -1698,8 +1698,6 @@
<string name="leave_accessibility_shortcut_on" msgid="6543362062336990814">"השתמש בקיצור הדרך"</string>
<string name="color_inversion_feature_name" msgid="326050048927789012">"היפוך צבעים"</string>
<string name="color_correction_feature_name" msgid="3655077237805422597">"תיקון צבעים"</string>
- <!-- no translation found for reduce_bright_colors_feature_name (6722364385073799185) -->
- <skip />
<string name="accessibility_shortcut_enabling_service" msgid="5473495203759847687">"לחצני עוצמת הקול נלחצו בלחיצה ארוכה. <xliff:g id="SERVICE_NAME">%1$s</xliff:g> הופעל."</string>
<string name="accessibility_shortcut_disabling_service" msgid="8675244165062700619">"לחצני עוצמת הקול נלחצו בלחיצה ארוכה. <xliff:g id="SERVICE_NAME">%1$s</xliff:g> הושבת."</string>
<string name="accessibility_shortcut_spoken_feedback" msgid="4228997042855695090">"יש ללחוץ לחיצה ארוכה על שני לחצני עוצמת הקול למשך שלוש שניות כדי להשתמש בשירות <xliff:g id="SERVICE_NAME">%1$s</xliff:g>"</string>
diff --git a/core/res/res/values-ja/strings.xml b/core/res/res/values-ja/strings.xml
index c9fc1c2041cd..32a4dedd6290 100644
--- a/core/res/res/values-ja/strings.xml
+++ b/core/res/res/values-ja/strings.xml
@@ -1654,8 +1654,6 @@
<string name="leave_accessibility_shortcut_on" msgid="6543362062336990814">"ショートカットを使用"</string>
<string name="color_inversion_feature_name" msgid="326050048927789012">"色反転"</string>
<string name="color_correction_feature_name" msgid="3655077237805422597">"色補正"</string>
- <!-- no translation found for reduce_bright_colors_feature_name (6722364385073799185) -->
- <skip />
<string name="accessibility_shortcut_enabling_service" msgid="5473495203759847687">"音量ボタンを長押ししました。<xliff:g id="SERVICE_NAME">%1$s</xliff:g> が ON になりました。"</string>
<string name="accessibility_shortcut_disabling_service" msgid="8675244165062700619">"音量ボタンを長押ししました。<xliff:g id="SERVICE_NAME">%1$s</xliff:g> が OFF になりました。"</string>
<string name="accessibility_shortcut_spoken_feedback" msgid="4228997042855695090">"<xliff:g id="SERVICE_NAME">%1$s</xliff:g> を使用するには、音量大と音量小の両方のボタンを 3 秒間長押ししてください"</string>
diff --git a/core/res/res/values-ka/strings.xml b/core/res/res/values-ka/strings.xml
index 060d72711575..349bd167ff56 100644
--- a/core/res/res/values-ka/strings.xml
+++ b/core/res/res/values-ka/strings.xml
@@ -1654,7 +1654,6 @@
<string name="leave_accessibility_shortcut_on" msgid="6543362062336990814">"მალსახმობის გამოყენება"</string>
<string name="color_inversion_feature_name" msgid="326050048927789012">"ფერთა ინვერსია"</string>
<string name="color_correction_feature_name" msgid="3655077237805422597">"ფერთა კორექცია"</string>
- <string name="reduce_bright_colors_feature_name" msgid="6722364385073799185">"კაშკაშა ფერების შემცირება"</string>
<string name="accessibility_shortcut_enabling_service" msgid="5473495203759847687">"ხანგრძლივად დააჭირეთ ხმის ღილაკებს. <xliff:g id="SERVICE_NAME">%1$s</xliff:g> ჩართულია."</string>
<string name="accessibility_shortcut_disabling_service" msgid="8675244165062700619">"ხანგრძლივად დააჭირეთ ხმის ღილაკებს. <xliff:g id="SERVICE_NAME">%1$s</xliff:g> გამორთულია."</string>
<string name="accessibility_shortcut_spoken_feedback" msgid="4228997042855695090">"<xliff:g id="SERVICE_NAME">%1$s</xliff:g> რომ გამოიყენოთ, დააჭირეთ ხმის ორივე ღილაკზე 3 წამის განმავლობაში"</string>
diff --git a/core/res/res/values-kk/strings.xml b/core/res/res/values-kk/strings.xml
index d80572ff1509..4d4eef0378dd 100644
--- a/core/res/res/values-kk/strings.xml
+++ b/core/res/res/values-kk/strings.xml
@@ -1654,8 +1654,6 @@
<string name="leave_accessibility_shortcut_on" msgid="6543362062336990814">"Төте жолды пайдалану"</string>
<string name="color_inversion_feature_name" msgid="326050048927789012">"Түстер инверсиясы"</string>
<string name="color_correction_feature_name" msgid="3655077237805422597">"Түсті түзету"</string>
- <!-- no translation found for reduce_bright_colors_feature_name (6722364385073799185) -->
- <skip />
<string name="accessibility_shortcut_enabling_service" msgid="5473495203759847687">"Пайдаланушы дыбыс деңгейі пернелерін басып ұстап тұрды. <xliff:g id="SERVICE_NAME">%1$s</xliff:g> қосулы."</string>
<string name="accessibility_shortcut_disabling_service" msgid="8675244165062700619">"Дыбыс деңгейі пернелерін басып тұрған соң, <xliff:g id="SERVICE_NAME">%1$s</xliff:g> өшірілді."</string>
<string name="accessibility_shortcut_spoken_feedback" msgid="4228997042855695090">"<xliff:g id="SERVICE_NAME">%1$s</xliff:g> қызметін пайдалану үшін дыбыс деңгейін реттейтін екі түймені де 3 секунд басып тұрыңыз"</string>
diff --git a/core/res/res/values-km/strings.xml b/core/res/res/values-km/strings.xml
index 2fd7257d85eb..3ebd7364b2c9 100644
--- a/core/res/res/values-km/strings.xml
+++ b/core/res/res/values-km/strings.xml
@@ -1654,8 +1654,6 @@
<string name="leave_accessibility_shortcut_on" msgid="6543362062336990814">"ប្រើប្រាស់​ផ្លូវកាត់"</string>
<string name="color_inversion_feature_name" msgid="326050048927789012">"បញ្ច្រាស​ពណ៌"</string>
<string name="color_correction_feature_name" msgid="3655077237805422597">"ការ​កែ​ពណ៌"</string>
- <!-- no translation found for reduce_bright_colors_feature_name (6722364385073799185) -->
- <skip />
<string name="accessibility_shortcut_enabling_service" msgid="5473495203759847687">"បានសង្កត់​គ្រាប់ចុច​កម្រិតសំឡេង​ជាប់។ បាន​បើក <xliff:g id="SERVICE_NAME">%1$s</xliff:g>។"</string>
<string name="accessibility_shortcut_disabling_service" msgid="8675244165062700619">"បានសង្កត់​គ្រាប់ចុច​កម្រិតសំឡេង​ជាប់។ បាន​បិទ <xliff:g id="SERVICE_NAME">%1$s</xliff:g>។"</string>
<string name="accessibility_shortcut_spoken_feedback" msgid="4228997042855695090">"ចុចគ្រាប់ចុច​កម្រិត​សំឡេងទាំងពីរ​ឱ្យជាប់រយៈពេលបីវិនាទី ដើម្បីប្រើ <xliff:g id="SERVICE_NAME">%1$s</xliff:g>"</string>
diff --git a/core/res/res/values-kn/strings.xml b/core/res/res/values-kn/strings.xml
index 20b2ccf7db6f..0cf6f494677b 100644
--- a/core/res/res/values-kn/strings.xml
+++ b/core/res/res/values-kn/strings.xml
@@ -1654,8 +1654,6 @@
<string name="leave_accessibility_shortcut_on" msgid="6543362062336990814">"ಶಾರ್ಟ್‌ಕಟ್ ಬಳಸಿ"</string>
<string name="color_inversion_feature_name" msgid="326050048927789012">"ಬಣ್ಣ ವಿಲೋಮ"</string>
<string name="color_correction_feature_name" msgid="3655077237805422597">"ಬಣ್ಣ ತಿದ್ದುಪಡಿ"</string>
- <!-- no translation found for reduce_bright_colors_feature_name (6722364385073799185) -->
- <skip />
<string name="accessibility_shortcut_enabling_service" msgid="5473495203759847687">"ವಾಲ್ಯೂಮ್ ಕೀಗಳನ್ನು ಹಿಡಿದುಕೊಳ್ಳಿ. <xliff:g id="SERVICE_NAME">%1$s</xliff:g> ಅನ್ನು ಆನ್ ಮಾಡಲಾಗಿದೆ."</string>
<string name="accessibility_shortcut_disabling_service" msgid="8675244165062700619">"ವಾಲ್ಯೂಮ್ ಕೀಗಳನ್ನು ಹಿಡಿದಿಟ್ಟುಕೊಳ್ಳಲಾಗಿದೆ. <xliff:g id="SERVICE_NAME">%1$s</xliff:g>, ಆಫ್ ಮಾಡಲಾಗಿದೆ."</string>
<string name="accessibility_shortcut_spoken_feedback" msgid="4228997042855695090">"<xliff:g id="SERVICE_NAME">%1$s</xliff:g> ಅನ್ನು ಬಳಸಲು ಎರಡೂ ಧ್ವನಿ ಕೀಗಳನ್ನು ಮೂರು ಸೆಕೆಂಡ್‌ಗಳ ಕಾಲ ಒತ್ತಿ ಹಿಡಿದುಕೊಳ್ಳಿ"</string>
diff --git a/core/res/res/values-ko/strings.xml b/core/res/res/values-ko/strings.xml
index 79569e241c3a..3dfdf3d4ebd1 100644
--- a/core/res/res/values-ko/strings.xml
+++ b/core/res/res/values-ko/strings.xml
@@ -1654,8 +1654,6 @@
<string name="leave_accessibility_shortcut_on" msgid="6543362062336990814">"단축키 사용"</string>
<string name="color_inversion_feature_name" msgid="326050048927789012">"색상 반전"</string>
<string name="color_correction_feature_name" msgid="3655077237805422597">"색상 보정"</string>
- <!-- no translation found for reduce_bright_colors_feature_name (6722364385073799185) -->
- <skip />
<string name="accessibility_shortcut_enabling_service" msgid="5473495203759847687">"볼륨 키를 길게 눌렀습니다. <xliff:g id="SERVICE_NAME">%1$s</xliff:g>이(가) 사용 설정되었습니다."</string>
<string name="accessibility_shortcut_disabling_service" msgid="8675244165062700619">"볼륨 키를 길게 눌렀습니다. <xliff:g id="SERVICE_NAME">%1$s</xliff:g>이(가) 사용 중지되었습니다."</string>
<string name="accessibility_shortcut_spoken_feedback" msgid="4228997042855695090">"<xliff:g id="SERVICE_NAME">%1$s</xliff:g> 서비스를 사용하려면 두 볼륨 키를 3초 동안 길게 누르세요"</string>
diff --git a/core/res/res/values-ky/strings.xml b/core/res/res/values-ky/strings.xml
index 4fee44ae67fc..012acf53a3a4 100644
--- a/core/res/res/values-ky/strings.xml
+++ b/core/res/res/values-ky/strings.xml
@@ -1654,8 +1654,6 @@
<string name="leave_accessibility_shortcut_on" msgid="6543362062336990814">"Кыска жолду колдонуу"</string>
<string name="color_inversion_feature_name" msgid="326050048927789012">"Түстү инверсиялоо"</string>
<string name="color_correction_feature_name" msgid="3655077237805422597">"Түсүн тууралоо"</string>
- <!-- no translation found for reduce_bright_colors_feature_name (6722364385073799185) -->
- <skip />
<string name="accessibility_shortcut_enabling_service" msgid="5473495203759847687">"Үндү катуулатуу/акырындатуу баскычтары басылып, <xliff:g id="SERVICE_NAME">%1$s</xliff:g> күйгүзүлдү."</string>
<string name="accessibility_shortcut_disabling_service" msgid="8675244165062700619">"Үндү катуулатуу/акырындатуу баскычтары басылып, <xliff:g id="SERVICE_NAME">%1$s</xliff:g> өчүрүлдү."</string>
<string name="accessibility_shortcut_spoken_feedback" msgid="4228997042855695090">"<xliff:g id="SERVICE_NAME">%1$s</xliff:g> кызматын колдонуу үчүн үнүн чоңойтуп/кичирейтүү баскычтарын үч секунд коё бербей басып туруңуз"</string>
diff --git a/core/res/res/values-lo/strings.xml b/core/res/res/values-lo/strings.xml
index 457b74e6036f..315ee322fa7c 100644
--- a/core/res/res/values-lo/strings.xml
+++ b/core/res/res/values-lo/strings.xml
@@ -1654,7 +1654,6 @@
<string name="leave_accessibility_shortcut_on" msgid="6543362062336990814">"ໃຊ້ປຸ່ມລັດ"</string>
<string name="color_inversion_feature_name" msgid="326050048927789012">"ການປີ້ນສີ"</string>
<string name="color_correction_feature_name" msgid="3655077237805422597">"ການແກ້ໄຂຄ່າສີ"</string>
- <string name="reduce_bright_colors_feature_name" msgid="6722364385073799185">"ຫຼຸດສີສະຫວ່າງ"</string>
<string name="accessibility_shortcut_enabling_service" msgid="5473495203759847687">"ກົດປຸ່ມລະດັບສຽງຄ້າງໄວ້. ເປີດໃຊ້ <xliff:g id="SERVICE_NAME">%1$s</xliff:g> ແລ້ວ."</string>
<string name="accessibility_shortcut_disabling_service" msgid="8675244165062700619">"ກົດປຸ່ມລະດັບສຽງຄ້າງໄວ້. ປິດ <xliff:g id="SERVICE_NAME">%1$s</xliff:g> ໄວ້ແລ້ວ."</string>
<string name="accessibility_shortcut_spoken_feedback" msgid="4228997042855695090">"ກົດປຸ່ມສຽງທັງສອງພ້ອມກັນຄ້າງໄວ້ສາມວິນາທີເພື່ອໃຊ້ <xliff:g id="SERVICE_NAME">%1$s</xliff:g>"</string>
diff --git a/core/res/res/values-lt/strings.xml b/core/res/res/values-lt/strings.xml
index cedde1181f0c..1d6b2c7dbb45 100644
--- a/core/res/res/values-lt/strings.xml
+++ b/core/res/res/values-lt/strings.xml
@@ -1698,8 +1698,6 @@
<string name="leave_accessibility_shortcut_on" msgid="6543362062336990814">"Naudoti spartųjį klavišą"</string>
<string name="color_inversion_feature_name" msgid="326050048927789012">"Spalvų inversija"</string>
<string name="color_correction_feature_name" msgid="3655077237805422597">"Spalvų taisymas"</string>
- <!-- no translation found for reduce_bright_colors_feature_name (6722364385073799185) -->
- <skip />
<string name="accessibility_shortcut_enabling_service" msgid="5473495203759847687">"Laikomi garsumo klavišai. „<xliff:g id="SERVICE_NAME">%1$s</xliff:g>“ įjungta."</string>
<string name="accessibility_shortcut_disabling_service" msgid="8675244165062700619">"Laikomi garsumo klavišai. „<xliff:g id="SERVICE_NAME">%1$s</xliff:g>“ išjungta."</string>
<string name="accessibility_shortcut_spoken_feedback" msgid="4228997042855695090">"Jei norite naudoti „<xliff:g id="SERVICE_NAME">%1$s</xliff:g>“, paspauskite abu garsumo klavišus ir palaikykite tris sekundes"</string>
diff --git a/core/res/res/values-lv/strings.xml b/core/res/res/values-lv/strings.xml
index e34bb9528518..ba790a0714c0 100644
--- a/core/res/res/values-lv/strings.xml
+++ b/core/res/res/values-lv/strings.xml
@@ -1676,8 +1676,6 @@
<string name="leave_accessibility_shortcut_on" msgid="6543362062336990814">"Izmantot saīsni"</string>
<string name="color_inversion_feature_name" msgid="326050048927789012">"Krāsu inversija"</string>
<string name="color_correction_feature_name" msgid="3655077237805422597">"Krāsu korekcija"</string>
- <!-- no translation found for reduce_bright_colors_feature_name (6722364385073799185) -->
- <skip />
<string name="accessibility_shortcut_enabling_service" msgid="5473495203759847687">"Turējāt nospiestas skaļuma pogas. Pakalpojums <xliff:g id="SERVICE_NAME">%1$s</xliff:g> tika ieslēgts."</string>
<string name="accessibility_shortcut_disabling_service" msgid="8675244165062700619">"Turējāt nospiestas skaļuma pogas. Pakalpojums <xliff:g id="SERVICE_NAME">%1$s</xliff:g> tika izslēgts."</string>
<string name="accessibility_shortcut_spoken_feedback" msgid="4228997042855695090">"Lai izmantotu pakalpojumu <xliff:g id="SERVICE_NAME">%1$s</xliff:g>, nospiediet abus skaļuma taustiņus un turiet tos trīs sekundes."</string>
diff --git a/core/res/res/values-mcc310-mnc560-as/strings.xml b/core/res/res/values-mcc310-mnc560-as/strings.xml
deleted file mode 100644
index 13f3657f7057..000000000000
--- a/core/res/res/values-mcc310-mnc560-as/strings.xml
+++ /dev/null
@@ -1,26 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-/* //device/apps/common/assets/res/any/strings.xml
-**
-** Copyright 2006, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License");
-** you may not use this file except in compliance with the License.
-** You may obtain a copy of the License at
-**
-** http://www.apache.org/licenses/LICENSE-2.0
-**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-** See the License for the specific language governing permissions and
-** limitations under the License.
-*/
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="mmcc_imsi_unknown_in_hlr" msgid="3526528316378889524">"ছিমখন প্ৰ\'ভিজন কৰা হোৱা নাই MM#2"</string>
- <string name="mmcc_illegal_ms" msgid="4618730283812066268">"ছিমৰ অনুমতি নাই MM#3"</string>
- <string name="mmcc_illegal_me" msgid="8522039751358990401">"ফ\'নৰ অনুমতি নাই MM#6"</string>
-</resources>
diff --git a/core/res/res/values-mk/strings.xml b/core/res/res/values-mk/strings.xml
index c06128307fc5..6f82395327d8 100644
--- a/core/res/res/values-mk/strings.xml
+++ b/core/res/res/values-mk/strings.xml
@@ -905,7 +905,7 @@
<string name="keyguard_accessibility_user_selector" msgid="1466067610235696600">"Избирач на корисник"</string>
<string name="keyguard_accessibility_status" msgid="6792745049712397237">"Статус"</string>
<string name="keyguard_accessibility_camera" msgid="7862557559464986528">"Камера"</string>
- <string name="keygaurd_accessibility_media_controls" msgid="2267379779900620614">"Контроли на медиуми"</string>
+ <string name="keygaurd_accessibility_media_controls" msgid="2267379779900620614">"Контроли за аудио/видео содржини"</string>
<string name="keyguard_accessibility_widget_reorder_start" msgid="7066213328912939191">"Прередувањето виџети започна."</string>
<string name="keyguard_accessibility_widget_reorder_end" msgid="1083806817600593490">"Прередувањето виџети заврши."</string>
<string name="keyguard_accessibility_widget_deleted" msgid="1509738950119878705">"Виџетот <xliff:g id="WIDGET_INDEX">%1$s</xliff:g> е избришан."</string>
@@ -1351,7 +1351,7 @@
<string name="ext_media_new_notification_title" product="automotive" msgid="9085349544984742727">"<xliff:g id="NAME">%s</xliff:g> не работи"</string>
<string name="ext_media_new_notification_message" msgid="6095403121990786986">"Допрете за поставување"</string>
<string name="ext_media_new_notification_message" product="automotive" msgid="5140127881613227162">"Можеби ќе треба да го преформатирате уредот. Допрете за отстранување."</string>
- <string name="ext_media_ready_notification_message" msgid="777258143284919261">"За пренесување фотографии и медиуми"</string>
+ <string name="ext_media_ready_notification_message" msgid="777258143284919261">"За пренесување фотографии и аудио/видео содржини"</string>
<string name="ext_media_unmountable_notification_title" msgid="4895444667278979910">"Проблем со <xliff:g id="NAME">%s</xliff:g>"</string>
<string name="ext_media_unmountable_notification_title" product="automotive" msgid="3142723758949023280">"<xliff:g id="NAME">%s</xliff:g> не работи"</string>
<string name="ext_media_unmountable_notification_message" msgid="3256290114063126205">"Допрете за да го поправите ова"</string>
@@ -1392,8 +1392,8 @@
<string name="ext_media_status_formatting" msgid="774148701503179906">"Се форматира..."</string>
<string name="ext_media_status_missing" msgid="6520746443048867314">"Не е внесено"</string>
<string name="activity_list_empty" msgid="4219430010716034252">"Не се пронајдени соодветни активности."</string>
- <string name="permlab_route_media_output" msgid="8048124531439513118">"насочување излез за медиуми"</string>
- <string name="permdesc_route_media_output" msgid="1759683269387729675">"Овозможува апликацијата да насочува излез за медиуми кон други надворешни уреди."</string>
+ <string name="permlab_route_media_output" msgid="8048124531439513118">"насочување излез за аудио/видео"</string>
+ <string name="permdesc_route_media_output" msgid="1759683269387729675">"Овозможува апликацијата да насочува излез за аудио/видео содржини кон други надворешни уреди."</string>
<string name="permlab_readInstallSessions" msgid="7279049337895583621">"читање сесии на инсталирање"</string>
<string name="permdesc_readInstallSessions" msgid="4012608316610763473">"Дозволува апликација да чита сесии на инсталирање. Тоа овозможува апликацијата да гледа детали за активни инсталации на пакет."</string>
<string name="permlab_requestInstallPackages" msgid="7600020863445351154">"барање пакети за инсталирање"</string>
@@ -1654,8 +1654,6 @@
<string name="leave_accessibility_shortcut_on" msgid="6543362062336990814">"Користи кратенка"</string>
<string name="color_inversion_feature_name" msgid="326050048927789012">"Инверзија на бои"</string>
<string name="color_correction_feature_name" msgid="3655077237805422597">"Корекција на бои"</string>
- <!-- no translation found for reduce_bright_colors_feature_name (6722364385073799185) -->
- <skip />
<string name="accessibility_shortcut_enabling_service" msgid="5473495203759847687">"Ги задржавте копчињата за јачина на звук. <xliff:g id="SERVICE_NAME">%1$s</xliff:g> е вклучена."</string>
<string name="accessibility_shortcut_disabling_service" msgid="8675244165062700619">"Ги задржавте копчињата за јачина на звук. <xliff:g id="SERVICE_NAME">%1$s</xliff:g> е исклучена."</string>
<string name="accessibility_shortcut_spoken_feedback" msgid="4228997042855695090">"Притиснете ги и задржете ги двете копчиња за јачина на звукот во траење од три секунди за да користите <xliff:g id="SERVICE_NAME">%1$s</xliff:g>"</string>
diff --git a/core/res/res/values-ml/strings.xml b/core/res/res/values-ml/strings.xml
index 18dbf0e76c6f..ffe073c2d31d 100644
--- a/core/res/res/values-ml/strings.xml
+++ b/core/res/res/values-ml/strings.xml
@@ -1654,8 +1654,6 @@
<string name="leave_accessibility_shortcut_on" msgid="6543362062336990814">"കുറുക്കുവഴി ഉപയോഗിക്കുക"</string>
<string name="color_inversion_feature_name" msgid="326050048927789012">"വർണ്ണ വിപര്യയം"</string>
<string name="color_correction_feature_name" msgid="3655077237805422597">"നിറം ക്രമീകരിക്കൽ"</string>
- <!-- no translation found for reduce_bright_colors_feature_name (6722364385073799185) -->
- <skip />
<string name="accessibility_shortcut_enabling_service" msgid="5473495203759847687">"വോളിയം കീകൾ പിടിച്ചു. <xliff:g id="SERVICE_NAME">%1$s</xliff:g> ഓണാക്കി."</string>
<string name="accessibility_shortcut_disabling_service" msgid="8675244165062700619">"വോളിയം കീകൾ അമർത്തിപ്പിടിച്ചു. <xliff:g id="SERVICE_NAME">%1$s</xliff:g> ഓഫാക്കി."</string>
<string name="accessibility_shortcut_spoken_feedback" msgid="4228997042855695090">"<xliff:g id="SERVICE_NAME">%1$s</xliff:g> ഉപയോഗിക്കാൻ, രണ്ട് വോളിയം കീകളും മൂന്ന് സെക്കൻഡ് അമർത്തിപ്പിടിക്കുക"</string>
diff --git a/core/res/res/values-mn/strings.xml b/core/res/res/values-mn/strings.xml
index a7a08ce13e61..2183d010283a 100644
--- a/core/res/res/values-mn/strings.xml
+++ b/core/res/res/values-mn/strings.xml
@@ -1654,8 +1654,6 @@
<string name="leave_accessibility_shortcut_on" msgid="6543362062336990814">"Товчлол ашиглах"</string>
<string name="color_inversion_feature_name" msgid="326050048927789012">"Өнгө хувиргалт"</string>
<string name="color_correction_feature_name" msgid="3655077237805422597">"Өнгөний засвар"</string>
- <!-- no translation found for reduce_bright_colors_feature_name (6722364385073799185) -->
- <skip />
<string name="accessibility_shortcut_enabling_service" msgid="5473495203759847687">"Дууны түвшний түлхүүрийг удаан дарсан. <xliff:g id="SERVICE_NAME">%1$s</xliff:g>-г асаалаа."</string>
<string name="accessibility_shortcut_disabling_service" msgid="8675244165062700619">"Дууны түвшний түлхүүрийг удаан дарсан. <xliff:g id="SERVICE_NAME">%1$s</xliff:g>-г унтраалаа."</string>
<string name="accessibility_shortcut_spoken_feedback" msgid="4228997042855695090">"<xliff:g id="SERVICE_NAME">%1$s</xliff:g>-г ашиглахын тулд дууны түвшнийг ихэсгэх, багасгах түлхүүрийг 3 секундийн турш зэрэг дарна уу"</string>
diff --git a/core/res/res/values-mr/strings.xml b/core/res/res/values-mr/strings.xml
index b9ef667a9990..9b4849f4b19b 100644
--- a/core/res/res/values-mr/strings.xml
+++ b/core/res/res/values-mr/strings.xml
@@ -1654,8 +1654,6 @@
<string name="leave_accessibility_shortcut_on" msgid="6543362062336990814">"शॉर्टकट वापरा"</string>
<string name="color_inversion_feature_name" msgid="326050048927789012">"रंगांची उलटापालट"</string>
<string name="color_correction_feature_name" msgid="3655077237805422597">"रंग सुधारणा"</string>
- <!-- no translation found for reduce_bright_colors_feature_name (6722364385073799185) -->
- <skip />
<string name="accessibility_shortcut_enabling_service" msgid="5473495203759847687">"धरून ठेवलेल्या व्हॉल्यूम की. <xliff:g id="SERVICE_NAME">%1$s</xliff:g> सुरू केला आहे."</string>
<string name="accessibility_shortcut_disabling_service" msgid="8675244165062700619">"धरून ठेवलेल्या व्हॉल्यूम की. <xliff:g id="SERVICE_NAME">%1$s</xliff:g> बंद केले आहे."</string>
<string name="accessibility_shortcut_spoken_feedback" msgid="4228997042855695090">"<xliff:g id="SERVICE_NAME">%1$s</xliff:g> वापरण्यासाठी दोन्ही व्हॉल्युम की तीन सेकंद दाबा आणि धरून ठेवा"</string>
diff --git a/core/res/res/values-ms/strings.xml b/core/res/res/values-ms/strings.xml
index d0b9f3affe25..5c35ba13f599 100644
--- a/core/res/res/values-ms/strings.xml
+++ b/core/res/res/values-ms/strings.xml
@@ -1654,8 +1654,6 @@
<string name="leave_accessibility_shortcut_on" msgid="6543362062336990814">"Gunakan Pintasan"</string>
<string name="color_inversion_feature_name" msgid="326050048927789012">"Penyongsangan Warna"</string>
<string name="color_correction_feature_name" msgid="3655077237805422597">"Pembetulan Warna"</string>
- <!-- no translation found for reduce_bright_colors_feature_name (6722364385073799185) -->
- <skip />
<string name="accessibility_shortcut_enabling_service" msgid="5473495203759847687">"Kekunci kelantangan ditahan. <xliff:g id="SERVICE_NAME">%1$s</xliff:g> dihidupkan."</string>
<string name="accessibility_shortcut_disabling_service" msgid="8675244165062700619">"Kekunci kelantangan ditahan. <xliff:g id="SERVICE_NAME">%1$s</xliff:g> dimatikan."</string>
<string name="accessibility_shortcut_spoken_feedback" msgid="4228997042855695090">"Tekan dan tahan kedua-dua kekunci kelantangan selama tiga saat untuk menggunakan <xliff:g id="SERVICE_NAME">%1$s</xliff:g>"</string>
diff --git a/core/res/res/values-my/strings.xml b/core/res/res/values-my/strings.xml
index 0729f53087c9..38f1aa8f8f6b 100644
--- a/core/res/res/values-my/strings.xml
+++ b/core/res/res/values-my/strings.xml
@@ -1654,8 +1654,6 @@
<string name="leave_accessibility_shortcut_on" msgid="6543362062336990814">"ဖြတ်လမ်းလင့်ခ်ကို သုံးရန်"</string>
<string name="color_inversion_feature_name" msgid="326050048927789012">"အရောင် ပြောင်းပြန်လှန်ခြင်း"</string>
<string name="color_correction_feature_name" msgid="3655077237805422597">"အရောင်ပြင်ဆင်ခြင်း"</string>
- <!-- no translation found for reduce_bright_colors_feature_name (6722364385073799185) -->
- <skip />
<string name="accessibility_shortcut_enabling_service" msgid="5473495203759847687">"အသံခလုတ်များကို ဖိထားသည်။ <xliff:g id="SERVICE_NAME">%1$s</xliff:g> ဖွင့်လိုက်သည်။"</string>
<string name="accessibility_shortcut_disabling_service" msgid="8675244165062700619">"အသံခလုတ်များကို ဖိထားသည်။ <xliff:g id="SERVICE_NAME">%1$s</xliff:g> ပိတ်လိုက်သည်။"</string>
<string name="accessibility_shortcut_spoken_feedback" msgid="4228997042855695090">"<xliff:g id="SERVICE_NAME">%1$s</xliff:g> ကို သုံးရန် အသံအတိုးအလျှော့ ခလုတ်နှစ်ခုလုံးကို သုံးစက္ကန့်ကြာ ဖိထားပါ"</string>
diff --git a/core/res/res/values-nb/strings.xml b/core/res/res/values-nb/strings.xml
index 183942651754..5b0a4ad1c124 100644
--- a/core/res/res/values-nb/strings.xml
+++ b/core/res/res/values-nb/strings.xml
@@ -1654,8 +1654,6 @@
<string name="leave_accessibility_shortcut_on" msgid="6543362062336990814">"Bruk snarveien"</string>
<string name="color_inversion_feature_name" msgid="326050048927789012">"Fargeinvertering"</string>
<string name="color_correction_feature_name" msgid="3655077237805422597">"Fargekorrigering"</string>
- <!-- no translation found for reduce_bright_colors_feature_name (6722364385073799185) -->
- <skip />
<string name="accessibility_shortcut_enabling_service" msgid="5473495203759847687">"Volumtastene holdes inne. <xliff:g id="SERVICE_NAME">%1$s</xliff:g> er slått på."</string>
<string name="accessibility_shortcut_disabling_service" msgid="8675244165062700619">"Volumtastene holdes inne. <xliff:g id="SERVICE_NAME">%1$s</xliff:g> er slått av."</string>
<string name="accessibility_shortcut_spoken_feedback" msgid="4228997042855695090">"Trykk og hold inne begge volumtastene i tre sekunder for å bruke <xliff:g id="SERVICE_NAME">%1$s</xliff:g>"</string>
diff --git a/core/res/res/values-ne/strings.xml b/core/res/res/values-ne/strings.xml
index b75a05d0ea07..0326c23722c6 100644
--- a/core/res/res/values-ne/strings.xml
+++ b/core/res/res/values-ne/strings.xml
@@ -1654,8 +1654,6 @@
<string name="leave_accessibility_shortcut_on" msgid="6543362062336990814">"सर्टकट प्रयोग गर्नुहोस्"</string>
<string name="color_inversion_feature_name" msgid="326050048927789012">"रङ्ग उल्टाउने सुविधा"</string>
<string name="color_correction_feature_name" msgid="3655077237805422597">"रङ्ग सच्याउने सुविधा"</string>
- <!-- no translation found for reduce_bright_colors_feature_name (6722364385073799185) -->
- <skip />
<string name="accessibility_shortcut_enabling_service" msgid="5473495203759847687">"तपाईंले भोल्युम बटनहरू थिचिराख्नुभयो। <xliff:g id="SERVICE_NAME">%1$s</xliff:g> अन भयो।"</string>
<string name="accessibility_shortcut_disabling_service" msgid="8675244165062700619">"तपाईंले भोल्युम बटनहरू थिचिराख्नुभयो। <xliff:g id="SERVICE_NAME">%1$s</xliff:g> अफ भयो।"</string>
<string name="accessibility_shortcut_spoken_feedback" msgid="4228997042855695090">"<xliff:g id="SERVICE_NAME">%1$s</xliff:g> प्रयोग गर्न दुवै भोल्युम कुञ्जीहरूलाई तीन सेकेन्डसम्म थिचिराख्नुहोस्"</string>
diff --git a/core/res/res/values-nl/strings.xml b/core/res/res/values-nl/strings.xml
index d460f40af9a1..17e988e4a344 100644
--- a/core/res/res/values-nl/strings.xml
+++ b/core/res/res/values-nl/strings.xml
@@ -1654,8 +1654,6 @@
<string name="leave_accessibility_shortcut_on" msgid="6543362062336990814">"Sneltoets gebruiken"</string>
<string name="color_inversion_feature_name" msgid="326050048927789012">"Kleurinversie"</string>
<string name="color_correction_feature_name" msgid="3655077237805422597">"Kleurcorrectie"</string>
- <!-- no translation found for reduce_bright_colors_feature_name (6722364385073799185) -->
- <skip />
<string name="accessibility_shortcut_enabling_service" msgid="5473495203759847687">"Volumetoetsen ingedrukt gehouden. <xliff:g id="SERVICE_NAME">%1$s</xliff:g> is ingeschakeld."</string>
<string name="accessibility_shortcut_disabling_service" msgid="8675244165062700619">"Volumetoetsen ingedrukt gehouden. <xliff:g id="SERVICE_NAME">%1$s</xliff:g> uitgeschakeld."</string>
<string name="accessibility_shortcut_spoken_feedback" msgid="4228997042855695090">"Houd beide volumetoetsen drie seconden ingedrukt om <xliff:g id="SERVICE_NAME">%1$s</xliff:g> te gebruiken"</string>
diff --git a/core/res/res/values-or/strings.xml b/core/res/res/values-or/strings.xml
index 129f4d3f9c2b..0f10cde4b9cb 100644
--- a/core/res/res/values-or/strings.xml
+++ b/core/res/res/values-or/strings.xml
@@ -1654,8 +1654,6 @@
<string name="leave_accessibility_shortcut_on" msgid="6543362062336990814">"ଶର୍ଟକଟ୍‍ ବ୍ୟବହାର କରନ୍ତୁ"</string>
<string name="color_inversion_feature_name" msgid="326050048927789012">"ରଙ୍ଗ ବଦଳାଇବାର ସୁବିଧା"</string>
<string name="color_correction_feature_name" msgid="3655077237805422597">"ରଙ୍ଗ ସଂଶୋଧନ"</string>
- <!-- no translation found for reduce_bright_colors_feature_name (6722364385073799185) -->
- <skip />
<string name="accessibility_shortcut_enabling_service" msgid="5473495203759847687">"ଭଲ୍ୟୁମ୍ କୀ\'ଗୁଡ଼ିକୁ ଧରି ରଖାଯାଇଛି। <xliff:g id="SERVICE_NAME">%1$s</xliff:g> ଚାଲୁ ହୋଇଛି।"</string>
<string name="accessibility_shortcut_disabling_service" msgid="8675244165062700619">"ଭଲ୍ୟୁମ୍ କୀ\'ଗୁଡ଼ିକୁ ଧରି ରଖାଯାଇଛି। <xliff:g id="SERVICE_NAME">%1$s</xliff:g> ବନ୍ଦ ହୋଇଛି।"</string>
<string name="accessibility_shortcut_spoken_feedback" msgid="4228997042855695090">"<xliff:g id="SERVICE_NAME">%1$s</xliff:g> ବ୍ୟବହାର କରିବାକୁ ତିନି ସେକେଣ୍ଡ ପାଇଁ ଉଭୟ ଭଲ୍ୟୁମ୍‍ କୀ ଦବାଇ ଧରି ରଖନ୍ତୁ"</string>
diff --git a/core/res/res/values-pa/strings.xml b/core/res/res/values-pa/strings.xml
index ccd20392b111..11bfd78a2ca7 100644
--- a/core/res/res/values-pa/strings.xml
+++ b/core/res/res/values-pa/strings.xml
@@ -1654,8 +1654,6 @@
<string name="leave_accessibility_shortcut_on" msgid="6543362062336990814">"ਸ਼ਾਰਟਕੱਟ ਦੀ ਵਰਤੋਂ ਕਰੋ"</string>
<string name="color_inversion_feature_name" msgid="326050048927789012">"ਰੰਗ ਪਲਟਨਾ"</string>
<string name="color_correction_feature_name" msgid="3655077237805422597">"ਰੰਗ ਸੁਧਾਈ"</string>
- <!-- no translation found for reduce_bright_colors_feature_name (6722364385073799185) -->
- <skip />
<string name="accessibility_shortcut_enabling_service" msgid="5473495203759847687">"ਅਵਾਜ਼ੀ ਕੁੰਜੀਆਂ ਦਬਾ ਕੇ ਰੱਖੀਆਂ ਗਈਆਂ। <xliff:g id="SERVICE_NAME">%1$s</xliff:g> ਨੂੰ ਚਾਲੂ ਕੀਤਾ ਗਿਆ।"</string>
<string name="accessibility_shortcut_disabling_service" msgid="8675244165062700619">"ਅਵਾਜ਼ੀ ਕੁੰਜੀਆਂ ਦਬਾ ਕੇ ਰੱਖੀਆਂ ਗਈਆਂ। <xliff:g id="SERVICE_NAME">%1$s</xliff:g> ਨੂੰ ਬੰਦ ਕੀਤਾ ਗਿਆ।"</string>
<string name="accessibility_shortcut_spoken_feedback" msgid="4228997042855695090">"<xliff:g id="SERVICE_NAME">%1$s</xliff:g> ਦੀ ਵਰਤੋਂ ਕਰਨ ਲਈ ਦੋਵੇਂ ਅਵਾਜ਼ ਕੁੰਜੀਆਂ ਨੂੰ 3 ਸਕਿੰਟਾਂ ਲਈ ਦਬਾਈ ਰੱਖੋ"</string>
diff --git a/core/res/res/values-pl/strings.xml b/core/res/res/values-pl/strings.xml
index a55ca4ca9b82..d62651326645 100644
--- a/core/res/res/values-pl/strings.xml
+++ b/core/res/res/values-pl/strings.xml
@@ -1698,8 +1698,6 @@
<string name="leave_accessibility_shortcut_on" msgid="6543362062336990814">"Użyj skrótu"</string>
<string name="color_inversion_feature_name" msgid="326050048927789012">"Odwrócenie kolorów"</string>
<string name="color_correction_feature_name" msgid="3655077237805422597">"Korekcja kolorów"</string>
- <!-- no translation found for reduce_bright_colors_feature_name (6722364385073799185) -->
- <skip />
<string name="accessibility_shortcut_enabling_service" msgid="5473495203759847687">"Przytrzymano klawisze głośności. Usługa <xliff:g id="SERVICE_NAME">%1$s</xliff:g> została włączona."</string>
<string name="accessibility_shortcut_disabling_service" msgid="8675244165062700619">"Przytrzymano klawisze głośności. Usługa <xliff:g id="SERVICE_NAME">%1$s</xliff:g> została wyłączona."</string>
<string name="accessibility_shortcut_spoken_feedback" msgid="4228997042855695090">"Naciśnij i przytrzymaj oba przyciski głośności przez trzy sekundy, by użyć usługi <xliff:g id="SERVICE_NAME">%1$s</xliff:g>"</string>
diff --git a/core/res/res/values-pt-rBR/strings.xml b/core/res/res/values-pt-rBR/strings.xml
index 66a29566f77a..450fddb025e2 100644
--- a/core/res/res/values-pt-rBR/strings.xml
+++ b/core/res/res/values-pt-rBR/strings.xml
@@ -1654,7 +1654,6 @@
<string name="leave_accessibility_shortcut_on" msgid="6543362062336990814">"Usar atalho"</string>
<string name="color_inversion_feature_name" msgid="326050048927789012">"Inversão de cores"</string>
<string name="color_correction_feature_name" msgid="3655077237805422597">"Correção de cor"</string>
- <string name="reduce_bright_colors_feature_name" msgid="6722364385073799185">"Reduzir cores brilhantes"</string>
<string name="accessibility_shortcut_enabling_service" msgid="5473495203759847687">"Teclas de volume pressionadas. Serviço <xliff:g id="SERVICE_NAME">%1$s</xliff:g> ativado."</string>
<string name="accessibility_shortcut_disabling_service" msgid="8675244165062700619">"Teclas de volume pressionadas. <xliff:g id="SERVICE_NAME">%1$s</xliff:g> desativado."</string>
<string name="accessibility_shortcut_spoken_feedback" msgid="4228997042855695090">"Toque nos dois botões de volume e os mantenha pressionados por três segundo para usar o <xliff:g id="SERVICE_NAME">%1$s</xliff:g>"</string>
diff --git a/core/res/res/values-pt-rPT/strings.xml b/core/res/res/values-pt-rPT/strings.xml
index c40eca0194a7..6862001b874e 100644
--- a/core/res/res/values-pt-rPT/strings.xml
+++ b/core/res/res/values-pt-rPT/strings.xml
@@ -1654,7 +1654,6 @@
<string name="leave_accessibility_shortcut_on" msgid="6543362062336990814">"Utilizar atalho"</string>
<string name="color_inversion_feature_name" msgid="326050048927789012">"Inversão de cores"</string>
<string name="color_correction_feature_name" msgid="3655077237805422597">"Correção da cor"</string>
- <string name="reduce_bright_colors_feature_name" msgid="6722364385073799185">"Reduzir cores brilhantes"</string>
<string name="accessibility_shortcut_enabling_service" msgid="5473495203759847687">"Teclas do volume premidas. Serviço <xliff:g id="SERVICE_NAME">%1$s</xliff:g> ativado."</string>
<string name="accessibility_shortcut_disabling_service" msgid="8675244165062700619">"Teclas de volume premidas. Serviço <xliff:g id="SERVICE_NAME">%1$s</xliff:g> desativado."</string>
<string name="accessibility_shortcut_spoken_feedback" msgid="4228997042855695090">"Prima sem soltar as teclas de volume durante três segundos para utilizar o serviço <xliff:g id="SERVICE_NAME">%1$s</xliff:g>."</string>
diff --git a/core/res/res/values-pt/strings.xml b/core/res/res/values-pt/strings.xml
index 66a29566f77a..450fddb025e2 100644
--- a/core/res/res/values-pt/strings.xml
+++ b/core/res/res/values-pt/strings.xml
@@ -1654,7 +1654,6 @@
<string name="leave_accessibility_shortcut_on" msgid="6543362062336990814">"Usar atalho"</string>
<string name="color_inversion_feature_name" msgid="326050048927789012">"Inversão de cores"</string>
<string name="color_correction_feature_name" msgid="3655077237805422597">"Correção de cor"</string>
- <string name="reduce_bright_colors_feature_name" msgid="6722364385073799185">"Reduzir cores brilhantes"</string>
<string name="accessibility_shortcut_enabling_service" msgid="5473495203759847687">"Teclas de volume pressionadas. Serviço <xliff:g id="SERVICE_NAME">%1$s</xliff:g> ativado."</string>
<string name="accessibility_shortcut_disabling_service" msgid="8675244165062700619">"Teclas de volume pressionadas. <xliff:g id="SERVICE_NAME">%1$s</xliff:g> desativado."</string>
<string name="accessibility_shortcut_spoken_feedback" msgid="4228997042855695090">"Toque nos dois botões de volume e os mantenha pressionados por três segundo para usar o <xliff:g id="SERVICE_NAME">%1$s</xliff:g>"</string>
diff --git a/core/res/res/values-ro/strings.xml b/core/res/res/values-ro/strings.xml
index 29140940ffaa..f9e608fd0b8e 100644
--- a/core/res/res/values-ro/strings.xml
+++ b/core/res/res/values-ro/strings.xml
@@ -1676,8 +1676,6 @@
<string name="leave_accessibility_shortcut_on" msgid="6543362062336990814">"Utilizați comanda rapidă"</string>
<string name="color_inversion_feature_name" msgid="326050048927789012">"Inversarea culorilor"</string>
<string name="color_correction_feature_name" msgid="3655077237805422597">"Corecția culorii"</string>
- <!-- no translation found for reduce_bright_colors_feature_name (6722364385073799185) -->
- <skip />
<string name="accessibility_shortcut_enabling_service" msgid="5473495203759847687">"S-au apăsat lung tastele de volum. S-a activat <xliff:g id="SERVICE_NAME">%1$s</xliff:g>."</string>
<string name="accessibility_shortcut_disabling_service" msgid="8675244165062700619">"S-au apăsat lung tastele de volum. S-a dezactivat <xliff:g id="SERVICE_NAME">%1$s</xliff:g>."</string>
<string name="accessibility_shortcut_spoken_feedback" msgid="4228997042855695090">"Apăsați ambele butoane de volum timp de trei secunde pentru a folosi <xliff:g id="SERVICE_NAME">%1$s</xliff:g>"</string>
diff --git a/core/res/res/values-ru/strings.xml b/core/res/res/values-ru/strings.xml
index e241bb74ebb3..be24770dcc2d 100644
--- a/core/res/res/values-ru/strings.xml
+++ b/core/res/res/values-ru/strings.xml
@@ -1698,8 +1698,6 @@
<string name="leave_accessibility_shortcut_on" msgid="6543362062336990814">"Использовать быстрое включение"</string>
<string name="color_inversion_feature_name" msgid="326050048927789012">"Инверсия цветов"</string>
<string name="color_correction_feature_name" msgid="3655077237805422597">"Коррекция цвета"</string>
- <!-- no translation found for reduce_bright_colors_feature_name (6722364385073799185) -->
- <skip />
<string name="accessibility_shortcut_enabling_service" msgid="5473495203759847687">"Использован жест с кнопками регулировки громкости. Функция \"<xliff:g id="SERVICE_NAME">%1$s</xliff:g>\" включена."</string>
<string name="accessibility_shortcut_disabling_service" msgid="8675244165062700619">"Использован жест с кнопками регулировки громкости. Функция \"<xliff:g id="SERVICE_NAME">%1$s</xliff:g>\" отключена."</string>
<string name="accessibility_shortcut_spoken_feedback" msgid="4228997042855695090">"Чтобы использовать сервис \"<xliff:g id="SERVICE_NAME">%1$s</xliff:g>\", нажмите и удерживайте обе клавиши громкости в течение трех секунд."</string>
diff --git a/core/res/res/values-si/strings.xml b/core/res/res/values-si/strings.xml
index bb2da61b9679..c23e4757805b 100644
--- a/core/res/res/values-si/strings.xml
+++ b/core/res/res/values-si/strings.xml
@@ -1654,8 +1654,6 @@
<string name="leave_accessibility_shortcut_on" msgid="6543362062336990814">"කෙටිමඟ භාවිතා කරන්න"</string>
<string name="color_inversion_feature_name" msgid="326050048927789012">"වර්ණ අපවර්තනය"</string>
<string name="color_correction_feature_name" msgid="3655077237805422597">"වර්ණ නිවැරදි කිරීම"</string>
- <!-- no translation found for reduce_bright_colors_feature_name (6722364385073799185) -->
- <skip />
<string name="accessibility_shortcut_enabling_service" msgid="5473495203759847687">"හඬ පරිමා යතුරු අල්ලා ගන්න <xliff:g id="SERVICE_NAME">%1$s</xliff:g> ක්‍රියාත්මකයි."</string>
<string name="accessibility_shortcut_disabling_service" msgid="8675244165062700619">"හඬ පරිමා යතුරු අල්ලා ගන්න <xliff:g id="SERVICE_NAME">%1$s</xliff:g> ක්‍රියාවිරහිතයි."</string>
<string name="accessibility_shortcut_spoken_feedback" msgid="4228997042855695090">"<xliff:g id="SERVICE_NAME">%1$s</xliff:g> භාවිත කිරීමට හඬ පරිමා යතුරු දෙකම තත්පර තුනකට ඔබාගෙන සිටින්න"</string>
diff --git a/core/res/res/values-sk/strings.xml b/core/res/res/values-sk/strings.xml
index 02f25f526e04..980a9451bff3 100644
--- a/core/res/res/values-sk/strings.xml
+++ b/core/res/res/values-sk/strings.xml
@@ -1698,8 +1698,6 @@
<string name="leave_accessibility_shortcut_on" msgid="6543362062336990814">"Použiť skratku"</string>
<string name="color_inversion_feature_name" msgid="326050048927789012">"Inverzia farieb"</string>
<string name="color_correction_feature_name" msgid="3655077237805422597">"Úprava farieb"</string>
- <!-- no translation found for reduce_bright_colors_feature_name (6722364385073799185) -->
- <skip />
<string name="accessibility_shortcut_enabling_service" msgid="5473495203759847687">"Pridržali ste tlačidlá hlasitosti. Služba <xliff:g id="SERVICE_NAME">%1$s</xliff:g> je zapnutá."</string>
<string name="accessibility_shortcut_disabling_service" msgid="8675244165062700619">"Pridržali ste tlačidlá hlasitosti. Služba <xliff:g id="SERVICE_NAME">%1$s</xliff:g> je vypnutá."</string>
<string name="accessibility_shortcut_spoken_feedback" msgid="4228997042855695090">"Ak chcete používať službu <xliff:g id="SERVICE_NAME">%1$s</xliff:g>, pridržte tri sekundy oba klávesy hlasitosti"</string>
diff --git a/core/res/res/values-sl/strings.xml b/core/res/res/values-sl/strings.xml
index 7fd02432e8c9..573a082e0439 100644
--- a/core/res/res/values-sl/strings.xml
+++ b/core/res/res/values-sl/strings.xml
@@ -1698,8 +1698,6 @@
<string name="leave_accessibility_shortcut_on" msgid="6543362062336990814">"Uporabi bližnjico"</string>
<string name="color_inversion_feature_name" msgid="326050048927789012">"Inverzija barv"</string>
<string name="color_correction_feature_name" msgid="3655077237805422597">"Popravljanje barv"</string>
- <!-- no translation found for reduce_bright_colors_feature_name (6722364385073799185) -->
- <skip />
<string name="accessibility_shortcut_enabling_service" msgid="5473495203759847687">"Tipki za glasnost sta pridržani. Storitev <xliff:g id="SERVICE_NAME">%1$s</xliff:g> je vklopljena."</string>
<string name="accessibility_shortcut_disabling_service" msgid="8675244165062700619">"Tipki za glasnost sta pridržani. Storitev <xliff:g id="SERVICE_NAME">%1$s</xliff:g> je izklopljena."</string>
<string name="accessibility_shortcut_spoken_feedback" msgid="4228997042855695090">"Za uporabo storitve <xliff:g id="SERVICE_NAME">%1$s</xliff:g> pritisnite obe tipki za glasnost in ju pridržite tri sekunde"</string>
diff --git a/core/res/res/values-sq/strings.xml b/core/res/res/values-sq/strings.xml
index 13ad398f16f7..f6f3594d0195 100644
--- a/core/res/res/values-sq/strings.xml
+++ b/core/res/res/values-sq/strings.xml
@@ -1654,8 +1654,6 @@
<string name="leave_accessibility_shortcut_on" msgid="6543362062336990814">"Përdor shkurtoren"</string>
<string name="color_inversion_feature_name" msgid="326050048927789012">"Kthimi i ngjyrës"</string>
<string name="color_correction_feature_name" msgid="3655077237805422597">"Korrigjimi i ngjyrës"</string>
- <!-- no translation found for reduce_bright_colors_feature_name (6722364385073799185) -->
- <skip />
<string name="accessibility_shortcut_enabling_service" msgid="5473495203759847687">"Tastet e volumit të mbajtura shtypur. <xliff:g id="SERVICE_NAME">%1$s</xliff:g> i aktivizuar."</string>
<string name="accessibility_shortcut_disabling_service" msgid="8675244165062700619">"Tastet e volumit të mbajtura shtypur. U çaktivizua \"<xliff:g id="SERVICE_NAME">%1$s</xliff:g>\"."</string>
<string name="accessibility_shortcut_spoken_feedback" msgid="4228997042855695090">"Shtyp dhe mbaj shtypur të dy butonat e volumit për tre sekonda për të përdorur <xliff:g id="SERVICE_NAME">%1$s</xliff:g>"</string>
diff --git a/core/res/res/values-sr/strings.xml b/core/res/res/values-sr/strings.xml
index 42dc695e2587..366d29b15c93 100644
--- a/core/res/res/values-sr/strings.xml
+++ b/core/res/res/values-sr/strings.xml
@@ -1676,8 +1676,6 @@
<string name="leave_accessibility_shortcut_on" msgid="6543362062336990814">"Користи пречицу"</string>
<string name="color_inversion_feature_name" msgid="326050048927789012">"Инверзија боја"</string>
<string name="color_correction_feature_name" msgid="3655077237805422597">"Корекција боја"</string>
- <!-- no translation found for reduce_bright_colors_feature_name (6722364385073799185) -->
- <skip />
<string name="accessibility_shortcut_enabling_service" msgid="5473495203759847687">"Држали сте тастере за јачину звука. Услуга <xliff:g id="SERVICE_NAME">%1$s</xliff:g> је укључена."</string>
<string name="accessibility_shortcut_disabling_service" msgid="8675244165062700619">"Држали сте тастере за јачину звука. Услуга <xliff:g id="SERVICE_NAME">%1$s</xliff:g> је искључена."</string>
<string name="accessibility_shortcut_spoken_feedback" msgid="4228997042855695090">"Притисните и задржите оба тастера за јачину звука три секунде да бисте користили <xliff:g id="SERVICE_NAME">%1$s</xliff:g>"</string>
diff --git a/core/res/res/values-sv/strings.xml b/core/res/res/values-sv/strings.xml
index 66ba07f71055..988fb9392025 100644
--- a/core/res/res/values-sv/strings.xml
+++ b/core/res/res/values-sv/strings.xml
@@ -1654,8 +1654,6 @@
<string name="leave_accessibility_shortcut_on" msgid="6543362062336990814">"Använd kortkommandot"</string>
<string name="color_inversion_feature_name" msgid="326050048927789012">"Inverterade färger"</string>
<string name="color_correction_feature_name" msgid="3655077237805422597">"Färgkorrigering"</string>
- <!-- no translation found for reduce_bright_colors_feature_name (6722364385073799185) -->
- <skip />
<string name="accessibility_shortcut_enabling_service" msgid="5473495203759847687">"Volymknapparna har tryckts ned. <xliff:g id="SERVICE_NAME">%1$s</xliff:g> har aktiverats."</string>
<string name="accessibility_shortcut_disabling_service" msgid="8675244165062700619">"Volymknapparna har tryckts ned. <xliff:g id="SERVICE_NAME">%1$s</xliff:g> har inaktiverats."</string>
<string name="accessibility_shortcut_spoken_feedback" msgid="4228997042855695090">"Tryck och håll båda volymknapparna i tre sekunder för att använda <xliff:g id="SERVICE_NAME">%1$s</xliff:g>"</string>
diff --git a/core/res/res/values-sw/strings.xml b/core/res/res/values-sw/strings.xml
index 5c0ab955eaf4..fd390d80f76a 100644
--- a/core/res/res/values-sw/strings.xml
+++ b/core/res/res/values-sw/strings.xml
@@ -1654,8 +1654,6 @@
<string name="leave_accessibility_shortcut_on" msgid="6543362062336990814">"Tumia Njia ya Mkato"</string>
<string name="color_inversion_feature_name" msgid="326050048927789012">"Ugeuzaji rangi"</string>
<string name="color_correction_feature_name" msgid="3655077237805422597">"Usahihishaji wa rangi"</string>
- <!-- no translation found for reduce_bright_colors_feature_name (6722364385073799185) -->
- <skip />
<string name="accessibility_shortcut_enabling_service" msgid="5473495203759847687">"Vitufe vya sauti vilivyoshikiliwa. Umewasha <xliff:g id="SERVICE_NAME">%1$s</xliff:g>."</string>
<string name="accessibility_shortcut_disabling_service" msgid="8675244165062700619">"Vitufe vya sauti vimeshikiliwa. Umezima <xliff:g id="SERVICE_NAME">%1$s</xliff:g>."</string>
<string name="accessibility_shortcut_spoken_feedback" msgid="4228997042855695090">"Bonyeza na ushikilie vitufe vyote viwili vya sauti kwa sekunde tatu ili utumie <xliff:g id="SERVICE_NAME">%1$s</xliff:g>"</string>
diff --git a/core/res/res/values-ta/strings.xml b/core/res/res/values-ta/strings.xml
index 23b721183543..c764a205fe59 100644
--- a/core/res/res/values-ta/strings.xml
+++ b/core/res/res/values-ta/strings.xml
@@ -1654,8 +1654,6 @@
<string name="leave_accessibility_shortcut_on" msgid="6543362062336990814">"ஷார்ட்கட்டைப் பயன்படுத்து"</string>
<string name="color_inversion_feature_name" msgid="326050048927789012">"கலர் இன்வெர்ஷன்"</string>
<string name="color_correction_feature_name" msgid="3655077237805422597">"வண்ணத் திருத்தம்"</string>
- <!-- no translation found for reduce_bright_colors_feature_name (6722364385073799185) -->
- <skip />
<string name="accessibility_shortcut_enabling_service" msgid="5473495203759847687">"ஒலியளவுக்கான விசைகளைப் பிடித்திருந்தீர்கள். <xliff:g id="SERVICE_NAME">%1$s</xliff:g> ஆன் செய்யப்பட்டது."</string>
<string name="accessibility_shortcut_disabling_service" msgid="8675244165062700619">"ஒலியளவுக்கான விசைகளைப் பிடித்திருந்தீர்கள். <xliff:g id="SERVICE_NAME">%1$s</xliff:g> ஆஃப் செய்யப்பட்டது."</string>
<string name="accessibility_shortcut_spoken_feedback" msgid="4228997042855695090">"<xliff:g id="SERVICE_NAME">%1$s</xliff:g>ஐப் பயன்படுத்த 3 விநாடிகளுக்கு இரண்டு ஒலியளவு பட்டன்களையும் அழுத்திப் பிடிக்கவும்"</string>
diff --git a/core/res/res/values-te/strings.xml b/core/res/res/values-te/strings.xml
index 9b03dcb4b271..23292a2adc76 100644
--- a/core/res/res/values-te/strings.xml
+++ b/core/res/res/values-te/strings.xml
@@ -1654,8 +1654,6 @@
<string name="leave_accessibility_shortcut_on" msgid="6543362062336990814">"సత్వరమార్గాన్ని ఉపయోగించు"</string>
<string name="color_inversion_feature_name" msgid="326050048927789012">"కలర్ మార్పిడి"</string>
<string name="color_correction_feature_name" msgid="3655077237805422597">"కలర్ సరిచేయడం"</string>
- <!-- no translation found for reduce_bright_colors_feature_name (6722364385073799185) -->
- <skip />
<string name="accessibility_shortcut_enabling_service" msgid="5473495203759847687">"వాల్యూమ్ కీలు నొక్కి ఉంచబడ్డాయి. <xliff:g id="SERVICE_NAME">%1$s</xliff:g> ఆన్ చేయబడింది"</string>
<string name="accessibility_shortcut_disabling_service" msgid="8675244165062700619">"వాల్యూమ్ కీలు నొక్కి ఉంచబడ్డాయి. <xliff:g id="SERVICE_NAME">%1$s</xliff:g> ఆఫ్ చేయబడింది"</string>
<string name="accessibility_shortcut_spoken_feedback" msgid="4228997042855695090">"<xliff:g id="SERVICE_NAME">%1$s</xliff:g>ని ఉపయోగించడానికి వాల్యూమ్ కీలు రెండింటినీ 3 సెకన్లు నొక్కి ఉంచండి"</string>
diff --git a/core/res/res/values-th/strings.xml b/core/res/res/values-th/strings.xml
index fc330606ff2c..d5d21c633d0a 100644
--- a/core/res/res/values-th/strings.xml
+++ b/core/res/res/values-th/strings.xml
@@ -1654,8 +1654,6 @@
<string name="leave_accessibility_shortcut_on" msgid="6543362062336990814">"ใช้ทางลัด"</string>
<string name="color_inversion_feature_name" msgid="326050048927789012">"การกลับสี"</string>
<string name="color_correction_feature_name" msgid="3655077237805422597">"การแก้สี"</string>
- <!-- no translation found for reduce_bright_colors_feature_name (6722364385073799185) -->
- <skip />
<string name="accessibility_shortcut_enabling_service" msgid="5473495203759847687">"กดปุ่มปรับระดับเสียงค้างไว้แล้ว เปิด <xliff:g id="SERVICE_NAME">%1$s</xliff:g> แล้ว"</string>
<string name="accessibility_shortcut_disabling_service" msgid="8675244165062700619">"กดปุ่มปรับระดับเสียงค้างไว้แล้ว ปิด <xliff:g id="SERVICE_NAME">%1$s</xliff:g> แล้ว"</string>
<string name="accessibility_shortcut_spoken_feedback" msgid="4228997042855695090">"กดปุ่มปรับระดับเสียงทั้ง 2 ปุ่มค้างไว้ 3 วินาทีเพื่อใช้ <xliff:g id="SERVICE_NAME">%1$s</xliff:g>"</string>
diff --git a/core/res/res/values-tl/strings.xml b/core/res/res/values-tl/strings.xml
index bc6724966b19..f53851d74ff9 100644
--- a/core/res/res/values-tl/strings.xml
+++ b/core/res/res/values-tl/strings.xml
@@ -1654,8 +1654,6 @@
<string name="leave_accessibility_shortcut_on" msgid="6543362062336990814">"Gamitin ang Shortcut"</string>
<string name="color_inversion_feature_name" msgid="326050048927789012">"Pag-invert ng Kulay"</string>
<string name="color_correction_feature_name" msgid="3655077237805422597">"Pagwawasto ng Kulay"</string>
- <!-- no translation found for reduce_bright_colors_feature_name (6722364385073799185) -->
- <skip />
<string name="accessibility_shortcut_enabling_service" msgid="5473495203759847687">"Pinindot nang matagal ang volume keys. Na-on ang <xliff:g id="SERVICE_NAME">%1$s</xliff:g>."</string>
<string name="accessibility_shortcut_disabling_service" msgid="8675244165062700619">"Pinindot nang matagal ang volume keys. Na-off ang <xliff:g id="SERVICE_NAME">%1$s</xliff:g>."</string>
<string name="accessibility_shortcut_spoken_feedback" msgid="4228997042855695090">"Pindutin nang matagal ang parehong volume key sa loob ng tatlong segundo para magamit ang <xliff:g id="SERVICE_NAME">%1$s</xliff:g>"</string>
diff --git a/core/res/res/values-tr/strings.xml b/core/res/res/values-tr/strings.xml
index c870742510d6..5aa336e9b554 100644
--- a/core/res/res/values-tr/strings.xml
+++ b/core/res/res/values-tr/strings.xml
@@ -1654,8 +1654,6 @@
<string name="leave_accessibility_shortcut_on" msgid="6543362062336990814">"Kısayolu Kullan"</string>
<string name="color_inversion_feature_name" msgid="326050048927789012">"Rengi Ters Çevirme"</string>
<string name="color_correction_feature_name" msgid="3655077237805422597">"Renk Düzeltme"</string>
- <!-- no translation found for reduce_bright_colors_feature_name (6722364385073799185) -->
- <skip />
<string name="accessibility_shortcut_enabling_service" msgid="5473495203759847687">"Ses tuşlarını basılı tuttunuz. <xliff:g id="SERVICE_NAME">%1$s</xliff:g> açıldı."</string>
<string name="accessibility_shortcut_disabling_service" msgid="8675244165062700619">"Ses tuşlarını basılı tuttunuz. <xliff:g id="SERVICE_NAME">%1$s</xliff:g> kapatıldı."</string>
<string name="accessibility_shortcut_spoken_feedback" msgid="4228997042855695090">"<xliff:g id="SERVICE_NAME">%1$s</xliff:g> hizmetini kullanmak için her iki ses tuşunu basılı tutun"</string>
diff --git a/core/res/res/values-uk/strings.xml b/core/res/res/values-uk/strings.xml
index 3af955d279c3..da41508b08cf 100644
--- a/core/res/res/values-uk/strings.xml
+++ b/core/res/res/values-uk/strings.xml
@@ -1698,8 +1698,6 @@
<string name="leave_accessibility_shortcut_on" msgid="6543362062336990814">"Використовувати ярлик"</string>
<string name="color_inversion_feature_name" msgid="326050048927789012">"Інверсія кольорів"</string>
<string name="color_correction_feature_name" msgid="3655077237805422597">"Корекція кольорів"</string>
- <!-- no translation found for reduce_bright_colors_feature_name (6722364385073799185) -->
- <skip />
<string name="accessibility_shortcut_enabling_service" msgid="5473495203759847687">"Утримано клавіші гучності. <xliff:g id="SERVICE_NAME">%1$s</xliff:g> увімкнено."</string>
<string name="accessibility_shortcut_disabling_service" msgid="8675244165062700619">"Утримано клавіші гучності. <xliff:g id="SERVICE_NAME">%1$s</xliff:g> вимкнено."</string>
<string name="accessibility_shortcut_spoken_feedback" msgid="4228997042855695090">"Щоб скористатися службою <xliff:g id="SERVICE_NAME">%1$s</xliff:g>, утримуйте обидві клавіші гучності впродовж трьох секунд"</string>
diff --git a/core/res/res/values-ur/strings.xml b/core/res/res/values-ur/strings.xml
index 095be187966f..698e9c47a7cd 100644
--- a/core/res/res/values-ur/strings.xml
+++ b/core/res/res/values-ur/strings.xml
@@ -1654,8 +1654,6 @@
<string name="leave_accessibility_shortcut_on" msgid="6543362062336990814">"شارٹ کٹ استعمال کریں"</string>
<string name="color_inversion_feature_name" msgid="326050048927789012">"رنگوں کی تقلیب"</string>
<string name="color_correction_feature_name" msgid="3655077237805422597">"رنگ کی تصحیح"</string>
- <!-- no translation found for reduce_bright_colors_feature_name (6722364385073799185) -->
- <skip />
<string name="accessibility_shortcut_enabling_service" msgid="5473495203759847687">"والیوم کی کلیدوں کو دبائے رکھا گیا۔ <xliff:g id="SERVICE_NAME">%1$s</xliff:g> آن ہے۔"</string>
<string name="accessibility_shortcut_disabling_service" msgid="8675244165062700619">"والیوم کی کلیدوں کو دبائے رکھا گیا۔ <xliff:g id="SERVICE_NAME">%1$s</xliff:g> آف ہے۔"</string>
<string name="accessibility_shortcut_spoken_feedback" msgid="4228997042855695090">"<xliff:g id="SERVICE_NAME">%1$s</xliff:g> کا استعمال کرنے کے لیے 3 سیکنڈ تک والیوم کی دونوں کلیدوں کو چھوئیں اور دبائے رکھیں"</string>
diff --git a/core/res/res/values-uz/strings.xml b/core/res/res/values-uz/strings.xml
index d1d5115e0ca4..61d29dce50b7 100644
--- a/core/res/res/values-uz/strings.xml
+++ b/core/res/res/values-uz/strings.xml
@@ -1654,8 +1654,6 @@
<string name="leave_accessibility_shortcut_on" msgid="6543362062336990814">"Tezkor ishga tushirishdan foydalanish"</string>
<string name="color_inversion_feature_name" msgid="326050048927789012">"Ranglarni akslantirish"</string>
<string name="color_correction_feature_name" msgid="3655077237805422597">"Rangni tuzatish"</string>
- <!-- no translation found for reduce_bright_colors_feature_name (6722364385073799185) -->
- <skip />
<string name="accessibility_shortcut_enabling_service" msgid="5473495203759847687">"Tovush tugmalari bosib turildi. <xliff:g id="SERVICE_NAME">%1$s</xliff:g> yoqildi."</string>
<string name="accessibility_shortcut_disabling_service" msgid="8675244165062700619">"Tovush tugmalari bosib turildi. <xliff:g id="SERVICE_NAME">%1$s</xliff:g> faolsizlantirildi."</string>
<string name="accessibility_shortcut_spoken_feedback" msgid="4228997042855695090">"<xliff:g id="SERVICE_NAME">%1$s</xliff:g> xizmatidan foydalanish uchun ikkala ovoz balandligi tugmalarini uzoq bosib turing"</string>
diff --git a/core/res/res/values-vi/strings.xml b/core/res/res/values-vi/strings.xml
index 6be3ac864816..fd7205d24730 100644
--- a/core/res/res/values-vi/strings.xml
+++ b/core/res/res/values-vi/strings.xml
@@ -1654,8 +1654,6 @@
<string name="leave_accessibility_shortcut_on" msgid="6543362062336990814">"Sử dụng phím tắt"</string>
<string name="color_inversion_feature_name" msgid="326050048927789012">"Đảo màu"</string>
<string name="color_correction_feature_name" msgid="3655077237805422597">"Chỉnh màu"</string>
- <!-- no translation found for reduce_bright_colors_feature_name (6722364385073799185) -->
- <skip />
<string name="accessibility_shortcut_enabling_service" msgid="5473495203759847687">"Bạn đã giữ các phím âm lượng. <xliff:g id="SERVICE_NAME">%1$s</xliff:g> đã bật."</string>
<string name="accessibility_shortcut_disabling_service" msgid="8675244165062700619">"Bạn đã giữ các phím âm lượng. <xliff:g id="SERVICE_NAME">%1$s</xliff:g> đã tắt."</string>
<string name="accessibility_shortcut_spoken_feedback" msgid="4228997042855695090">"Nhấn và giữ đồng thời cả hai phím âm lượng trong 3 giây để sử dụng <xliff:g id="SERVICE_NAME">%1$s</xliff:g>"</string>
diff --git a/core/res/res/values-zh-rCN/strings.xml b/core/res/res/values-zh-rCN/strings.xml
index 62b8937b5530..16775d5c0324 100644
--- a/core/res/res/values-zh-rCN/strings.xml
+++ b/core/res/res/values-zh-rCN/strings.xml
@@ -1654,8 +1654,6 @@
<string name="leave_accessibility_shortcut_on" msgid="6543362062336990814">"使用快捷方式"</string>
<string name="color_inversion_feature_name" msgid="326050048927789012">"颜色反转"</string>
<string name="color_correction_feature_name" msgid="3655077237805422597">"色彩校正"</string>
- <!-- no translation found for reduce_bright_colors_feature_name (6722364385073799185) -->
- <skip />
<string name="accessibility_shortcut_enabling_service" msgid="5473495203759847687">"已按住音量键。<xliff:g id="SERVICE_NAME">%1$s</xliff:g>已开启。"</string>
<string name="accessibility_shortcut_disabling_service" msgid="8675244165062700619">"已按住音量键。<xliff:g id="SERVICE_NAME">%1$s</xliff:g>已关闭。"</string>
<string name="accessibility_shortcut_spoken_feedback" msgid="4228997042855695090">"同时按住两个音量键 3 秒钟即可使用 <xliff:g id="SERVICE_NAME">%1$s</xliff:g>"</string>
diff --git a/core/res/res/values-zh-rHK/strings.xml b/core/res/res/values-zh-rHK/strings.xml
index 54f2a8720d32..bd13574b5135 100644
--- a/core/res/res/values-zh-rHK/strings.xml
+++ b/core/res/res/values-zh-rHK/strings.xml
@@ -1654,8 +1654,6 @@
<string name="leave_accessibility_shortcut_on" msgid="6543362062336990814">"使用快速鍵"</string>
<string name="color_inversion_feature_name" msgid="326050048927789012">"色彩反轉"</string>
<string name="color_correction_feature_name" msgid="3655077237805422597">"色彩校正"</string>
- <!-- no translation found for reduce_bright_colors_feature_name (6722364385073799185) -->
- <skip />
<string name="accessibility_shortcut_enabling_service" msgid="5473495203759847687">"已按住音量鍵。<xliff:g id="SERVICE_NAME">%1$s</xliff:g> 已開啟。"</string>
<string name="accessibility_shortcut_disabling_service" msgid="8675244165062700619">"已按住音量鍵。<xliff:g id="SERVICE_NAME">%1$s</xliff:g> 已關閉。"</string>
<string name="accessibility_shortcut_spoken_feedback" msgid="4228997042855695090">"㩒住兩個音量鍵 3 秒就可以用 <xliff:g id="SERVICE_NAME">%1$s</xliff:g>"</string>
diff --git a/core/res/res/values-zh-rTW/strings.xml b/core/res/res/values-zh-rTW/strings.xml
index e71f7944056f..0637742f1344 100644
--- a/core/res/res/values-zh-rTW/strings.xml
+++ b/core/res/res/values-zh-rTW/strings.xml
@@ -1654,8 +1654,6 @@
<string name="leave_accessibility_shortcut_on" msgid="6543362062336990814">"使用捷徑"</string>
<string name="color_inversion_feature_name" msgid="326050048927789012">"色彩反轉"</string>
<string name="color_correction_feature_name" msgid="3655077237805422597">"色彩校正"</string>
- <!-- no translation found for reduce_bright_colors_feature_name (6722364385073799185) -->
- <skip />
<string name="accessibility_shortcut_enabling_service" msgid="5473495203759847687">"已按住音量鍵。「<xliff:g id="SERVICE_NAME">%1$s</xliff:g>」已開啟。"</string>
<string name="accessibility_shortcut_disabling_service" msgid="8675244165062700619">"已按住音量鍵。「<xliff:g id="SERVICE_NAME">%1$s</xliff:g>」已關閉。"</string>
<string name="accessibility_shortcut_spoken_feedback" msgid="4228997042855695090">"同時按住調低及調高音量鍵三秒即可使用「<xliff:g id="SERVICE_NAME">%1$s</xliff:g>」"</string>
diff --git a/core/res/res/values-zu/strings.xml b/core/res/res/values-zu/strings.xml
index cc4a3d0c7443..ea97a6e3fd4f 100644
--- a/core/res/res/values-zu/strings.xml
+++ b/core/res/res/values-zu/strings.xml
@@ -1654,8 +1654,6 @@
<string name="leave_accessibility_shortcut_on" msgid="6543362062336990814">"Sebenzisa isinqamuleli"</string>
<string name="color_inversion_feature_name" msgid="326050048927789012">"Ukuguqulwa kombala"</string>
<string name="color_correction_feature_name" msgid="3655077237805422597">"Ukulungiswa kombala"</string>
- <!-- no translation found for reduce_bright_colors_feature_name (6722364385073799185) -->
- <skip />
<string name="accessibility_shortcut_enabling_service" msgid="5473495203759847687">"Ubambe okhiye bevolumu. I-<xliff:g id="SERVICE_NAME">%1$s</xliff:g> ivuliwe."</string>
<string name="accessibility_shortcut_disabling_service" msgid="8675244165062700619">"Ubambe okhiye bevolumu. I-<xliff:g id="SERVICE_NAME">%1$s</xliff:g> ivaliwe."</string>
<string name="accessibility_shortcut_spoken_feedback" msgid="4228997042855695090">"Cindezela uphinde ubambe bobabili okhiye bevolumu ngamasekhondi amathathu ukuze usebenzise i-<xliff:g id="SERVICE_NAME">%1$s</xliff:g>"</string>
diff --git a/core/res/res/values/attrs.xml b/core/res/res/values/attrs.xml
index 64de32c9ad09..b74f96de33b1 100644
--- a/core/res/res/values/attrs.xml
+++ b/core/res/res/values/attrs.xml
@@ -3748,6 +3748,7 @@
<flag name="flagServiceHandlesDoubleTap" value="0x00000800" />
<!-- Has flag {@link android.accessibilityservice.AccessibilityServiceInfo#FLAG_REQUEST_MULTI_FINGER_GESTURES}. -->
<flag name="flagRequestMultiFingerGestures" value="0x00001000" />
+ <flag name="flagSendMotionEvents" value="0x0004000" />
</attr>
<!-- Component name of an activity that allows the user to modify
the settings for this service. This setting cannot be changed at runtime. -->
diff --git a/core/res/res/values/required_apps_managed_device.xml b/core/res/res/values/required_apps_managed_device.xml
index 40db9dfbcd2c..e17d2147c8f0 100644
--- a/core/res/res/values/required_apps_managed_device.xml
+++ b/core/res/res/values/required_apps_managed_device.xml
@@ -21,6 +21,7 @@
Takes precedence over the disallowed apps lists. -->
<string-array translatable="false" name="required_apps_managed_device">
<item>com.android.settings</item>
+ <item>com.android.systemui</item>
<item>com.android.contacts</item>
<item>com.android.dialer</item>
<item>com.android.stk</item> <!-- Required by com.android.phone by certain carriers -->
diff --git a/core/res/res/values/required_apps_managed_profile.xml b/core/res/res/values/required_apps_managed_profile.xml
index c6b37e810f1a..6ed385ad50df 100644
--- a/core/res/res/values/required_apps_managed_profile.xml
+++ b/core/res/res/values/required_apps_managed_profile.xml
@@ -22,6 +22,7 @@
<string-array translatable="false" name="required_apps_managed_profile">
<item>com.android.contacts</item>
<item>com.android.settings</item>
+ <item>com.android.systemui</item>
<item>com.android.providers.downloads</item>
<item>com.android.providers.downloads.ui</item>
<item>com.android.documentsui</item>
diff --git a/core/res/res/values/required_apps_managed_user.xml b/core/res/res/values/required_apps_managed_user.xml
index 8800e5353776..a6fc573a1ebc 100644
--- a/core/res/res/values/required_apps_managed_user.xml
+++ b/core/res/res/values/required_apps_managed_user.xml
@@ -21,6 +21,7 @@
Takes precedence over the disallowed apps lists. -->
<string-array translatable="false" name="required_apps_managed_user">
<item>com.android.settings</item>
+ <item>com.android.systemui</item>
<item>com.android.contacts</item>
<item>com.android.dialer</item>
<item>com.android.stk</item> <!-- Required by com.android.phone by certain carriers -->
diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml
index 645bae728c02..c2120de74d01 100644
--- a/core/res/res/values/strings.xml
+++ b/core/res/res/values/strings.xml
@@ -4494,8 +4494,9 @@
shown in the warning dialog about the accessibility shortcut. -->
<string name="color_correction_feature_name">Color Correction</string>
+ <!-- TODO(b/170970602): remove translatable=false when RBC has official name and strings -->
<!-- Title of Reduce Bright Colors feature, shown in the warning dialog about the accessibility shortcut. [CHAR LIMIT=none] -->
- <string name="reduce_bright_colors_feature_name">Reduce Bright Colors</string>
+ <string name="reduce_bright_colors_feature_name" translatable="false">Reduce Bright Colors</string>
<!-- Text in toast to alert the user that the accessibility shortcut turned on an accessibility service. [CHAR LIMIT=none] -->
<string name="accessibility_shortcut_enabling_service">Held volume keys. <xliff:g id="service_name" example="TalkBack">%1$s</xliff:g> turned on.</string>
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index 4ee912304a4b..caa3dffb60dd 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -200,9 +200,6 @@
<java-symbol type="id" name="action2" />
<java-symbol type="id" name="action3" />
<java-symbol type="id" name="action4" />
- <java-symbol type="id" name="media_seamless" />
- <java-symbol type="id" name="media_seamless_image" />
- <java-symbol type="id" name="media_seamless_text" />
<java-symbol type="id" name="notification_media_seekbar_container" />
<java-symbol type="id" name="notification_media_content" />
<java-symbol type="id" name="notification_media_progress" />
diff --git a/core/tests/coretests/Android.bp b/core/tests/coretests/Android.bp
index c6ef0948174a..e2b975ff78ac 100644
--- a/core/tests/coretests/Android.bp
+++ b/core/tests/coretests/Android.bp
@@ -54,7 +54,6 @@ android_test {
"android.test.mock",
"framework-atb-backward-compatibility",
"framework",
- "icing-java-proto-lite",
"ext",
"framework-res",
],
diff --git a/core/tests/coretests/AndroidManifest.xml b/core/tests/coretests/AndroidManifest.xml
index 38dce150d85c..bb826deb4eff 100644
--- a/core/tests/coretests/AndroidManifest.xml
+++ b/core/tests/coretests/AndroidManifest.xml
@@ -190,6 +190,17 @@
</intent-filter>
</activity>
+ <activity android:name="android.widget.CustomInputConnectionEditTextActivity"
+ android:label="CustomInputConnectionEditTextActivity"
+ android:screenOrientation="portrait"
+ android:exported="true"
+ android:theme="@android:style/Theme.Material.Light">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+ <category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST" />
+ </intent-filter>
+ </activity>
+
<activity android:name="android.widget.TextViewActivity"
android:label="TextViewActivity"
android:screenOrientation="portrait"
diff --git a/core/tests/coretests/apks/install_decl_perm/AndroidManifest.xml b/core/tests/coretests/apks/install_decl_perm/AndroidManifest.xml
index 9a1f0ff7efb0..6a0c4215ce52 100644
--- a/core/tests/coretests/apks/install_decl_perm/AndroidManifest.xml
+++ b/core/tests/coretests/apks/install_decl_perm/AndroidManifest.xml
@@ -17,17 +17,14 @@
package="com.android.frameworks.coretests.install_decl_perm">
<permission android:name="com.android.frameworks.coretests.NORMAL"
- android:permissionGroup="android.permission-group.COST_MONEY"
android:protectionLevel="normal"
android:label="test normal perm" />
<permission android:name="com.android.frameworks.coretests.DANGEROUS"
- android:permissionGroup="android.permission-group.COST_MONEY"
android:protectionLevel="dangerous"
android:label="test dangerous perm" />
<permission android:name="com.android.frameworks.coretests.SIGNATURE"
- android:permissionGroup="android.permission-group.COST_MONEY"
android:protectionLevel="signature"
android:label="test signature perm" />
diff --git a/core/tests/coretests/res/layout/activity_custom_input_connection_edit_text.xml b/core/tests/coretests/res/layout/activity_custom_input_connection_edit_text.xml
new file mode 100644
index 000000000000..c4db8becaf48
--- /dev/null
+++ b/core/tests/coretests/res/layout/activity_custom_input_connection_edit_text.xml
@@ -0,0 +1,33 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ~ Copyright (C) 2020 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License.
+ -->
+
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:orientation="vertical"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent">
+
+ <android.widget.CustomInputConnectionEditText
+ android:id="@+id/edittext1"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content" />
+
+ <android.widget.CustomInputConnectionEditText
+ android:id="@+id/edittext2"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content" />
+
+</LinearLayout>
diff --git a/core/tests/coretests/src/android/text/TextUtilsTest.java b/core/tests/coretests/src/android/text/TextUtilsTest.java
index 4e49118f438c..5362be337ede 100644
--- a/core/tests/coretests/src/android/text/TextUtilsTest.java
+++ b/core/tests/coretests/src/android/text/TextUtilsTest.java
@@ -822,6 +822,25 @@ public class TextUtilsTest {
}
@Test
+ public void testFormatSimple_Width() {
+ assertEquals("42", formatSimple("%1d", 42));
+ assertEquals("42", formatSimple("%2d", 42));
+ assertEquals(" 42", formatSimple("%3d", 42));
+ assertEquals(" 42", formatSimple("%4d", 42));
+ assertEquals(" 42 42", formatSimple("%4d%4d", 42, 42));
+ assertEquals(" -42", formatSimple("%4d", -42));
+ assertEquals(" 42", formatSimple("%10d", 42));
+
+ assertEquals("42", formatSimple("%01d", 42));
+ assertEquals("42", formatSimple("%02d", 42));
+ assertEquals("042", formatSimple("%03d", 42));
+ assertEquals("0042", formatSimple("%04d", 42));
+ assertEquals("00420042", formatSimple("%04d%04d", 42, 42));
+ assertEquals("-042", formatSimple("%04d", -42));
+ assertEquals("0000000042", formatSimple("%010d", 42));
+ }
+
+ @Test
public void testFormatSimple_Empty() {
assertEquals("", formatSimple(""));
}
@@ -833,6 +852,13 @@ public class TextUtilsTest {
}
@Test
+ public void testFormatSimple_Advanced() {
+ assertEquals("crtcl=0x002a:intrsv=Y:grnk=0x0018:gsmry=A:example:rnk=0x0000",
+ formatSimple("crtcl=0x%04x:intrsv=%c:grnk=0x%04x:gsmry=%c:%s:rnk=0x%04x",
+ 42, 'Y', 24, 'A', "example", 0));
+ }
+
+ @Test
public void testFormatSimple_Mismatch() {
try {
formatSimple("%s");
diff --git a/core/tests/coretests/src/android/view/InsetsAnimationControlImplTest.java b/core/tests/coretests/src/android/view/InsetsAnimationControlImplTest.java
index b98ce308ae3b..873627eae696 100644
--- a/core/tests/coretests/src/android/view/InsetsAnimationControlImplTest.java
+++ b/core/tests/coretests/src/android/view/InsetsAnimationControlImplTest.java
@@ -109,7 +109,7 @@ public class InsetsAnimationControlImplTest {
mController = new InsetsAnimationControlImpl(controls,
new Rect(0, 0, 500, 500), mInsetsState, mMockListener, systemBars(),
mMockController, 10 /* durationMs */, new LinearInterpolator(),
- 0 /* animationType */);
+ 0 /* animationType */, null /* translator */);
mController.mReadyDispatched = true;
}
diff --git a/core/tests/coretests/src/android/view/ScrollCaptureClientTest.java b/core/tests/coretests/src/android/view/ScrollCaptureConnectionTest.java
index e6ac2d6c43da..b9cf1e4a234c 100644
--- a/core/tests/coretests/src/android/view/ScrollCaptureClientTest.java
+++ b/core/tests/coretests/src/android/view/ScrollCaptureConnectionTest.java
@@ -47,11 +47,11 @@ import org.mockito.MockitoAnnotations;
import org.mockito.stubbing.Answer;
/**
- * Tests of {@link ScrollCaptureClient}.
+ * Tests of {@link ScrollCaptureConnection}.
*/
@SuppressWarnings("UnnecessaryLocalVariable")
@RunWith(AndroidJUnit4.class)
-public class ScrollCaptureClientTest {
+public class ScrollCaptureConnectionTest {
private final Point mPositionInWindow = new Point(1, 2);
private final Rect mLocalVisibleRect = new Rect(2, 3, 4, 5);
@@ -63,7 +63,7 @@ public class ScrollCaptureClientTest {
@Mock
private Surface mSurface;
@Mock
- private IScrollCaptureController mClientCallbacks;
+ private IScrollCaptureCallbacks mConnectionCallbacks;
@Mock
private View mMockView1;
@Mock
@@ -86,8 +86,8 @@ public class ScrollCaptureClientTest {
@Test
public void testDelayedAction() {
Runnable action = Mockito.mock(Runnable.class);
- ScrollCaptureClient.DelayedAction delayed =
- new ScrollCaptureClient.DelayedAction(mHandler, 100, action);
+ ScrollCaptureConnection.DelayedAction delayed =
+ new ScrollCaptureConnection.DelayedAction(mHandler, 100, action);
try {
Thread.sleep(200);
} catch (InterruptedException ex) {
@@ -103,8 +103,8 @@ public class ScrollCaptureClientTest {
@Test
public void testDelayedAction_cancel() {
Runnable action = Mockito.mock(Runnable.class);
- ScrollCaptureClient.DelayedAction delayed =
- new ScrollCaptureClient.DelayedAction(mHandler, 100, action);
+ ScrollCaptureConnection.DelayedAction delayed =
+ new ScrollCaptureConnection.DelayedAction(mHandler, 100, action);
try {
Thread.sleep(50);
} catch (InterruptedException ex) {
@@ -125,8 +125,8 @@ public class ScrollCaptureClientTest {
@Test
public void testDelayedAction_timeoutNow() {
Runnable action = Mockito.mock(Runnable.class);
- ScrollCaptureClient.DelayedAction delayed =
- new ScrollCaptureClient.DelayedAction(mHandler, 100, action);
+ ScrollCaptureConnection.DelayedAction delayed =
+ new ScrollCaptureConnection.DelayedAction(mHandler, 100, action);
try {
Thread.sleep(50);
} catch (InterruptedException ex) {
@@ -141,7 +141,7 @@ public class ScrollCaptureClientTest {
/** Test creating a client with valid info */
@Test
public void testConstruction() {
- new ScrollCaptureClient(mTarget1, mClientCallbacks);
+ new ScrollCaptureConnection(mTarget1, mConnectionCallbacks);
}
/** Test creating a client fails if arguments are not valid. */
@@ -149,7 +149,7 @@ public class ScrollCaptureClientTest {
public void testConstruction_requiresScrollBounds() {
try {
mTarget1.setScrollBounds(null);
- new ScrollCaptureClient(mTarget1, mClientCallbacks);
+ new ScrollCaptureConnection(mTarget1, mConnectionCallbacks);
fail("An exception was expected.");
} catch (RuntimeException ex) {
// Ignore, expected.
@@ -174,48 +174,51 @@ public class ScrollCaptureClientTest {
};
}
- /** @see ScrollCaptureClient#startCapture(Surface) */
+ /** @see ScrollCaptureConnection#startCapture(Surface) */
@Test
public void testStartCapture() throws Exception {
- final ScrollCaptureClient client = new ScrollCaptureClient(mTarget1, mClientCallbacks);
+ final ScrollCaptureConnection connection = new ScrollCaptureConnection(mTarget1,
+ mConnectionCallbacks);
// Have the session start accepted immediately
doAnswer(runRunnable(1)).when(mCallback1)
.onScrollCaptureStart(any(ScrollCaptureSession.class), any(Runnable.class));
- client.startCapture(mSurface);
+ connection.startCapture(mSurface);
getInstrumentation().waitForIdleSync();
verify(mCallback1, times(1))
.onScrollCaptureStart(any(ScrollCaptureSession.class), any(Runnable.class));
- verify(mClientCallbacks, times(1)).onCaptureStarted();
- verifyNoMoreInteractions(mClientCallbacks);
+ verify(mConnectionCallbacks, times(1)).onCaptureStarted();
+ verifyNoMoreInteractions(mConnectionCallbacks);
}
@Test
public void testStartCaptureTimeout() throws Exception {
- final ScrollCaptureClient client = new ScrollCaptureClient(mTarget1, mClientCallbacks);
- client.startCapture(mSurface);
+ final ScrollCaptureConnection connection = new ScrollCaptureConnection(mTarget1,
+ mConnectionCallbacks);
+ connection.startCapture(mSurface);
// Force timeout to fire
- client.getTimeoutAction().timeoutNow();
+ connection.getTimeoutAction().timeoutNow();
getInstrumentation().waitForIdleSync();
verify(mCallback1, times(1)).onScrollCaptureEnd(any(Runnable.class));
}
- private void startClient(ScrollCaptureClient client) throws Exception {
+ private void startCapture(ScrollCaptureConnection connection) throws Exception {
doAnswer(runRunnable(1)).when(mCallback1)
.onScrollCaptureStart(any(ScrollCaptureSession.class), any(Runnable.class));
- client.startCapture(mSurface);
+ connection.startCapture(mSurface);
getInstrumentation().waitForIdleSync();
- reset(mCallback1, mClientCallbacks);
+ reset(mCallback1, mConnectionCallbacks);
}
- /** @see ScrollCaptureClient#requestImage(Rect) */
+ /** @see ScrollCaptureConnection#requestImage(Rect) */
@Test
public void testRequestImage() throws Exception {
- final ScrollCaptureClient client = new ScrollCaptureClient(mTarget1, mClientCallbacks);
- startClient(client);
+ final ScrollCaptureConnection connection = new ScrollCaptureConnection(mTarget1,
+ mConnectionCallbacks);
+ startCapture(connection);
// Stub the callback to complete the request immediately
doAnswer(reportBufferSent(/* sessionArg */ 0, /* frameNum */ 1L, new Rect(1, 2, 3, 4)))
@@ -223,7 +226,7 @@ public class ScrollCaptureClientTest {
.onScrollCaptureImageRequest(any(ScrollCaptureSession.class), any(Rect.class));
// Make the inbound binder call
- client.requestImage(new Rect(1, 2, 3, 4));
+ connection.requestImage(new Rect(1, 2, 3, 4));
// Wait for handler thread dispatch
getInstrumentation().waitForIdleSync();
@@ -232,18 +235,20 @@ public class ScrollCaptureClientTest {
// Wait for binder thread dispatch
getInstrumentation().waitForIdleSync();
- verify(mClientCallbacks, times(1)).onCaptureBufferSent(eq(1L), eq(new Rect(1, 2, 3, 4)));
+ verify(mConnectionCallbacks, times(1))
+ .onCaptureBufferSent(eq(1L), eq(new Rect(1, 2, 3, 4)));
- verifyNoMoreInteractions(mCallback1, mClientCallbacks);
+ verifyNoMoreInteractions(mCallback1, mConnectionCallbacks);
}
@Test
public void testRequestImageTimeout() throws Exception {
- final ScrollCaptureClient client = new ScrollCaptureClient(mTarget1, mClientCallbacks);
- startClient(client);
+ final ScrollCaptureConnection connection = new ScrollCaptureConnection(mTarget1,
+ mConnectionCallbacks);
+ startCapture(connection);
// Make the inbound binder call
- client.requestImage(new Rect(1, 2, 3, 4));
+ connection.requestImage(new Rect(1, 2, 3, 4));
// Wait for handler thread dispatch
getInstrumentation().waitForIdleSync();
@@ -251,20 +256,21 @@ public class ScrollCaptureClientTest {
any(ScrollCaptureSession.class), eq(new Rect(1, 2, 3, 4)));
// Force timeout to fire
- client.getTimeoutAction().timeoutNow();
+ connection.getTimeoutAction().timeoutNow();
getInstrumentation().waitForIdleSync();
// (callback not stubbed, does nothing)
// Timeout triggers request to end capture
verify(mCallback1, times(1)).onScrollCaptureEnd(any(Runnable.class));
- verifyNoMoreInteractions(mCallback1, mClientCallbacks);
+ verifyNoMoreInteractions(mCallback1, mConnectionCallbacks);
}
- /** @see ScrollCaptureClient#endCapture() */
+ /** @see ScrollCaptureConnection#endCapture() */
@Test
public void testEndCapture() throws Exception {
- final ScrollCaptureClient client = new ScrollCaptureClient(mTarget1, mClientCallbacks);
- startClient(client);
+ final ScrollCaptureConnection connection = new ScrollCaptureConnection(mTarget1,
+ mConnectionCallbacks);
+ startCapture(connection);
// Stub the callback to complete the request immediately
doAnswer(runRunnable(0))
@@ -272,7 +278,7 @@ public class ScrollCaptureClientTest {
.onScrollCaptureEnd(any(Runnable.class));
// Make the inbound binder call
- client.endCapture();
+ connection.endCapture();
// Wait for handler thread dispatch
getInstrumentation().waitForIdleSync();
@@ -280,30 +286,31 @@ public class ScrollCaptureClientTest {
// Wait for binder thread dispatch
getInstrumentation().waitForIdleSync();
- verify(mClientCallbacks, times(1)).onConnectionClosed();
+ verify(mConnectionCallbacks, times(1)).onConnectionClosed();
- verifyNoMoreInteractions(mCallback1, mClientCallbacks);
+ verifyNoMoreInteractions(mCallback1, mConnectionCallbacks);
}
@Test
public void testEndCaptureTimeout() throws Exception {
- final ScrollCaptureClient client = new ScrollCaptureClient(mTarget1, mClientCallbacks);
- startClient(client);
+ final ScrollCaptureConnection connection = new ScrollCaptureConnection(mTarget1,
+ mConnectionCallbacks);
+ startCapture(connection);
// Make the inbound binder call
- client.endCapture();
+ connection.endCapture();
// Wait for handler thread dispatch
getInstrumentation().waitForIdleSync();
verify(mCallback1, times(1)).onScrollCaptureEnd(any(Runnable.class));
// Force timeout to fire
- client.getTimeoutAction().timeoutNow();
+ connection.getTimeoutAction().timeoutNow();
// Wait for binder thread dispatch
getInstrumentation().waitForIdleSync();
- verify(mClientCallbacks, times(1)).onConnectionClosed();
+ verify(mConnectionCallbacks, times(1)).onConnectionClosed();
- verifyNoMoreInteractions(mCallback1, mClientCallbacks);
+ verifyNoMoreInteractions(mCallback1, mConnectionCallbacks);
}
}
diff --git a/core/tests/coretests/src/android/widget/CustomInputConnectionEditText.java b/core/tests/coretests/src/android/widget/CustomInputConnectionEditText.java
new file mode 100644
index 000000000000..2dfc53a591eb
--- /dev/null
+++ b/core/tests/coretests/src/android/widget/CustomInputConnectionEditText.java
@@ -0,0 +1,84 @@
+/*
+ * 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 android.widget;
+
+import android.content.Context;
+import android.util.AttributeSet;
+import android.util.Log;
+import android.view.inputmethod.EditorInfo;
+import android.view.inputmethod.InputConnection;
+import android.view.inputmethod.InputConnectionWrapper;
+
+import java.util.Arrays;
+
+/**
+ * An {@link EditText} component that allows customizing its
+ * {@link android.view.inputmethod.InputConnection}.
+ */
+public class CustomInputConnectionEditText extends EditText {
+ private static final String LOG_TAG = "CustomInputConnectionEditText";
+
+ private String[] mContentMimeTypes;
+ private InputConnectionWrapper mInputConnectionWrapper;
+
+ public CustomInputConnectionEditText(Context context) {
+ super(context);
+ }
+
+ public CustomInputConnectionEditText(Context context, AttributeSet attrs) {
+ super(context, attrs);
+ }
+
+ public CustomInputConnectionEditText(Context context, AttributeSet attrs, int defStyleAttr) {
+ super(context, attrs, defStyleAttr);
+ }
+
+ public CustomInputConnectionEditText(Context context, AttributeSet attrs, int defStyleAttr,
+ int defStyleRes) {
+ super(context, attrs, defStyleAttr, defStyleRes);
+ }
+
+ public void setContentMimeTypes(String[] contentMimeTypes) {
+ mContentMimeTypes = contentMimeTypes;
+ }
+
+ public void setInputConnectionWrapper(InputConnectionWrapper inputConnectionWrapper) {
+ mInputConnectionWrapper = inputConnectionWrapper;
+ }
+
+ @Override
+ public InputConnection onCreateInputConnection(EditorInfo outAttrs) {
+ InputConnection ic = super.onCreateInputConnection(outAttrs);
+ if (ic == null) {
+ Log.d(LOG_TAG, "Not wrapping InputConnection, because super returned null");
+ return null;
+ }
+ if (mInputConnectionWrapper == null) {
+ Log.d(LOG_TAG, "Not wrapping InputConnection, because wrapper is null");
+ return ic;
+ }
+
+ Log.d(LOG_TAG, "Wrapping InputConnection");
+ mInputConnectionWrapper.setTarget(ic);
+
+ Log.d(LOG_TAG,
+ "Setting EditorInfo.contentMimeTypes: " + Arrays.toString(mContentMimeTypes));
+ outAttrs.contentMimeTypes = mContentMimeTypes;
+
+ return mInputConnectionWrapper;
+ }
+}
diff --git a/core/tests/coretests/src/android/widget/CustomInputConnectionEditTextActivity.java b/core/tests/coretests/src/android/widget/CustomInputConnectionEditTextActivity.java
new file mode 100644
index 000000000000..9328a50f900c
--- /dev/null
+++ b/core/tests/coretests/src/android/widget/CustomInputConnectionEditTextActivity.java
@@ -0,0 +1,34 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.widget;
+
+import android.app.Activity;
+import android.os.Bundle;
+
+import com.android.frameworks.coretests.R;
+
+/**
+ * Activity that uses an {@link EditText} component that allows customizing its
+ * {@link android.view.inputmethod.InputConnection}.
+ */
+public class CustomInputConnectionEditTextActivity extends Activity {
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.activity_custom_input_connection_edit_text);
+ }
+}
diff --git a/core/tests/coretests/src/android/widget/TextViewOnReceiveContentCallbackTest.java b/core/tests/coretests/src/android/widget/TextViewOnReceiveContentCallbackTest.java
new file mode 100644
index 000000000000..5112326ea0b6
--- /dev/null
+++ b/core/tests/coretests/src/android/widget/TextViewOnReceiveContentCallbackTest.java
@@ -0,0 +1,262 @@
+/*
+ * 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 android.widget;
+
+import static android.view.OnReceiveContentCallback.Payload.SOURCE_AUTOFILL;
+import static android.view.OnReceiveContentCallback.Payload.SOURCE_CLIPBOARD;
+import static android.view.OnReceiveContentCallback.Payload.SOURCE_DRAG_AND_DROP;
+import static android.view.OnReceiveContentCallback.Payload.SOURCE_INPUT_METHOD;
+import static android.view.OnReceiveContentCallback.Payload.SOURCE_PROCESS_TEXT;
+import static android.widget.TextViewOnReceiveContentCallback.canReuse;
+import static android.widget.espresso.TextViewActions.clickOnTextAtIndex;
+
+import static androidx.test.espresso.Espresso.onView;
+import static androidx.test.espresso.matcher.ViewMatchers.withId;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.verifyNoMoreInteractions;
+import static org.mockito.Mockito.verifyZeroInteractions;
+
+import android.app.Activity;
+import android.app.Instrumentation;
+import android.content.ClipData;
+import android.content.ClipDescription;
+import android.net.Uri;
+import android.os.Bundle;
+import android.util.ArraySet;
+import android.view.OnReceiveContentCallback;
+import android.view.inputmethod.InputConnection;
+import android.view.inputmethod.InputConnectionWrapper;
+import android.view.inputmethod.InputContentInfo;
+
+import androidx.test.InstrumentationRegistry;
+import androidx.test.filters.MediumTest;
+import androidx.test.rule.ActivityTestRule;
+import androidx.test.runner.AndroidJUnit4;
+
+import com.android.frameworks.coretests.R;
+
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mockito;
+
+/**
+ * Tests for {@link TextViewOnReceiveContentCallback}. Most of the test cases are in the CTS test
+ * {@link android.widget.cts.TextViewOnReceiveContentCallbackTest}. This class tests some internal
+ * implementation details, e.g. fallback to the keyboard image API.
+ */
+@RunWith(AndroidJUnit4.class)
+@MediumTest
+public class TextViewOnReceiveContentCallbackTest {
+ private static final Uri SAMPLE_CONTENT_URI = Uri.parse("content://com.example/path");
+
+ @Rule
+ public ActivityTestRule<CustomInputConnectionEditTextActivity> mActivityRule =
+ new ActivityTestRule<>(CustomInputConnectionEditTextActivity.class);
+
+ private Instrumentation mInstrumentation;
+ private Activity mActivity;
+ private CustomInputConnectionEditText mEditText;
+ private TextViewOnReceiveContentCallback mDefaultCallback;
+
+ @Before
+ public void before() {
+ mInstrumentation = InstrumentationRegistry.getInstrumentation();
+ mActivity = mActivityRule.getActivity();
+ mEditText = mActivity.findViewById(R.id.edittext2);
+ mDefaultCallback = mEditText.getEditorForTesting().getDefaultOnReceiveContentCallback();
+ }
+
+ @Test
+ public void testGetSupportedMimeTypes_fallbackToCommitContent() throws Throwable {
+ // Configure the EditText with an EditorInfo/InputConnection that supports some image MIME
+ // types.
+ mEditText.setContentMimeTypes(new String[] {"image/gif", "image/png"});
+ MyInputConnection ic = new MyInputConnection();
+ mEditText.setInputConnectionWrapper(ic);
+
+ // Focus into the EditText.
+ onView(withId(mEditText.getId())).perform(clickOnTextAtIndex(0));
+
+ // Assert that the callback returns the MIME types declared in the EditorInfo in addition to
+ // the default.
+ assertThat(mDefaultCallback.getSupportedMimeTypes(mEditText)).containsExactly(
+ "text/*", "image/gif", "image/png");
+ }
+
+ @Test
+ public void testGetSupportedMimeTypes_fallbackToCommitContent_noMimeTypesInEditorInfo()
+ throws Throwable {
+ // Configure the EditText with an EditorInfo/InputConnection that doesn't declare any MIME
+ // types.
+ mEditText.setContentMimeTypes(new String[0]);
+ MyInputConnection ic = new MyInputConnection();
+ mEditText.setInputConnectionWrapper(ic);
+
+ // Focus into the EditText.
+ onView(withId(mEditText.getId())).perform(clickOnTextAtIndex(0));
+
+ // Assert that the callback returns the default MIME types.
+ assertThat(mDefaultCallback.getSupportedMimeTypes(mEditText)).containsExactly("text/*");
+ }
+
+ @Test
+ public void testOnReceive_fallbackToCommitContent() throws Throwable {
+ // Configure the EditText with an EditorInfo/InputConnection that supports some image MIME
+ // types.
+ mEditText.setContentMimeTypes(new String[] {"image/gif", "image/png"});
+ MyInputConnection ic = new MyInputConnection();
+ mEditText.setInputConnectionWrapper(ic);
+
+ // Focus into the EditText.
+ onView(withId(mEditText.getId())).perform(clickOnTextAtIndex(0));
+
+ // Invoke the callback with SOURCE_AUTOFILL and assert that it triggers a call to
+ // InputConnection.commitContent.
+ ClipDescription description = new ClipDescription("", new String[] {"image/gif"});
+ ClipData clip = new ClipData(description, new ClipData.Item(SAMPLE_CONTENT_URI));
+ OnReceiveContentCallback.Payload payload =
+ new OnReceiveContentCallback.Payload.Builder(clip, SOURCE_AUTOFILL).build();
+ mDefaultCallback.onReceiveContent(mEditText, payload);
+ verify(ic.mMock, times(1))
+ .commitContent(any(InputContentInfo.class), eq(0), eq(null));
+ verifyNoMoreInteractions(ic.mMock);
+ }
+
+ @Test
+ public void testOnReceive_fallbackToCommitContent_noMimeTypesInEditorInfo() throws Throwable {
+ // Configure the EditText with an EditorInfo/InputConnection that doesn't declare any MIME
+ // types.
+ mEditText.setContentMimeTypes(new String[0]);
+ MyInputConnection ic = new MyInputConnection();
+ mEditText.setInputConnectionWrapper(ic);
+
+ // Focus into the EditText.
+ onView(withId(mEditText.getId())).perform(clickOnTextAtIndex(0));
+
+ // Invoke the callback and assert that the InputConnection is not invoked.
+ ClipDescription description = new ClipDescription("", new String[] {"image/gif"});
+ ClipData clip = new ClipData(description, new ClipData.Item(SAMPLE_CONTENT_URI));
+ OnReceiveContentCallback.Payload payload =
+ new OnReceiveContentCallback.Payload.Builder(clip, SOURCE_AUTOFILL).build();
+ mDefaultCallback.onReceiveContent(mEditText, payload);
+ verifyZeroInteractions(ic.mMock);
+ }
+
+ @Test
+ public void testOnReceive_fallbackToCommitContent_sourceOtherThanAutofill() throws Throwable {
+ // Configure the EditText with an EditorInfo/InputConnection that supports some image MIME
+ // types.
+ mEditText.setContentMimeTypes(new String[] {"image/gif", "image/png"});
+ MyInputConnection ic = new MyInputConnection();
+ mEditText.setInputConnectionWrapper(ic);
+
+ // Focus into the EditText.
+ onView(withId(mEditText.getId())).perform(clickOnTextAtIndex(0));
+
+ // Invoke the callback with sources other than SOURCE_AUTOFILL and assert that it does NOT
+ // trigger calls to InputConnection.commitContent.
+ ClipDescription description = new ClipDescription("", new String[] {"image/gif"});
+ ClipData clip = new ClipData(description, new ClipData.Item(SAMPLE_CONTENT_URI));
+ OnReceiveContentCallback.Payload payload =
+ new OnReceiveContentCallback.Payload.Builder(clip, SOURCE_CLIPBOARD).build();
+ mDefaultCallback.onReceiveContent(mEditText, payload);
+ verifyZeroInteractions(ic.mMock);
+
+ payload = new OnReceiveContentCallback.Payload.Builder(clip, SOURCE_INPUT_METHOD).build();
+ mDefaultCallback.onReceiveContent(mEditText, payload);
+ verifyZeroInteractions(ic.mMock);
+
+ payload = new OnReceiveContentCallback.Payload.Builder(clip, SOURCE_DRAG_AND_DROP).build();
+ mDefaultCallback.onReceiveContent(mEditText, payload);
+ verifyZeroInteractions(ic.mMock);
+
+ payload = new OnReceiveContentCallback.Payload.Builder(clip, SOURCE_PROCESS_TEXT).build();
+ mDefaultCallback.onReceiveContent(mEditText, payload);
+ verifyZeroInteractions(ic.mMock);
+ }
+
+ @Test
+ public void testCanReuse() throws Throwable {
+ ArraySet<String> mimeTypes = null;
+ String[] editorContentMimeTypes = new String[0];
+ assertThat(canReuse(mimeTypes, editorContentMimeTypes)).isFalse();
+
+ mimeTypes = new ArraySet<>();
+ editorContentMimeTypes = new String[0];
+ assertThat(canReuse(mimeTypes, editorContentMimeTypes)).isTrue();
+
+ mimeTypes = newArraySet("text/*");
+ editorContentMimeTypes = new String[0];
+ assertThat(canReuse(mimeTypes, editorContentMimeTypes)).isTrue();
+
+ mimeTypes = newArraySet("text/*");
+ editorContentMimeTypes = new String[] {"text/*"};
+ assertThat(canReuse(mimeTypes, editorContentMimeTypes)).isTrue();
+
+ mimeTypes = newArraySet("image/gif", "image/png", "text/*");
+ editorContentMimeTypes = new String[] {"image/gif", "image/png"};
+ assertThat(canReuse(mimeTypes, editorContentMimeTypes)).isTrue();
+
+ mimeTypes = newArraySet("image/gif", "image/png", "text/*");
+ editorContentMimeTypes = new String[] {"image/gif", "image/png", "text/*"};
+ assertThat(canReuse(mimeTypes, editorContentMimeTypes)).isTrue();
+
+ mimeTypes = newArraySet("image/gif", "image/png", "text/*");
+ editorContentMimeTypes = new String[] {"image/gif"};
+ assertThat(canReuse(mimeTypes, editorContentMimeTypes)).isFalse();
+
+ mimeTypes = newArraySet("image/gif", "image/png", "text/*");
+ editorContentMimeTypes = new String[] {"image/gif", "image/png", "image/jpg"};
+ assertThat(canReuse(mimeTypes, editorContentMimeTypes)).isFalse();
+
+ mimeTypes = newArraySet("image/gif", "image/png", "text/*");
+ editorContentMimeTypes = new String[] {"image/gif", "image/jpg"};
+ assertThat(canReuse(mimeTypes, editorContentMimeTypes)).isFalse();
+
+ mimeTypes = newArraySet("image/gif", "image/png", "text/*");
+ editorContentMimeTypes = new String[] {"image/gif", "image/jpg", "text/*"};
+ assertThat(canReuse(mimeTypes, editorContentMimeTypes)).isFalse();
+ }
+
+ private static class MyInputConnection extends InputConnectionWrapper {
+ public final InputConnection mMock;
+
+ MyInputConnection() {
+ super(null, true);
+ mMock = Mockito.mock(InputConnection.class);
+ }
+
+ @Override
+ public boolean commitContent(InputContentInfo inputContentInfo, int flags, Bundle opts) {
+ mMock.commitContent(inputContentInfo, flags, opts);
+ return true;
+ }
+ }
+
+ @SafeVarargs
+ private static <T> ArraySet<T> newArraySet(T ... elements) {
+ return new ArraySet<>(elements);
+ }
+}
diff --git a/core/tests/coretests/src/com/android/internal/os/BinderCallsStatsTest.java b/core/tests/coretests/src/com/android/internal/os/BinderCallsStatsTest.java
index 0eb34a993dec..3117935fb3ed 100644
--- a/core/tests/coretests/src/com/android/internal/os/BinderCallsStatsTest.java
+++ b/core/tests/coretests/src/com/android/internal/os/BinderCallsStatsTest.java
@@ -497,9 +497,9 @@ public class BinderCallsStatsTest {
bcs.callEnded(callSession, REQUEST_SIZE, REPLY_SIZE, WORKSOURCE_UID);
PrintWriter pw = new PrintWriter(new StringWriter());
- bcs.dump(pw, new AppIdToPackageMap(new HashMap<>()), Process.INVALID_UID, true);
+ bcs.dump(pw, new AppIdToPackageMap(new SparseArray<>()), Process.INVALID_UID, true);
- bcs.dump(pw, new AppIdToPackageMap(new HashMap<>()), WORKSOURCE_UID, true);
+ bcs.dump(pw, new AppIdToPackageMap(new SparseArray<>()), WORKSOURCE_UID, true);
}
@Test
diff --git a/data/etc/car/com.android.car.provision.xml b/data/etc/car/com.android.car.provision.xml
index fa51d55ee8a1..14de7fe9587d 100644
--- a/data/etc/car/com.android.car.provision.xml
+++ b/data/etc/car/com.android.car.provision.xml
@@ -16,6 +16,8 @@
-->
<permissions>
<privapp-permissions package="com.android.car.provision">
+ <permission name="android.permission.INTERACT_ACROSS_USERS"/>
+ <permission name="android.permission.QUERY_ALL_PACKAGES"/>
<permission name="android.permission.WRITE_SECURE_SETTINGS"/>
<permission name="android.permission.WRITE_SETTINGS"/>
</privapp-permissions>
diff --git a/data/etc/car/com.google.android.car.kitchensink.xml b/data/etc/car/com.google.android.car.kitchensink.xml
index 59aa45e1f6e4..3a20a9cb1695 100644
--- a/data/etc/car/com.google.android.car.kitchensink.xml
+++ b/data/etc/car/com.google.android.car.kitchensink.xml
@@ -44,5 +44,8 @@
<!-- use for CarServiceTest -->
<permission name="android.permission.SET_ACTIVITY_WATCHER"/>
<permission name="android.permission.WRITE_SECURE_SETTINGS"/>
+
+ <!-- use for rotary fragment to enable/disable packages related to rotary -->
+ <permission name="android.permission.CHANGE_COMPONENT_ENABLED_STATE"/>
</privapp-permissions>
</permissions>
diff --git a/data/etc/platform.xml b/data/etc/platform.xml
index 977703dcd956..301b49181947 100644
--- a/data/etc/platform.xml
+++ b/data/etc/platform.xml
@@ -248,8 +248,7 @@
<library name="android.hidl.base-V1.0-java"
file="/system/framework/android.hidl.base-V1.0-java.jar" />
<library name="android.hidl.manager-V1.0-java"
- file="/system/framework/android.hidl.manager-V1.0-java.jar"
- dependency="android.hidl.base-V1.0-java" />
+ file="/system/framework/android.hidl.manager-V1.0-java.jar" />
<!-- These are the standard packages that are white-listed to always have internet
access while in power save mode, even if they aren't in the foreground. -->
diff --git a/data/etc/services.core.protolog.json b/data/etc/services.core.protolog.json
index 31dae22df454..98c33705255a 100644
--- a/data/etc/services.core.protolog.json
+++ b/data/etc/services.core.protolog.json
@@ -121,6 +121,12 @@
"group": "WM_ERROR",
"at": "com\/android\/server\/wm\/WindowManagerService.java"
},
+ "-1973119651": {
+ "message": "SyncGroup %d: Adding to group: %s",
+ "level": "VERBOSE",
+ "group": "WM_DEBUG_SYNC_ENGINE",
+ "at": "com\/android\/server\/wm\/BLASTSyncEngine.java"
+ },
"-1963461591": {
"message": "Removing %s from %s",
"level": "VERBOSE",
@@ -157,14 +163,20 @@
"group": "WM_DEBUG_STARTING_WINDOW",
"at": "com\/android\/server\/wm\/ActivityRecord.java"
},
+ "-1918702467": {
+ "message": "onSyncFinishedDrawing %s",
+ "level": "VERBOSE",
+ "group": "WM_DEBUG_SYNC_ENGINE",
+ "at": "com\/android\/server\/wm\/WindowContainer.java"
+ },
"-1915280162": {
"message": "Attempted to add wallpaper window with bad token %s. Aborting.",
"level": "WARN",
"group": "WM_ERROR",
"at": "com\/android\/server\/wm\/WindowManagerService.java"
},
- "-1910833551": {
- "message": "SyncSet{%x:%d} Start for %s",
+ "-1905191109": {
+ "message": "SyncGroup %d: Finished!",
"level": "VERBOSE",
"group": "WM_DEBUG_SYNC_ENGINE",
"at": "com\/android\/server\/wm\/BLASTSyncEngine.java"
@@ -607,12 +619,6 @@
"group": "WM_ERROR",
"at": "com\/android\/server\/wm\/WindowManagerService.java"
},
- "-1387080937": {
- "message": "SyncSet{%x:%d} Child ready, now ready=%b and waiting on %d transactions",
- "level": "VERBOSE",
- "group": "WM_DEBUG_SYNC_ENGINE",
- "at": "com\/android\/server\/wm\/BLASTSyncEngine.java"
- },
"-1376035390": {
"message": "No task found",
"level": "DEBUG",
@@ -643,12 +649,6 @@
"group": "WM_DEBUG_BOOT",
"at": "com\/android\/server\/wm\/WindowManagerService.java"
},
- "-1340783230": {
- "message": "SyncSet{%x:%d} Added %s. now waiting on %d transactions",
- "level": "VERBOSE",
- "group": "WM_DEBUG_SYNC_ENGINE",
- "at": "com\/android\/server\/wm\/BLASTSyncEngine.java"
- },
"-1340540100": {
"message": "Creating SnapshotStartingData",
"level": "VERBOSE",
@@ -1177,12 +1177,6 @@
"group": "WM_DEBUG_ORIENTATION",
"at": "com\/android\/server\/wm\/DragState.java"
},
- "-678300709": {
- "message": "SyncSet{%x:%d} Trying to add %s",
- "level": "VERBOSE",
- "group": "WM_DEBUG_SYNC_ENGINE",
- "at": "com\/android\/server\/wm\/BLASTSyncEngine.java"
- },
"-677449371": {
"message": "moveTaskToRootTask: moving task=%d to rootTaskId=%d toTop=%b",
"level": "DEBUG",
@@ -1405,12 +1399,6 @@
"group": "WM_DEBUG_RECENTS_ANIMATIONS",
"at": "com\/android\/server\/wm\/RecentsAnimationController.java"
},
- "-444624452": {
- "message": "REPARENT from: %s to: %s",
- "level": "INFO",
- "group": "WM_SHOW_TRANSACTIONS",
- "at": "com\/android\/server\/wm\/WindowSurfaceController.java"
- },
"-443173857": {
"message": "Moving pending starting from %s to %s",
"level": "VERBOSE",
@@ -1519,12 +1507,6 @@
"group": "WM_DEBUG_STATES",
"at": "com\/android\/server\/wm\/Task.java"
},
- "-324085783": {
- "message": "SURFACE CROP %s: %s",
- "level": "INFO",
- "group": "WM_SHOW_TRANSACTIONS",
- "at": "com\/android\/server\/wm\/WindowSurfaceController.java"
- },
"-322743468": {
"message": "setInputMethodInputTarget %s",
"level": "INFO",
@@ -1603,6 +1585,12 @@
"group": "WM_DEBUG_STATES",
"at": "com\/android\/server\/wm\/Task.java"
},
+ "-230587670": {
+ "message": "SyncGroup %d: Unfinished container: %s",
+ "level": "VERBOSE",
+ "group": "WM_DEBUG_SYNC_ENGINE",
+ "at": "com\/android\/server\/wm\/BLASTSyncEngine.java"
+ },
"-198463978": {
"message": "updateRotationUnchecked: alwaysSendConfiguration=%b forceRelayout=%b",
"level": "VERBOSE",
@@ -1711,12 +1699,6 @@
"group": "WM_DEBUG_APP_TRANSITIONS_ANIM",
"at": "com\/android\/server\/wm\/WindowContainer.java"
},
- "-29233992": {
- "message": "SURFACE CLEAR CROP: %s",
- "level": "INFO",
- "group": "WM_SHOW_TRANSACTIONS",
- "at": "com\/android\/server\/wm\/WindowSurfaceController.java"
- },
"-21399771": {
"message": "activity %s already destroying, skipping request with reason:%s",
"level": "VERBOSE",
@@ -2107,6 +2089,12 @@
"group": "WM_DEBUG_CONFIGURATION",
"at": "com\/android\/server\/wm\/ActivityRecord.java"
},
+ "371173718": {
+ "message": "finishSync cancel=%b for %s",
+ "level": "VERBOSE",
+ "group": "WM_DEBUG_SYNC_ENGINE",
+ "at": "com\/android\/server\/wm\/WindowContainer.java"
+ },
"371641947": {
"message": "Window Manager Crash %s",
"level": "WTF",
@@ -2251,6 +2239,12 @@
"group": "WM_DEBUG_BOOT",
"at": "com\/android\/server\/wm\/WindowManagerService.java"
},
+ "550717438": {
+ "message": "SyncGroup %d: Started for listener: %s",
+ "level": "VERBOSE",
+ "group": "WM_DEBUG_SYNC_ENGINE",
+ "at": "com\/android\/server\/wm\/BLASTSyncEngine.java"
+ },
"556758086": {
"message": "Applying new update lock state '%s' for %s",
"level": "DEBUG",
@@ -2287,12 +2281,6 @@
"group": "WM_DEBUG_IME",
"at": "com\/android\/server\/wm\/ImeInsetsSourceProvider.java"
},
- "590184240": {
- "message": "- NOT adding to sync: visible=%b hasListener=%b",
- "level": "VERBOSE",
- "group": "WM_DEBUG_SYNC_ENGINE",
- "at": "com\/android\/server\/wm\/WindowContainer.java"
- },
"594260577": {
"message": "createWallpaperAnimations()",
"level": "DEBUG",
@@ -2617,6 +2605,18 @@
"group": "WM_DEBUG_LOCKTASK",
"at": "com\/android\/server\/wm\/LockTaskController.java"
},
+ "959486822": {
+ "message": "setSyncGroup #%d on %s",
+ "level": "VERBOSE",
+ "group": "WM_DEBUG_SYNC_ENGINE",
+ "at": "com\/android\/server\/wm\/WindowContainer.java"
+ },
+ "966569777": {
+ "message": "SyncGroup %d: onSurfacePlacement checking %s",
+ "level": "VERBOSE",
+ "group": "WM_DEBUG_SYNC_ENGINE",
+ "at": "com\/android\/server\/wm\/BLASTSyncEngine.java"
+ },
"969323241": {
"message": "Sending new config to %s, config: %s",
"level": "VERBOSE",
@@ -2641,12 +2641,6 @@
"group": "WM_DEBUG_WINDOW_TRANSITIONS",
"at": "com\/android\/server\/wm\/Transition.java"
},
- "1000601037": {
- "message": "SyncSet{%x:%d} Set ready",
- "level": "VERBOSE",
- "group": "WM_DEBUG_SYNC_ENGINE",
- "at": "com\/android\/server\/wm\/BLASTSyncEngine.java"
- },
"1001509841": {
"message": "Auto-PIP allowed, entering PIP mode directly: %s",
"level": "DEBUG",
@@ -2677,6 +2671,12 @@
"group": "WM_ERROR",
"at": "com\/android\/server\/wm\/WindowManagerService.java"
},
+ "1035154109": {
+ "message": "SURFACE backgroundBlur=%o: %s",
+ "level": "INFO",
+ "group": "WM_SHOW_TRANSACTIONS",
+ "at": "com\/android\/server\/wm\/WindowSurfaceController.java"
+ },
"1040675582": {
"message": "Can't report activity configuration update - client not running, activityRecord=%s",
"level": "WARN",
@@ -2809,12 +2809,6 @@
"group": "WM_DEBUG_FOCUS",
"at": "com\/android\/server\/wm\/WindowToken.java"
},
- "1220075598": {
- "message": "SURFACE SIZE %dx%d: %s",
- "level": "INFO",
- "group": "WM_SHOW_TRANSACTIONS",
- "at": "com\/android\/server\/wm\/WindowSurfaceController.java"
- },
"1224184681": {
"message": "No longer Stopped: %s",
"level": "VERBOSE",
@@ -3181,6 +3175,12 @@
"group": "WM_DEBUG_CONFIGURATION",
"at": "com\/android\/server\/wm\/ActivityRecord.java"
},
+ "1689989893": {
+ "message": "SyncGroup %d: Set ready",
+ "level": "VERBOSE",
+ "group": "WM_DEBUG_SYNC_ENGINE",
+ "at": "com\/android\/server\/wm\/BLASTSyncEngine.java"
+ },
"1696210756": {
"message": "Launch on display check: allow launch on public display",
"level": "DEBUG",
@@ -3409,12 +3409,6 @@
"group": "WM_DEBUG_CONFIGURATION",
"at": "com\/android\/server\/wm\/ActivityRecord.java"
},
- "2001924866": {
- "message": "SyncSet{%x:%d} Finished. Reporting %d containers to %s",
- "level": "VERBOSE",
- "group": "WM_DEBUG_SYNC_ENGINE",
- "at": "com\/android\/server\/wm\/BLASTSyncEngine.java"
- },
"2016061474": {
"message": "Prepare app transition: transit=%s %s alwaysKeepCurrent=%b displayId=%d Callers=%s",
"level": "VERBOSE",
diff --git a/errorprone/java/com/google/errorprone/bugpatterns/android/ParcelablePerformanceChecker.java b/errorprone/java/com/google/errorprone/bugpatterns/android/EfficientParcelableChecker.java
index d5243164abdc..c29a095ecc1b 100644
--- a/errorprone/java/com/google/errorprone/bugpatterns/android/ParcelablePerformanceChecker.java
+++ b/errorprone/java/com/google/errorprone/bugpatterns/android/EfficientParcelableChecker.java
@@ -43,10 +43,10 @@ import com.sun.source.tree.Tree;
*/
@AutoService(BugChecker.class)
@BugPattern(
- name = "AndroidFrameworkParcelablePerformance",
+ name = "AndroidFrameworkEfficientParcelable",
summary = "Verifies Parcelable performance best-practices",
severity = WARNING)
-public final class ParcelablePerformanceChecker extends BugChecker
+public final class EfficientParcelableChecker extends BugChecker
implements MethodInvocationTreeMatcher {
private static final Matcher<Tree> INSIDE_WRITE_TO_PARCEL = allOf(
enclosingClass(isSubtypeOf("android.os.Parcelable")),
diff --git a/errorprone/java/com/google/errorprone/bugpatterns/android/EfficientStringsChecker.java b/errorprone/java/com/google/errorprone/bugpatterns/android/EfficientStringsChecker.java
index 3fbd51deec65..3a0fbd33933f 100644
--- a/errorprone/java/com/google/errorprone/bugpatterns/android/EfficientStringsChecker.java
+++ b/errorprone/java/com/google/errorprone/bugpatterns/android/EfficientStringsChecker.java
@@ -18,7 +18,11 @@ package com.google.errorprone.bugpatterns.android;
import static com.google.errorprone.BugPattern.SeverityLevel.WARNING;
import static com.google.errorprone.matchers.Matchers.allOf;
+import static com.google.errorprone.matchers.Matchers.anyOf;
import static com.google.errorprone.matchers.Matchers.contains;
+import static com.google.errorprone.matchers.Matchers.hasModifier;
+import static com.google.errorprone.matchers.Matchers.instanceMethod;
+import static com.google.errorprone.matchers.Matchers.isSubtypeOf;
import static com.google.errorprone.matchers.Matchers.kindIs;
import static com.google.errorprone.matchers.Matchers.methodInvocation;
import static com.google.errorprone.matchers.Matchers.not;
@@ -28,19 +32,28 @@ import com.google.auto.service.AutoService;
import com.google.errorprone.BugPattern;
import com.google.errorprone.VisitorState;
import com.google.errorprone.bugpatterns.BugChecker;
+import com.google.errorprone.bugpatterns.BugChecker.CompoundAssignmentTreeMatcher;
import com.google.errorprone.bugpatterns.BugChecker.MethodInvocationTreeMatcher;
+import com.google.errorprone.bugpatterns.BugChecker.NewClassTreeMatcher;
import com.google.errorprone.matchers.Description;
import com.google.errorprone.matchers.Matcher;
import com.google.errorprone.predicates.TypePredicate;
import com.google.errorprone.util.ASTHelpers;
+import com.sun.source.tree.BinaryTree;
+import com.sun.source.tree.CompoundAssignmentTree;
import com.sun.source.tree.ExpressionTree;
import com.sun.source.tree.LiteralTree;
import com.sun.source.tree.MethodInvocationTree;
+import com.sun.source.tree.NewClassTree;
+import com.sun.source.tree.Tree;
import com.sun.source.tree.Tree.Kind;
import com.sun.tools.javac.code.Symbol.VarSymbol;
import com.sun.tools.javac.code.Type;
import java.util.List;
+import java.util.Objects;
+
+import javax.lang.model.element.Modifier;
/**
* Android offers several efficient alternatives to some upstream {@link String}
@@ -52,7 +65,7 @@ import java.util.List;
summary = "Verifies efficient Strings best-practices",
severity = WARNING)
public final class EfficientStringsChecker extends BugChecker
- implements MethodInvocationTreeMatcher {
+ implements MethodInvocationTreeMatcher, NewClassTreeMatcher, CompoundAssignmentTreeMatcher {
private static final Matcher<ExpressionTree> FORMAT_CALL = methodInvocation(
staticMethod().onClass("java.lang.String").named("format"));
@@ -60,17 +73,37 @@ public final class EfficientStringsChecker extends BugChecker
staticMethod().onClass(withSimpleName("Preconditions")).withAnyName());
private static final Matcher<ExpressionTree> OBJECTS_CALL = methodInvocation(
staticMethod().onClass("java.util.Objects").named("requireNonNull"));
+ private static final Matcher<ExpressionTree> APPEND_CALL = methodInvocation(
+ instanceMethod().onExactClass("java.lang.StringBuilder")
+ .withSignature("append(java.lang.String)"));
+
+ /**
+ * Identify any dynamic values that will likely cause us to allocate a
+ * transparent StringBuilder.
+ */
+ private static final Matcher<ExpressionTree> DYNAMIC_VALUE = anyOf(
+ allOf(kindIs(Kind.MEMBER_SELECT),
+ not(allOf(hasModifier(Modifier.STATIC), hasModifier(Modifier.FINAL)))),
+ allOf(kindIs(Kind.IDENTIFIER),
+ not(allOf(hasModifier(Modifier.STATIC), hasModifier(Modifier.FINAL)))),
+ kindIs(Kind.METHOD_INVOCATION));
+
+ /**
+ * Identify an expression that is either a direct "+" binary operator, or
+ * that contains a "+" binary operator nested deep inside.
+ */
+ private static final Matcher<Tree> PLUS = anyOf(kindIs(Kind.PLUS),
+ contains(BinaryTree.class, kindIs(Kind.PLUS)));
/**
- * Match an expression which combines both string literals any other dynamic
- * values, since these allocate a transparent StringBuilder.
- * <p>
- * This won't match a single isolated string literal, or a chain consisting
- * of only string literals, since those don't require dynamic construction.
+ * Identify an expression that is using a "+" binary operator to combine
+ * dynamic values, which will likely end up allocating a transparent
+ * {@link StringBuilder}.
*/
- private static final Matcher<ExpressionTree> CONTAINS_DYNAMIC_STRING = allOf(
- contains(ExpressionTree.class, kindIs(Kind.STRING_LITERAL)),
- contains(ExpressionTree.class, not(kindIs(Kind.STRING_LITERAL))));
+ private static final Matcher<Tree> PLUS_DYNAMIC_VALUE = allOf(
+ PLUS, contains(ExpressionTree.class, DYNAMIC_VALUE));
+
+ private static final Matcher<Tree> IS_STRING_BUFFER = isSubtypeOf("java.lang.StringBuffer");
@Override
public Description matchMethodInvocation(MethodInvocationTree tree, VisitorState state) {
@@ -98,9 +131,9 @@ public final class EfficientStringsChecker extends BugChecker
} else if (PRECONDITIONS_CALL.matches(tree, state)
|| OBJECTS_CALL.matches(tree, state)) {
final List<? extends ExpressionTree> args = tree.getArguments();
- for (int i = 1 ; i < args.size(); i++) {
- final ExpressionTree arg = args.get(i);
- if (CONTAINS_DYNAMIC_STRING.matches(arg, state)) {
+ if (args.size() > 1) {
+ final ExpressionTree arg = args.get(1);
+ if (PLUS_DYNAMIC_VALUE.matches(arg, state)) {
return buildDescription(arg)
.setMessage("Building dynamic messages is discouraged, since they "
+ "always allocate a transparent StringBuilder, even in "
@@ -108,6 +141,37 @@ public final class EfficientStringsChecker extends BugChecker
.build();
}
}
+ } else if (APPEND_CALL.matches(tree, state)) {
+ final ExpressionTree arg = tree.getArguments().get(0);
+ if (PLUS_DYNAMIC_VALUE.matches(arg, state)) {
+ return buildDescription(arg)
+ .setMessage("Call append() directly for each argument instead of "
+ + "allocating a transparent StringBuilder")
+ .build();
+ }
+ }
+ return Description.NO_MATCH;
+ }
+
+ @Override
+ public Description matchNewClass(NewClassTree tree, VisitorState state) {
+ if (IS_STRING_BUFFER.matches(tree, state)) {
+ return buildDescription(tree)
+ .setMessage("Strongly encouraged to replace with StringBuilder "
+ + "which avoids synchronization overhead")
+ .build();
+ }
+ return Description.NO_MATCH;
+ }
+
+ @Override
+ public Description matchCompoundAssignment(CompoundAssignmentTree tree, VisitorState state) {
+ if (tree.getKind() == Kind.PLUS_ASSIGNMENT && "java.lang.String"
+ .equals(String.valueOf(ASTHelpers.getType(tree.getVariable())))) {
+ return buildDescription(tree)
+ .setMessage("Strongly encouraged to replace with StringBuilder "
+ + "which avoids transparent StringBuilder allocations")
+ .build();
}
return Description.NO_MATCH;
}
@@ -116,8 +180,10 @@ public final class EfficientStringsChecker extends BugChecker
for (int i = 0; i < format.length(); i++) {
char c = format.charAt(i);
if (c == '%') {
- i++;
- c = format.charAt(i);
+ c = format.charAt(++i);
+ while ('0' <= c && c <= '9') {
+ c = format.charAt(++i);
+ }
switch (c) {
case 'b':
case 'c':
diff --git a/errorprone/tests/java/com/google/errorprone/bugpatterns/android/ParcelablePerformanceCheckerTest.java b/errorprone/tests/java/com/google/errorprone/bugpatterns/android/EfficientParcelableCheckerTest.java
index 75c76e32f00e..a40414bc1cef 100644
--- a/errorprone/tests/java/com/google/errorprone/bugpatterns/android/ParcelablePerformanceCheckerTest.java
+++ b/errorprone/tests/java/com/google/errorprone/bugpatterns/android/EfficientParcelableCheckerTest.java
@@ -24,13 +24,13 @@ import org.junit.runner.RunWith;
import org.junit.runners.JUnit4;
@RunWith(JUnit4.class)
-public class ParcelablePerformanceCheckerTest {
+public class EfficientParcelableCheckerTest {
private CompilationTestHelper compilationHelper;
@Before
public void setUp() {
compilationHelper = CompilationTestHelper.newInstance(
- ParcelablePerformanceChecker.class, getClass());
+ EfficientParcelableChecker.class, getClass());
}
@Test
diff --git a/errorprone/tests/java/com/google/errorprone/bugpatterns/android/EfficientStringsCheckerTest.java b/errorprone/tests/java/com/google/errorprone/bugpatterns/android/EfficientStringsCheckerTest.java
index a755564d52dd..48e4ad11f9bf 100644
--- a/errorprone/tests/java/com/google/errorprone/bugpatterns/android/EfficientStringsCheckerTest.java
+++ b/errorprone/tests/java/com/google/errorprone/bugpatterns/android/EfficientStringsCheckerTest.java
@@ -41,9 +41,13 @@ public class EfficientStringsCheckerTest {
assertTrue(EfficientStringsChecker.isSimple(""));
assertTrue(EfficientStringsChecker.isSimple("%s"));
assertTrue(EfficientStringsChecker.isSimple("String %s%s and %%%% number %d%d together"));
+ assertTrue(EfficientStringsChecker.isSimple("%04d"));
+ assertTrue(EfficientStringsChecker.isSimple("%02x:%02x:%02x"));
+ assertTrue(EfficientStringsChecker.isSimple("%10d"));
- assertFalse(EfficientStringsChecker.isSimple("%04d"));
- assertFalse(EfficientStringsChecker.isSimple("%02x:%02x:%02x"));
+ assertFalse(EfficientStringsChecker.isSimple("%0.4f"));
+ assertFalse(EfficientStringsChecker.isSimple("%t"));
+ assertFalse(EfficientStringsChecker.isSimple("%1$s"));
}
@Test
@@ -58,6 +62,7 @@ public class EfficientStringsCheckerTest {
" String.format(\"foo %s bar\", str);",
" // BUG: Diagnostic contains:",
" String.format(\"foo %d bar\", 42);",
+ " // BUG: Diagnostic contains:",
" String.format(\"foo %04d bar\", 42);",
" }",
" public void exampleLocale(String str) {",
@@ -66,6 +71,7 @@ public class EfficientStringsCheckerTest {
" String.format(Locale.US, \"foo %s bar\", str);",
" // BUG: Diagnostic contains:",
" String.format(Locale.US, \"foo %d bar\", 42);",
+ " // BUG: Diagnostic contains:",
" String.format(Locale.US, \"foo %04d bar\", 42);",
" }",
"}")
@@ -116,4 +122,126 @@ public class EfficientStringsCheckerTest {
"}")
.doTest();
}
+
+ @Test
+ public void testPreconditions_Complex() {
+ compilationHelper
+ .addSourceFile("/android/util/Preconditions.java")
+ .addSourceLines("Example.java",
+ "import android.util.Preconditions;",
+ "public class Example {",
+ " String[] classArray = new String[] { null };",
+ " String classVar;",
+ " static final String CONST_VAR = \"baz\";",
+ " public String classMethod() { return \"baz\"; }",
+ " public static final String CONST_METHOD() { return \"baz\"; }",
+ " public void checkNotNull(Example example, Object val) {",
+ " String methodVar = \"baz\";",
+ " Preconditions.checkNotNull(val, \"foo\");",
+ " Preconditions.checkNotNull(val, (\"foo\"));",
+ " Preconditions.checkNotNull(val, classArray[0]);",
+ " Preconditions.checkNotNull(val, classVar);",
+ " Preconditions.checkNotNull(val, CONST_VAR);",
+ " Preconditions.checkNotNull(val, example.classVar);",
+ " Preconditions.checkNotNull(val, Example.CONST_VAR);",
+ " Preconditions.checkNotNull(val, methodVar);",
+ " Preconditions.checkNotNull(val, classMethod());",
+ " Preconditions.checkNotNull(val, CONST_METHOD());",
+ " Preconditions.checkNotNull(val, \"foo\" + \"bar\");",
+ " Preconditions.checkNotNull(val, (\"foo\" + \"bar\"));",
+ " // BUG: Diagnostic contains:",
+ " Preconditions.checkNotNull(val, \"foo\" + classArray[0]);",
+ " // BUG: Diagnostic contains:",
+ " Preconditions.checkNotNull(val, \"foo\" + classVar);",
+ " Preconditions.checkNotNull(val, \"foo\" + CONST_VAR);",
+ " // BUG: Diagnostic contains:",
+ " Preconditions.checkNotNull(val, \"foo\" + methodVar);",
+ " // BUG: Diagnostic contains:",
+ " Preconditions.checkNotNull(val, \"foo\" + classMethod());",
+ " // BUG: Diagnostic contains:",
+ " Preconditions.checkNotNull(val, \"foo\" + CONST_METHOD());",
+ " }",
+ "}")
+ .doTest();
+ }
+
+ @Test
+ public void testStringBuffer() {
+ compilationHelper
+ .addSourceLines("Example.java",
+ "public class Example {",
+ " public void example() {",
+ " // BUG: Diagnostic contains:",
+ " StringBuffer sb = new StringBuffer();",
+ " }",
+ "}")
+ .doTest();
+ }
+
+ @Test
+ public void testStringBuilder() {
+ compilationHelper
+ .addSourceLines("Example.java",
+ "public class Example {",
+ " StringBuilder sb = new StringBuilder();",
+ " String[] classArray = new String[] { null };",
+ " String classVar;",
+ " static final String CONST_VAR = \"baz\";",
+ " public String classMethod() { return \"baz\"; }",
+ " public static final String CONST_METHOD() { return \"baz\"; }",
+ " public void generic(Example example) {",
+ " sb.append(\"foo\");",
+ " sb.append(\"foo\" + \"bar\");",
+ " sb.append(classArray[0]);",
+ " sb.append(example.classArray[0]);",
+ " sb.append(classVar);",
+ " sb.append(CONST_VAR);",
+ " sb.append(example.classVar);",
+ " sb.append(Example.CONST_VAR);",
+ " sb.append(classMethod());",
+ " sb.append(CONST_METHOD());",
+ " }",
+ " public void string(String val) {",
+ " sb.append(\"foo\").append(val);",
+ " sb.append(\"foo\").append(val != null ? \"bar\" : \"baz\");",
+ " // BUG: Diagnostic contains:",
+ " sb.append(\"foo\" + val);",
+ " }",
+ " public void number(int val) {",
+ " sb.append(\"foo\").append(val);",
+ " sb.append(\"foo\").append(val + val);",
+ " sb.append(\"foo\").append(val > 0 ? \"bar\" : \"baz\");",
+ " // BUG: Diagnostic contains:",
+ " sb.append(\"foo\" + val);",
+ " // BUG: Diagnostic contains:",
+ " sb.append(\"foo\" + String.valueOf(val));",
+ " // BUG: Diagnostic contains:",
+ " sb.append(\"foo\" + Integer.toString(val));",
+ " }",
+ "}")
+ .doTest();
+ }
+
+ @Test
+ public void testPlusAssignment() {
+ compilationHelper
+ .addSourceLines("Example.java",
+ "public class Example {",
+ " public void string(String val) {",
+ " String s = \"foo\";",
+ " // BUG: Diagnostic contains:",
+ " s += \"bar\";",
+ " // BUG: Diagnostic contains:",
+ " s += val;",
+ " // BUG: Diagnostic contains:",
+ " s += (\"bar\" + \"baz\");",
+ " }",
+ " public void number(int val) {",
+ " int other = 42;",
+ " other += 24;",
+ " other += val;",
+ " }",
+ "}")
+ .doTest();
+ }
}
diff --git a/graphics/java/android/graphics/Typeface.java b/graphics/java/android/graphics/Typeface.java
index a2dd9a8322b6..ecb0ff43a9e2 100644
--- a/graphics/java/android/graphics/Typeface.java
+++ b/graphics/java/android/graphics/Typeface.java
@@ -768,7 +768,7 @@ public class Typeface {
public @NonNull CustomFallbackBuilder addCustomFallback(@NonNull FontFamily family) {
Preconditions.checkNotNull(family);
Preconditions.checkArgument(mFamilies.size() < getMaxCustomFallbackCount(),
- "Custom fallback limit exceeded(" + getMaxCustomFallbackCount() + ")");
+ "Custom fallback limit exceeded(%d)", getMaxCustomFallbackCount());
mFamilies.add(family);
return this;
}
diff --git a/graphics/java/android/graphics/text/MeasuredText.java b/graphics/java/android/graphics/text/MeasuredText.java
index b6d8fa19fca8..31c3d09ed5b1 100644
--- a/graphics/java/android/graphics/text/MeasuredText.java
+++ b/graphics/java/android/graphics/text/MeasuredText.java
@@ -80,11 +80,11 @@ public class MeasuredText {
public @FloatRange(from = 0.0) @Px float getWidth(
@IntRange(from = 0) int start, @IntRange(from = 0) int end) {
Preconditions.checkArgument(0 <= start && start <= mChars.length,
- "start(" + start + ") must be 0 <= start <= " + mChars.length);
+ "start(%d) must be 0 <= start <= %d", start, mChars.length);
Preconditions.checkArgument(0 <= end && end <= mChars.length,
- "end(" + end + ") must be 0 <= end <= " + mChars.length);
+ "end(%d) must be 0 <= end <= %d", end, mChars.length);
Preconditions.checkArgument(start <= end,
- "start(" + start + ") is larger than end(" + end + ")");
+ "start(%d) is larger than end(%d)", start, end);
return nGetWidth(mNativePtr, start, end);
}
@@ -107,11 +107,11 @@ public class MeasuredText {
public void getBounds(@IntRange(from = 0) int start, @IntRange(from = 0) int end,
@NonNull Rect rect) {
Preconditions.checkArgument(0 <= start && start <= mChars.length,
- "start(" + start + ") must be 0 <= start <= " + mChars.length);
+ "start(%d) must be 0 <= start <= %d", start, mChars.length);
Preconditions.checkArgument(0 <= end && end <= mChars.length,
- "end(" + end + ") must be 0 <= end <= " + mChars.length);
+ "end(%d) must be 0 <= end <= %d", end, mChars.length);
Preconditions.checkArgument(start <= end,
- "start(" + start + ") is larger than end(" + end + ")");
+ "start(%d) is larger than end(%d)", start, end);
Preconditions.checkNotNull(rect);
nGetBounds(mNativePtr, mChars, start, end, rect);
}
@@ -123,7 +123,7 @@ public class MeasuredText {
*/
public @FloatRange(from = 0.0f) @Px float getCharWidthAt(@IntRange(from = 0) int offset) {
Preconditions.checkArgument(0 <= offset && offset < mChars.length,
- "offset(" + offset + ") is larger than text length: " + mChars.length);
+ "offset(%d) is larger than text length %d" + offset, mChars.length);
return nGetCharWidthAt(mNativePtr, offset);
}
diff --git a/graphics/java/android/graphics/text/PositionedGlyphs.java b/graphics/java/android/graphics/text/PositionedGlyphs.java
index ecbc45c54d85..c2de0acebca9 100644
--- a/graphics/java/android/graphics/text/PositionedGlyphs.java
+++ b/graphics/java/android/graphics/text/PositionedGlyphs.java
@@ -170,9 +170,8 @@ public final class PositionedGlyphs {
* @hide
*
* @param layoutPtr the address of native layout object.
- * @param paint a paint object
*/
- public PositionedGlyphs(long layoutPtr, @NonNull Paint paint, float xOffset, float yOffset) {
+ public PositionedGlyphs(long layoutPtr, float xOffset, float yOffset) {
mLayoutPtr = layoutPtr;
int glyphCount = nGetGlyphCount(layoutPtr);
mFonts = new ArrayList<>(glyphCount);
diff --git a/graphics/java/android/graphics/text/TextRunShaper.java b/graphics/java/android/graphics/text/TextRunShaper.java
index b73436e36ae0..8459e7bfe191 100644
--- a/graphics/java/android/graphics/text/TextRunShaper.java
+++ b/graphics/java/android/graphics/text/TextRunShaper.java
@@ -72,7 +72,7 @@ public class TextRunShaper {
return new PositionedGlyphs(
nativeShapeTextRun(text, start, count, contextStart, contextCount, isRtl,
paint.getNativeInstance()),
- paint, xOffset, yOffset);
+ xOffset, yOffset);
}
/**
@@ -104,7 +104,7 @@ public class TextRunShaper {
nativeShapeTextRun(
(String) text, start, count, contextStart, contextCount, isRtl,
paint.getNativeInstance()),
- paint, xOffset, yOffset);
+ xOffset, yOffset);
} else {
char[] buf = new char[contextCount];
TextUtils.getChars(text, contextStart, contextStart + contextCount, buf, 0);
@@ -112,7 +112,7 @@ public class TextRunShaper {
nativeShapeTextRun(
buf, start - contextStart, count,
0, contextCount, isRtl, paint.getNativeInstance()),
- paint, xOffset, yOffset);
+ xOffset, yOffset);
}
}
diff --git a/keystore/java/android/security/keystore/AttestationUtils.java b/keystore/java/android/security/keystore/AttestationUtils.java
index c8d4be319bab..f48da74eb397 100644
--- a/keystore/java/android/security/keystore/AttestationUtils.java
+++ b/keystore/java/android/security/keystore/AttestationUtils.java
@@ -20,7 +20,6 @@ import android.Manifest;
import android.annotation.NonNull;
import android.annotation.RequiresPermission;
import android.annotation.SystemApi;
-import android.annotation.TestApi;
import android.content.Context;
import android.os.Build;
import android.security.KeyStore;
@@ -44,7 +43,6 @@ import java.util.Set;
* @hide
*/
@SystemApi
-@TestApi
public abstract class AttestationUtils {
private AttestationUtils() {
}
diff --git a/keystore/java/android/security/keystore/DeviceIdAttestationException.java b/keystore/java/android/security/keystore/DeviceIdAttestationException.java
index 8ba0317845d0..4f9f9e633a98 100644
--- a/keystore/java/android/security/keystore/DeviceIdAttestationException.java
+++ b/keystore/java/android/security/keystore/DeviceIdAttestationException.java
@@ -18,7 +18,6 @@ package android.security.keystore;
import android.annotation.Nullable;
import android.annotation.SystemApi;
-import android.annotation.TestApi;
/**
* Thrown when {@link AttestationUtils} is unable to attest the given device ids.
@@ -26,7 +25,6 @@ import android.annotation.TestApi;
* @hide
*/
@SystemApi
-@TestApi
public class DeviceIdAttestationException extends Exception {
/**
* Constructs a new {@code DeviceIdAttestationException} with the current stack trace and the
diff --git a/libs/WindowManager/Shell/res/raw/wm_shell_protolog.json b/libs/WindowManager/Shell/res/raw/wm_shell_protolog.json
index 44744bc227a9..02bf38504725 100644
--- a/libs/WindowManager/Shell/res/raw/wm_shell_protolog.json
+++ b/libs/WindowManager/Shell/res/raw/wm_shell_protolog.json
@@ -1,12 +1,6 @@
{
"version": "1.0.0",
"messages": {
- "-1823823103": {
- "message": "Add listener for types=%s listener=%s",
- "level": "VERBOSE",
- "group": "WM_SHELL_TASK_ORG",
- "at": "com\/android\/wm\/shell\/ShellTaskOrganizer.java"
- },
"-1683614271": {
"message": "Existing task: id=%d component=%s",
"level": "VERBOSE",
@@ -37,6 +31,12 @@
"group": "WM_SHELL_TASK_ORG",
"at": "com\/android\/wm\/shell\/ShellTaskOrganizer.java"
},
+ "-1312360667": {
+ "message": "createRootTask() displayId=%d winMode=%d listener=%s",
+ "level": "VERBOSE",
+ "group": "WM_SHELL_TASK_ORG",
+ "at": "com\/android\/wm\/shell\/ShellTaskOrganizer.java"
+ },
"-880817403": {
"message": "Task vanished taskId=%d",
"level": "VERBOSE",
@@ -61,6 +61,12 @@
"group": "WM_SHELL_TASK_ORG",
"at": "com\/android\/wm\/shell\/ShellTaskOrganizer.java"
},
+ "481673835": {
+ "message": "addListenerForTaskId taskId=%s",
+ "level": "VERBOSE",
+ "group": "WM_SHELL_TASK_ORG",
+ "at": "com\/android\/wm\/shell\/ShellTaskOrganizer.java"
+ },
"564235578": {
"message": "Fullscreen Task Vanished: #%d",
"level": "VERBOSE",
@@ -78,6 +84,12 @@
"level": "VERBOSE",
"group": "WM_SHELL_TASK_ORG",
"at": "com\/android\/wm\/shell\/ShellTaskOrganizer.java"
+ },
+ "1990759023": {
+ "message": "addListenerForType types=%s listener=%s",
+ "level": "VERBOSE",
+ "group": "WM_SHELL_TASK_ORG",
+ "at": "com\/android\/wm\/shell\/ShellTaskOrganizer.java"
}
},
"groups": {
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/FullscreenTaskListener.java b/libs/WindowManager/Shell/src/com/android/wm/shell/FullscreenTaskListener.java
index 9d6271bca426..4cb5fd139259 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/FullscreenTaskListener.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/FullscreenTaskListener.java
@@ -16,17 +16,24 @@
package com.android.wm.shell;
+import static com.android.wm.shell.ShellTaskOrganizer.TASK_LISTENER_TYPE_FULLSCREEN;
+import static com.android.wm.shell.ShellTaskOrganizer.taskListenerTypeToString;
+
import android.app.ActivityManager;
import android.util.ArraySet;
import android.util.Slog;
import android.view.SurfaceControl;
+import androidx.annotation.NonNull;
+
import com.android.internal.protolog.common.ProtoLog;
import com.android.wm.shell.common.SyncTransactionQueue;
import com.android.wm.shell.protolog.ShellProtoLogGroup;
+import java.io.PrintWriter;
+
class FullscreenTaskListener implements ShellTaskOrganizer.TaskListener {
- private static final String TAG = "FullscreenTaskOrg";
+ private static final String TAG = "FullscreenTaskListener";
private final SyncTransactionQueue mSyncQueue;
@@ -74,6 +81,15 @@ class FullscreenTaskListener implements ShellTaskOrganizer.TaskListener {
}
@Override
- public void onTaskInfoChanged(ActivityManager.RunningTaskInfo taskInfo) {
+ public void dump(@NonNull PrintWriter pw, String prefix) {
+ final String innerPrefix = prefix + " ";
+ final String childPrefix = innerPrefix + " ";
+ pw.println(prefix + this);
+ pw.println(innerPrefix + mTasks.size() + " Tasks");
+ }
+
+ @Override
+ public String toString() {
+ return TAG + ":" + taskListenerTypeToString(TASK_LISTENER_TYPE_FULLSCREEN);
}
}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/ShellTaskOrganizer.java b/libs/WindowManager/Shell/src/com/android/wm/shell/ShellTaskOrganizer.java
index d87de5a06c55..8bd7193843f7 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/ShellTaskOrganizer.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/ShellTaskOrganizer.java
@@ -24,9 +24,13 @@ import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_PRIMAR
import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_SECONDARY;
import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED;
+import static com.android.wm.shell.protolog.ShellProtoLogGroup.WM_SHELL_TASK_ORG;
+
import android.annotation.IntDef;
import android.app.ActivityManager.RunningTaskInfo;
import android.app.WindowConfiguration.WindowingMode;
+import android.os.IBinder;
+import android.util.ArrayMap;
import android.util.Log;
import android.util.SparseArray;
import android.view.SurfaceControl;
@@ -43,6 +47,8 @@ import com.android.wm.shell.common.SyncTransactionQueue;
import com.android.wm.shell.common.TransactionPool;
import com.android.wm.shell.protolog.ShellProtoLogGroup;
+import java.io.PrintWriter;
+import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
@@ -79,14 +85,23 @@ public class ShellTaskOrganizer extends TaskOrganizer {
default void onTaskInfoChanged(RunningTaskInfo taskInfo) {}
default void onTaskVanished(RunningTaskInfo taskInfo) {}
default void onBackPressedOnTaskRoot(RunningTaskInfo taskInfo) {}
+ default void dump(@NonNull PrintWriter pw, String prefix) {};
}
- private final SparseArray<TaskListener> mTaskListenersByType = new SparseArray<>();
+ /**
+ * Keys map from either a task id or {@link TaskListenerType}.
+ * @see #addListenerForTaskId
+ * @see #addListenerForType
+ */
+ private final SparseArray<TaskListener> mTaskListeners = new SparseArray<>();
// Keeps track of all the tasks reported to this organizer (changes in windowing mode will
// require us to report to both old and new listeners)
private final SparseArray<TaskAppearedInfo> mTasks = new SparseArray<>();
+ /** @see #setPendingLaunchCookieListener */
+ private final ArrayMap<IBinder, TaskListener> mLaunchCookieToListener = new ArrayMap<>();
+
// TODO(shell-transitions): move to a more "global" Shell location as this isn't only for Tasks
private final Transitions mTransitions;
@@ -100,7 +115,7 @@ public class ShellTaskOrganizer extends TaskOrganizer {
SyncTransactionQueue syncQueue, TransactionPool transactionPool,
ShellExecutor mainExecutor, ShellExecutor animExecutor) {
super(taskOrganizerController);
- addListener(new FullscreenTaskListener(syncQueue), TASK_LISTENER_TYPE_FULLSCREEN);
+ addListenerForType(new FullscreenTaskListener(syncQueue), TASK_LISTENER_TYPE_FULLSCREEN);
mTransitions = new Transitions(this, transactionPool, mainExecutor, animExecutor);
if (Transitions.ENABLE_SHELL_TRANSITIONS) registerTransitionPlayer(mTransitions);
}
@@ -113,32 +128,62 @@ public class ShellTaskOrganizer extends TaskOrganizer {
final TaskAppearedInfo info = taskInfos.get(i);
ProtoLog.v(ShellProtoLogGroup.WM_SHELL_TASK_ORG, "Existing task: id=%d component=%s",
info.getTaskInfo().taskId, info.getTaskInfo().baseIntent);
- onTaskAppeared(info.getTaskInfo(), info.getLeash());
+ onTaskAppeared(info);
}
return taskInfos;
}
+ public TaskAppearedInfo createRootTask(
+ int displayId, int windowingMode, TaskListener listener) {
+ ProtoLog.v(ShellProtoLogGroup.WM_SHELL_TASK_ORG,
+ "createRootTask() displayId=%d winMode=%d listener=%s",
+ displayId, windowingMode, listener.toString());
+ final TaskAppearedInfo info = super.createRootTask(displayId, windowingMode);
+
+ // Add the listener and send the task appeared signal
+ mTaskListeners.put(info.getTaskInfo().taskId, listener);
+ onTaskAppeared(info);
+ return info;
+ }
+
+ /**
+ * Adds a listener for a specific task id.
+ */
+ public void addListenerForTaskId(TaskListener listener, int taskId) {
+ ProtoLog.v(WM_SHELL_TASK_ORG, "addListenerForTaskId taskId=%s", taskId);
+ if (mTaskListeners.get(taskId) != null) {
+ throw new IllegalArgumentException("Listener for taskId=" + taskId + " already exists");
+ }
+
+ final TaskAppearedInfo info = mTasks.get(taskId);
+ if (info == null) {
+ throw new IllegalArgumentException("addListenerForTaskId unknown taskId=" + taskId);
+ }
+
+ final TaskListener oldListener = getTaskListener(info.getTaskInfo());
+ mTaskListeners.put(taskId, listener);
+ updateTaskListenerIfNeeded(info.getTaskInfo(), info.getLeash(), oldListener, listener);
+ }
+
/**
* Adds a listener for tasks with given types.
*/
- public void addListener(TaskListener listener, @TaskListenerType int... taskListenerTypes) {
- ProtoLog.v(ShellProtoLogGroup.WM_SHELL_TASK_ORG, "Add listener for types=%s listener=%s",
- Arrays.toString(taskListenerTypes), listener);
- for (int listenerType : taskListenerTypes) {
- if (mTaskListenersByType.get(listenerType) != null) {
+ public void addListenerForType(TaskListener listener, @TaskListenerType int... listenerTypes) {
+ ProtoLog.v(WM_SHELL_TASK_ORG, "addListenerForType types=%s listener=%s",
+ Arrays.toString(listenerTypes), listener);
+ for (int listenerType : listenerTypes) {
+ if (mTaskListeners.get(listenerType) != null) {
throw new IllegalArgumentException("Listener for listenerType=" + listenerType
+ " already exists");
}
- mTaskListenersByType.put(listenerType, listener);
+ mTaskListeners.put(listenerType, listener);
// Notify the listener of all existing tasks with the given type.
- for (int i = mTasks.size() - 1; i >= 0; i--) {
- TaskAppearedInfo data = mTasks.valueAt(i);
- final @TaskListenerType int taskListenerType = getTaskListenerType(
- data.getTaskInfo());
- if (taskListenerType == listenerType) {
- listener.onTaskAppeared(data.getTaskInfo(), data.getLeash());
- }
+ for (int i = mTasks.size() - 1; i >= 0; --i) {
+ final TaskAppearedInfo data = mTasks.valueAt(i);
+ final TaskListener taskListener = getTaskListener(data.getTaskInfo());
+ if (taskListener != listener) continue;
+ listener.onTaskAppeared(data.getTaskInfo(), data.getLeash());
}
}
}
@@ -147,59 +192,75 @@ public class ShellTaskOrganizer extends TaskOrganizer {
* Removes a registered listener.
*/
public void removeListener(TaskListener listener) {
- ProtoLog.v(ShellProtoLogGroup.WM_SHELL_TASK_ORG, "Remove listener=%s", listener);
- final int index = mTaskListenersByType.indexOfValue(listener);
+ ProtoLog.v(WM_SHELL_TASK_ORG, "Remove listener=%s", listener);
+ final int index = mTaskListeners.indexOfValue(listener);
if (index == -1) {
Log.w(TAG, "No registered listener found");
return;
}
- mTaskListenersByType.removeAt(index);
+
+ // Collect tasks associated with the listener we are about to remove.
+ final ArrayList<TaskAppearedInfo> tasks = new ArrayList<>();
+ for (int i = mTasks.size() - 1; i >= 0; --i) {
+ final TaskAppearedInfo data = mTasks.valueAt(i);
+ final TaskListener taskListener = getTaskListener(data.getTaskInfo());
+ if (taskListener != listener) continue;
+ tasks.add(data);
+ }
+
+ // Remove listener
+ mTaskListeners.removeAt(index);
+
+ // Associate tasks with new listeners if needed.
+ for (int i = tasks.size() - 1; i >= 0; --i) {
+ final TaskAppearedInfo data = tasks.get(i);
+ updateTaskListenerIfNeeded(data.getTaskInfo(), data.getLeash(),
+ null /* oldListener already removed*/, getTaskListener(data.getTaskInfo()));
+ }
+ }
+
+ /**
+ * Associated a listener to a pending launch cookie so we can route the task later once it
+ * appears.
+ */
+ public void setPendingLaunchCookieListener(IBinder cookie, TaskListener listener) {
+ mLaunchCookieToListener.put(cookie, listener);
}
@Override
public void onTaskAppeared(RunningTaskInfo taskInfo, SurfaceControl leash) {
- ProtoLog.v(ShellProtoLogGroup.WM_SHELL_TASK_ORG, "Task appeared taskId=%d",
- taskInfo.taskId);
- mTasks.put(taskInfo.taskId, new TaskAppearedInfo(taskInfo, leash));
- final TaskListener listener = mTaskListenersByType.get(getTaskListenerType(taskInfo));
+ onTaskAppeared(new TaskAppearedInfo(taskInfo, leash));
+ }
+
+ private void onTaskAppeared(TaskAppearedInfo info) {
+ final int taskId = info.getTaskInfo().taskId;
+ ProtoLog.v(WM_SHELL_TASK_ORG, "Task appeared taskId=%d", taskId);
+ mTasks.put(taskId, info);
+ final TaskListener listener =
+ getTaskListener(info.getTaskInfo(), true /*removeLaunchCookieIfNeeded*/);
if (listener != null) {
- listener.onTaskAppeared(taskInfo, leash);
+ listener.onTaskAppeared(info.getTaskInfo(), info.getLeash());
}
}
@Override
public void onTaskInfoChanged(RunningTaskInfo taskInfo) {
- ProtoLog.v(ShellProtoLogGroup.WM_SHELL_TASK_ORG, "Task info changed taskId=%d",
- taskInfo.taskId);
+ ProtoLog.v(WM_SHELL_TASK_ORG, "Task info changed taskId=%d", taskInfo.taskId);
final TaskAppearedInfo data = mTasks.get(taskInfo.taskId);
- final @TaskListenerType int listenerType = getTaskListenerType(taskInfo);
- final @TaskListenerType int prevListenerType = getTaskListenerType(data.getTaskInfo());
+ final TaskListener oldListener = getTaskListener(data.getTaskInfo());
+ final TaskListener newListener = getTaskListener(taskInfo);
mTasks.put(taskInfo.taskId, new TaskAppearedInfo(taskInfo, data.getLeash()));
- if (prevListenerType != listenerType) {
- // TODO: We currently send vanished/appeared as the task moves between types, but
- // we should consider adding a different mode-changed callback
- TaskListener listener = mTaskListenersByType.get(prevListenerType);
- if (listener != null) {
- listener.onTaskVanished(taskInfo);
- }
- listener = mTaskListenersByType.get(listenerType);
- if (listener != null) {
- SurfaceControl leash = data.getLeash();
- listener.onTaskAppeared(taskInfo, leash);
- }
- } else {
- final TaskListener listener = mTaskListenersByType.get(listenerType);
- if (listener != null) {
- listener.onTaskInfoChanged(taskInfo);
- }
+ final boolean updated = updateTaskListenerIfNeeded(
+ taskInfo, data.getLeash(), oldListener, newListener);
+ if (!updated && newListener != null) {
+ newListener.onTaskInfoChanged(taskInfo);
}
}
@Override
public void onBackPressedOnTaskRoot(RunningTaskInfo taskInfo) {
- ProtoLog.v(ShellProtoLogGroup.WM_SHELL_TASK_ORG, "Task root back pressed taskId=%d",
- taskInfo.taskId);
- final TaskListener listener = mTaskListenersByType.get(getTaskListenerType(taskInfo));
+ ProtoLog.v(WM_SHELL_TASK_ORG, "Task root back pressed taskId=%d", taskInfo.taskId);
+ final TaskListener listener = getTaskListener(taskInfo);
if (listener != null) {
listener.onBackPressedOnTaskRoot(taskInfo);
}
@@ -207,22 +268,72 @@ public class ShellTaskOrganizer extends TaskOrganizer {
@Override
public void onTaskVanished(RunningTaskInfo taskInfo) {
- ProtoLog.v(ShellProtoLogGroup.WM_SHELL_TASK_ORG, "Task vanished taskId=%d",
- taskInfo.taskId);
- final @TaskListenerType int prevListenerType =
- getTaskListenerType(mTasks.get(taskInfo.taskId).getTaskInfo());
- mTasks.remove(taskInfo.taskId);
- final TaskListener listener = mTaskListenersByType.get(prevListenerType);
+ ProtoLog.v(WM_SHELL_TASK_ORG, "Task vanished taskId=%d", taskInfo.taskId);
+ final int taskId = taskInfo.taskId;
+ final TaskListener listener = getTaskListener(mTasks.get(taskId).getTaskInfo());
+ mTasks.remove(taskId);
if (listener != null) {
listener.onTaskVanished(taskInfo);
}
}
- @TaskListenerType
- private static int getTaskListenerType(RunningTaskInfo runningTaskInfo) {
- // Right now it's N:1 mapping but in the future different task listerners
- // may be triggered by one windowing mode depending on task parameters.
- switch (getWindowingMode(runningTaskInfo)) {
+ private boolean updateTaskListenerIfNeeded(RunningTaskInfo taskInfo, SurfaceControl leash,
+ TaskListener oldListener, TaskListener newListener) {
+ if (oldListener == newListener) return false;
+ // TODO: We currently send vanished/appeared as the task moves between types, but
+ // we should consider adding a different mode-changed callback
+ if (oldListener != null) {
+ oldListener.onTaskVanished(taskInfo);
+ }
+ if (newListener != null) {
+ newListener.onTaskAppeared(taskInfo, leash);
+ }
+ return true;
+ }
+
+ private TaskListener getTaskListener(RunningTaskInfo runningTaskInfo) {
+ return getTaskListener(runningTaskInfo, false /*removeLaunchCookieIfNeeded*/);
+ }
+
+ private TaskListener getTaskListener(RunningTaskInfo runningTaskInfo,
+ boolean removeLaunchCookieIfNeeded) {
+
+ final int taskId = runningTaskInfo.taskId;
+ TaskListener listener;
+
+ // First priority goes to listener that might be pending for this task.
+ final ArrayList<IBinder> launchCookies = runningTaskInfo.launchCookies;
+ for (int i = launchCookies.size() - 1; i >= 0; --i) {
+ final IBinder cookie = launchCookies.get(i);
+ listener = mLaunchCookieToListener.get(cookie);
+ if (listener == null) continue;
+
+ if (removeLaunchCookieIfNeeded) {
+ // Remove the cookie and add the listener.
+ mLaunchCookieToListener.remove(cookie);
+ mTaskListeners.put(taskId, listener);
+ }
+ return listener;
+ }
+
+ // Next priority goes to taskId specific listeners.
+ listener = mTaskListeners.get(taskId);
+ if (listener != null) return listener;
+
+ // Next we try type specific listeners.
+ final int windowingMode = getWindowingMode(runningTaskInfo);
+ final int taskListenerType = windowingModeToTaskListenerType(windowingMode);
+ return mTaskListeners.get(taskListenerType);
+ }
+
+ @WindowingMode
+ private static int getWindowingMode(RunningTaskInfo taskInfo) {
+ return taskInfo.configuration.windowConfiguration.getWindowingMode();
+ }
+
+ private static @TaskListenerType int windowingModeToTaskListenerType(
+ @WindowingMode int windowingMode) {
+ switch (windowingMode) {
case WINDOWING_MODE_FULLSCREEN:
return TASK_LISTENER_TYPE_FULLSCREEN;
case WINDOWING_MODE_MULTI_WINDOW:
@@ -239,8 +350,50 @@ public class ShellTaskOrganizer extends TaskOrganizer {
}
}
- @WindowingMode
- private static int getWindowingMode(RunningTaskInfo taskInfo) {
- return taskInfo.configuration.windowConfiguration.getWindowingMode();
+ public static String taskListenerTypeToString(@TaskListenerType int type) {
+ switch (type) {
+ case TASK_LISTENER_TYPE_FULLSCREEN:
+ return "TASK_LISTENER_TYPE_FULLSCREEN";
+ case TASK_LISTENER_TYPE_MULTI_WINDOW:
+ return "TASK_LISTENER_TYPE_MULTI_WINDOW";
+ case TASK_LISTENER_TYPE_SPLIT_SCREEN:
+ return "TASK_LISTENER_TYPE_SPLIT_SCREEN";
+ case TASK_LISTENER_TYPE_PIP:
+ return "TASK_LISTENER_TYPE_PIP";
+ case TASK_LISTENER_TYPE_UNDEFINED:
+ return "TASK_LISTENER_TYPE_UNDEFINED";
+ default:
+ return "taskId#" + type;
+ }
+ }
+
+ public void dump(@NonNull PrintWriter pw, String prefix) {
+ final String innerPrefix = prefix + " ";
+ final String childPrefix = innerPrefix + " ";
+ pw.println(prefix + TAG);
+ pw.println(innerPrefix + mTaskListeners.size() + " Listeners");
+ for (int i = mTaskListeners.size() - 1; i >= 0; --i) {
+ final int key = mTaskListeners.keyAt(i);
+ final TaskListener listener = mTaskListeners.valueAt(i);
+ pw.println(innerPrefix + "#" + i + " " + taskListenerTypeToString(key));
+ listener.dump(pw, childPrefix);
+ }
+
+ pw.println();
+ pw.println(innerPrefix + mTasks.size() + " Tasks");
+ for (int i = mTasks.size() - 1; i >= 0; --i) {
+ final int key = mTasks.keyAt(i);
+ final TaskAppearedInfo info = mTasks.valueAt(i);
+ final TaskListener listener = getTaskListener(info.getTaskInfo());
+ pw.println(innerPrefix + "#" + i + " task=" + key + " listener=" + listener);
+ }
+
+ pw.println();
+ pw.println(innerPrefix + mLaunchCookieToListener.size() + " Launch Cookies");
+ for (int i = mLaunchCookieToListener.size() - 1; i >= 0; --i) {
+ final IBinder key = mLaunchCookieToListener.keyAt(i);
+ final TaskListener listener = mLaunchCookieToListener.valueAt(i);
+ pw.println(innerPrefix + "#" + i + " cookie=" + key + " listener=" + listener);
+ }
}
}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/common/DisplayImeController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/common/DisplayImeController.java
index d810fb8257a9..ea18a19c2ee5 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/common/DisplayImeController.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/common/DisplayImeController.java
@@ -69,11 +69,6 @@ public class DisplayImeController implements DisplayController.OnDisplaysChanged
private final SparseArray<PerDisplay> mImePerDisplay = new SparseArray<>();
private final ArrayList<ImePositionProcessor> mPositionProcessors = new ArrayList<>();
- @Deprecated
- public DisplayImeController(IWindowManager wmService, DisplayController displayController,
- Handler mainHandler, TransactionPool transactionPool) {
- this(wmService, displayController, mainHandler::post, transactionPool);
- }
public DisplayImeController(IWindowManager wmService, DisplayController displayController,
Executor mainExecutor, TransactionPool transactionPool) {
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/common/SystemWindows.java b/libs/WindowManager/Shell/src/com/android/wm/shell/common/SystemWindows.java
index 17fd16bccc4a..24381d937e2f 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/common/SystemWindows.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/common/SystemWindows.java
@@ -32,7 +32,7 @@ import android.util.Slog;
import android.util.SparseArray;
import android.view.Display;
import android.view.DragEvent;
-import android.view.IScrollCaptureController;
+import android.view.IScrollCaptureCallbacks;
import android.view.IWindow;
import android.view.IWindowManager;
import android.view.IWindowSession;
@@ -270,25 +270,6 @@ public class SystemWindows {
mDisplayId = displayId;
}
- @Override
- public int relayout(IWindow window, WindowManager.LayoutParams attrs,
- int requestedWidth, int requestedHeight, int viewVisibility, int flags,
- long frameNumber, ClientWindowFrames outFrames,
- MergedConfiguration mergedConfiguration,
- SurfaceControl outSurfaceControl, InsetsState outInsetsState,
- InsetsSourceControl[] outActiveControls, Point outSurfaceSize) {
- int res = super.relayout(window, attrs, requestedWidth, requestedHeight,
- viewVisibility, flags, frameNumber, outFrames,
- mergedConfiguration, outSurfaceControl, outInsetsState,
- outActiveControls, outSurfaceSize);
- if (res != 0) {
- return res;
- }
- DisplayLayout dl = mDisplayController.getDisplayLayout(mDisplayId);
- outFrames.stableInsets.set(dl.stableInsets());
- return 0;
- }
-
void updateConfiguration(Configuration configuration) {
setConfiguration(configuration);
}
@@ -373,9 +354,9 @@ public class SystemWindows {
public void dispatchPointerCaptureChanged(boolean hasCapture) {}
@Override
- public void requestScrollCapture(IScrollCaptureController controller) {
+ public void requestScrollCapture(IScrollCaptureCallbacks callbacks) {
try {
- controller.onClientUnavailable();
+ callbacks.onUnavailable();
} catch (RemoteException ex) {
// ignore
}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/Pip.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/Pip.java
index 488f9092b7da..3ded4091ec11 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/Pip.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/Pip.java
@@ -98,7 +98,7 @@ public interface Pip {
/**
* Hides the PIP menu.
*/
- void hidePipMenu(Runnable onStartCallback, Runnable onEndCallback);
+ default void hidePipMenu(Runnable onStartCallback, Runnable onEndCallback) {}
/**
* Returns {@code true} if PIP is shown.
@@ -226,7 +226,7 @@ public interface Pip {
/**
* Called when showing Pip menu.
*/
- void showPictureInPictureMenu();
+ default void showPictureInPictureMenu() {}
/**
* Suspends resizing operation on the Pip until {@link #resumePipResizing} is called.
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipBoundsHandler.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipBoundsHandler.java
index de3261baf9b7..6d6cc204538a 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipBoundsHandler.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipBoundsHandler.java
@@ -22,9 +22,9 @@ import static android.util.TypedValue.COMPLEX_UNIT_DIP;
import static android.view.Surface.ROTATION_0;
import static android.view.Surface.ROTATION_180;
+import android.annotation.NonNull;
import android.app.ActivityTaskManager;
import android.app.ActivityTaskManager.RootTaskInfo;
-import android.content.ComponentName;
import android.content.Context;
import android.content.res.Resources;
import android.graphics.Point;
@@ -52,14 +52,11 @@ public class PipBoundsHandler {
private static final String TAG = PipBoundsHandler.class.getSimpleName();
private static final float INVALID_SNAP_FRACTION = -1f;
+ private final @NonNull PipBoundsState mPipBoundsState;
private final PipSnapAlgorithm mSnapAlgorithm;
private final DisplayInfo mDisplayInfo = new DisplayInfo();
private DisplayLayout mDisplayLayout;
- private ComponentName mLastPipComponentName;
- private float mReentrySnapFraction = INVALID_SNAP_FRACTION;
- private Size mReentrySize;
-
private float mDefaultAspectRatio;
private float mMinAspectRatio;
private float mMaxAspectRatio;
@@ -75,7 +72,8 @@ public class PipBoundsHandler {
private boolean mIsShelfShowing;
private int mShelfHeight;
- public PipBoundsHandler(Context context) {
+ public PipBoundsHandler(Context context, @NonNull PipBoundsState pipBoundsState) {
+ mPipBoundsState = pipBoundsState;
mSnapAlgorithm = new PipSnapAlgorithm(context);
mDisplayLayout = new DisplayLayout();
reloadResources(context);
@@ -121,6 +119,13 @@ public class PipBoundsHandler {
}
/**
+ * Get the current saved display info.
+ */
+ public DisplayInfo getDisplayInfo() {
+ return mDisplayInfo;
+ }
+
+ /**
* Update the Min edge size for {@link PipSnapAlgorithm} to calculate corresponding bounds
* @param minEdgeSize
*/
@@ -175,40 +180,6 @@ public class PipBoundsHandler {
}
/**
- * Responds to IPinnedStackListener on saving reentry snap fraction and size
- * for a given {@link ComponentName}.
- */
- public void onSaveReentryBounds(ComponentName componentName, Rect bounds) {
- mReentrySnapFraction = getSnapFraction(bounds);
- mReentrySize = new Size(bounds.width(), bounds.height());
- mLastPipComponentName = componentName;
- }
-
- /**
- * Responds to IPinnedStackListener on resetting reentry snap fraction and size
- * for a given {@link ComponentName}.
- */
- public void onResetReentryBounds(ComponentName componentName) {
- if (componentName.equals(mLastPipComponentName)) {
- onResetReentryBoundsUnchecked();
- }
- }
-
- private void onResetReentryBoundsUnchecked() {
- mReentrySnapFraction = INVALID_SNAP_FRACTION;
- mReentrySize = null;
- mLastPipComponentName = null;
- }
-
- /**
- * Returns ture if there's a valid snap fraction. This is used with {@link EXTRA_IS_FIRST_ENTRY}
- * to see if this is the first time user has entered PIP for the component.
- */
- public boolean hasSaveReentryBounds() {
- return mReentrySnapFraction != INVALID_SNAP_FRACTION;
- }
-
- /**
* The {@link PipSnapAlgorithm} is couple on display bounds
* @return {@link PipSnapAlgorithm}.
*/
@@ -250,37 +221,43 @@ public class PipBoundsHandler {
}
/**
- * See {@link #getDestinationBounds(ComponentName, float, Rect, Size, boolean)}
+ * See {@link #getDestinationBounds(float, Rect, Size, boolean)}
*/
- public Rect getDestinationBounds(ComponentName componentName, float aspectRatio, Rect bounds,
- Size minimalSize) {
- return getDestinationBounds(componentName, aspectRatio, bounds, minimalSize,
+ public Rect getDestinationBounds(float aspectRatio, Rect bounds, Size minimalSize) {
+ return getDestinationBounds(aspectRatio, bounds, minimalSize,
false /* useCurrentMinEdgeSize */);
}
/**
* @return {@link Rect} of the destination PiP window bounds.
*/
- public Rect getDestinationBounds(ComponentName componentName, float aspectRatio, Rect bounds,
+ public Rect getDestinationBounds(float aspectRatio, Rect bounds,
Size minimalSize, boolean useCurrentMinEdgeSize) {
- if (!componentName.equals(mLastPipComponentName)) {
- onResetReentryBoundsUnchecked();
- mLastPipComponentName = componentName;
- }
+ boolean isReentryBounds = false;
final Rect destinationBounds;
if (bounds == null) {
- final Rect defaultBounds = getDefaultBounds(mReentrySnapFraction, mReentrySize);
- destinationBounds = new Rect(defaultBounds);
- if (mReentrySnapFraction == INVALID_SNAP_FRACTION && mReentrySize == null) {
+ // Calculating initial entry bounds
+ final PipBoundsState.PipReentryState state = mPipBoundsState.getReentryState();
+
+ final Rect defaultBounds;
+ if (state != null) {
+ // Restore to reentry bounds.
+ defaultBounds = getDefaultBounds(state.getSnapFraction(), state.getSize());
+ isReentryBounds = true;
+ } else {
+ // Get actual default bounds.
+ defaultBounds = getDefaultBounds(INVALID_SNAP_FRACTION, null /* size */);
mOverrideMinimalSize = minimalSize;
}
+
+ destinationBounds = new Rect(defaultBounds);
} else {
+ // Just adjusting bounds (e.g. on aspect ratio changed).
destinationBounds = new Rect(bounds);
}
if (isValidPictureInPictureAspectRatio(aspectRatio)) {
- boolean useCurrentSize = bounds == null && mReentrySize != null;
transformBoundsToAspectRatio(destinationBounds, aspectRatio, useCurrentMinEdgeSize,
- useCurrentSize);
+ isReentryBounds);
}
mAspectRatio = aspectRatio;
return destinationBounds;
@@ -533,9 +510,6 @@ public class PipBoundsHandler {
public void dump(PrintWriter pw, String prefix) {
final String innerPrefix = prefix + " ";
pw.println(prefix + TAG);
- pw.println(innerPrefix + "mLastPipComponentName=" + mLastPipComponentName);
- pw.println(innerPrefix + "mReentrySnapFraction=" + mReentrySnapFraction);
- pw.println(innerPrefix + "mReentrySize=" + mReentrySize);
pw.println(innerPrefix + "mDisplayInfo=" + mDisplayInfo);
pw.println(innerPrefix + "mDefaultAspectRatio=" + mDefaultAspectRatio);
pw.println(innerPrefix + "mMinAspectRatio=" + mMinAspectRatio);
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipBoundsState.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipBoundsState.java
index 10e5c3d33def..2625f16fac46 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipBoundsState.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipBoundsState.java
@@ -17,9 +17,15 @@
package com.android.wm.shell.pip;
import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.content.ComponentName;
import android.graphics.Rect;
+import android.util.Size;
+
+import com.android.internal.annotations.VisibleForTesting;
import java.io.PrintWriter;
+import java.util.Objects;
/**
* Singleton source of truth for the current state of PIP bounds.
@@ -28,6 +34,8 @@ public final class PipBoundsState {
private static final String TAG = PipBoundsState.class.getSimpleName();
private final @NonNull Rect mBounds = new Rect();
+ private PipReentryState mPipReentryState;
+ private ComponentName mLastPipComponentName;
void setBounds(@NonNull Rect bounds) {
mBounds.set(bounds);
@@ -39,11 +47,83 @@ public final class PipBoundsState {
}
/**
+ * Save the reentry state to restore to when re-entering PIP mode.
+ *
+ * TODO(b/169373982): consider refactoring this so that this class alone can use mBounds and
+ * calculate the snap fraction to save for re-entry.
+ */
+ public void saveReentryState(@NonNull Rect bounds, float fraction) {
+ mPipReentryState = new PipReentryState(new Size(bounds.width(), bounds.height()), fraction);
+ }
+
+ /**
+ * Returns the saved reentry state.
+ */
+ @Nullable
+ public PipReentryState getReentryState() {
+ return mPipReentryState;
+ }
+
+ /**
+ * Set the last {@link ComponentName} to enter PIP mode.
+ */
+ public void setLastPipComponentName(ComponentName lastPipComponentName) {
+ final boolean changed = !Objects.equals(mLastPipComponentName, lastPipComponentName);
+ mLastPipComponentName = lastPipComponentName;
+ if (changed) {
+ clearReentryState();
+ }
+ }
+
+ public ComponentName getLastPipComponentName() {
+ return mLastPipComponentName;
+ }
+
+ @VisibleForTesting
+ void clearReentryState() {
+ mPipReentryState = null;
+ }
+
+ static final class PipReentryState {
+ private static final String TAG = PipReentryState.class.getSimpleName();
+
+ private final @NonNull Size mSize;
+ private final float mSnapFraction;
+
+ PipReentryState(@NonNull Size size, float snapFraction) {
+ mSize = size;
+ mSnapFraction = snapFraction;
+ }
+
+ @NonNull
+ Size getSize() {
+ return mSize;
+ }
+
+ float getSnapFraction() {
+ return mSnapFraction;
+ }
+
+ void dump(PrintWriter pw, String prefix) {
+ final String innerPrefix = prefix + " ";
+ pw.println(prefix + TAG);
+ pw.println(innerPrefix + "mSize=" + mSize);
+ pw.println(innerPrefix + "mSnapFraction=" + mSnapFraction);
+ }
+ }
+
+ /**
* Dumps internal state.
*/
public void dump(PrintWriter pw, String prefix) {
final String innerPrefix = prefix + " ";
pw.println(prefix + TAG);
pw.println(innerPrefix + "mBounds=" + mBounds);
+ pw.println(innerPrefix + "mLastPipComponentName=" + mLastPipComponentName);
+ if (mPipReentryState == null) {
+ pw.println(innerPrefix + "mPipReentryState=null");
+ } else {
+ mPipReentryState.dump(pw, innerPrefix);
+ }
}
}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipTaskOrganizer.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipTaskOrganizer.java
index 15fd4245a819..cd5d35bf0c4c 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipTaskOrganizer.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipTaskOrganizer.java
@@ -22,6 +22,7 @@ import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_SECOND
import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED;
import static com.android.wm.shell.ShellTaskOrganizer.TASK_LISTENER_TYPE_PIP;
+import static com.android.wm.shell.ShellTaskOrganizer.taskListenerTypeToString;
import static com.android.wm.shell.pip.PipAnimationController.ANIM_TYPE_ALPHA;
import static com.android.wm.shell.pip.PipAnimationController.ANIM_TYPE_BOUNDS;
import static com.android.wm.shell.pip.PipAnimationController.TRANSITION_DIRECTION_LEAVE_PIP;
@@ -67,6 +68,7 @@ import com.android.wm.shell.common.DisplayController;
import com.android.wm.shell.pip.phone.PipMenuActivityController;
import com.android.wm.shell.pip.phone.PipMotionHelper;
import com.android.wm.shell.pip.phone.PipUpdateThread;
+import com.android.wm.shell.pip.phone.PipUtils;
import com.android.wm.shell.splitscreen.SplitScreen;
import java.io.PrintWriter;
@@ -77,6 +79,7 @@ import java.util.Map;
import java.util.Objects;
import java.util.Optional;
import java.util.function.Consumer;
+import java.util.function.IntConsumer;
/**
* Manages PiP tasks such as resize and offset.
@@ -246,6 +249,7 @@ public class PipTaskOrganizer implements ShellTaskOrganizer.TaskListener,
private PipSurfaceTransactionHelper.SurfaceControlTransactionFactory
mSurfaceControlTransactionFactory;
private PictureInPictureParams mPictureInPictureParams;
+ private IntConsumer mOnDisplayIdChangeCallback;
/**
* If set to {@code true}, the entering animation will be skipped and we will wait for
@@ -280,7 +284,7 @@ public class PipTaskOrganizer implements ShellTaskOrganizer.TaskListener,
mSurfaceControlTransactionFactory = SurfaceControl.Transaction::new;
mSplitScreenOptional = splitScreenOptional;
mTaskOrganizer = shellTaskOrganizer;
- mTaskOrganizer.addListener(this, TASK_LISTENER_TYPE_PIP);
+ mTaskOrganizer.addListenerForType(this, TASK_LISTENER_TYPE_PIP);
displayController.addDisplayWindowListener(this);
}
@@ -313,6 +317,13 @@ public class PipTaskOrganizer implements ShellTaskOrganizer.TaskListener,
}
/**
+ * Registers a callback when a display change has been detected when we enter PiP.
+ */
+ public void registerOnDisplayIdChangeCallback(IntConsumer onDisplayIdChangeCallback) {
+ mOnDisplayIdChangeCallback = onDisplayIdChangeCallback;
+ }
+
+ /**
* Sets the preferred animation type for one time.
* This is typically used to set the animation type to
* {@link PipAnimationController#ANIM_TYPE_ALPHA}.
@@ -329,7 +340,8 @@ public class PipTaskOrganizer implements ShellTaskOrganizer.TaskListener,
PictureInPictureParams pictureInPictureParams) {
mShouldIgnoreEnteringPipTransition = true;
mState = State.ENTERING_PIP;
- return mPipBoundsHandler.getDestinationBounds(componentName,
+ mPipBoundsState.setLastPipComponentName(componentName);
+ return mPipBoundsHandler.getDestinationBounds(
getAspectRatioOrDefault(pictureInPictureParams),
null /* bounds */, getMinimalSize(activityInfo));
}
@@ -400,9 +412,13 @@ public class PipTaskOrganizer implements ShellTaskOrganizer.TaskListener,
@Override
public void onTransactionReady(int id, SurfaceControl.Transaction t) {
t.apply();
- scheduleAnimateResizePip(mPipBoundsState.getBounds(),
- destinationBounds, getValidSourceHintRect(mTaskInfo, destinationBounds),
- direction, animationDurationMs, null /* updateBoundsCallback */);
+ // Make sure to grab the latest source hint rect as it could have been updated
+ // right after applying the windowing mode change.
+ final Rect sourceHintRect = getValidSourceHintRect(mPictureInPictureParams,
+ destinationBounds);
+ scheduleAnimateResizePip(mPipBoundsState.getBounds(), destinationBounds,
+ sourceHintRect, direction, animationDurationMs,
+ null /* updateBoundsCallback */);
mState = State.EXITING_PIP;
}
});
@@ -465,10 +481,18 @@ public class PipTaskOrganizer implements ShellTaskOrganizer.TaskListener,
mLeash = leash;
mInitialState.put(mToken.asBinder(), new Configuration(mTaskInfo.configuration));
mPictureInPictureParams = mTaskInfo.pictureInPictureParams;
+ mPipBoundsState.setLastPipComponentName(mTaskInfo.topActivity);
mPipUiEventLoggerLogger.setTaskInfo(mTaskInfo);
mPipUiEventLoggerLogger.log(PipUiEventLogger.PipUiEventEnum.PICTURE_IN_PICTURE_ENTER);
+ // If the displayId of the task is different than what PipBoundsHandler has, then update
+ // it. This is possible if we entered PiP on an external display.
+ if (info.displayId != mPipBoundsHandler.getDisplayInfo().displayId
+ && mOnDisplayIdChangeCallback != null) {
+ mOnDisplayIdChangeCallback.accept(info.displayId);
+ }
+
if (mShouldIgnoreEnteringPipTransition) {
// Animation has been finished together with Recents, directly apply the sync
// transaction to PiP here.
@@ -491,13 +515,14 @@ public class PipTaskOrganizer implements ShellTaskOrganizer.TaskListener,
}
final Rect destinationBounds = mPipBoundsHandler.getDestinationBounds(
- mTaskInfo.topActivity, getAspectRatioOrDefault(mPictureInPictureParams),
+ getAspectRatioOrDefault(mPictureInPictureParams),
null /* bounds */, getMinimalSize(mTaskInfo.topActivityInfo));
Objects.requireNonNull(destinationBounds, "Missing destination bounds");
final Rect currentBounds = mTaskInfo.configuration.windowConfiguration.getBounds();
if (mOneShotAnimationType == ANIM_TYPE_BOUNDS) {
- final Rect sourceHintRect = getValidSourceHintRect(info, currentBounds);
+ final Rect sourceHintRect = getValidSourceHintRect(info.pictureInPictureParams,
+ currentBounds);
scheduleAnimateResizePip(currentBounds, destinationBounds, sourceHintRect,
TRANSITION_DIRECTION_TO_PIP, mEnterExitAnimationDuration,
null /* updateBoundsCallback */);
@@ -514,10 +539,10 @@ public class PipTaskOrganizer implements ShellTaskOrganizer.TaskListener,
* Returns the source hint rect if it is valid (if provided and is contained by the current
* task bounds).
*/
- private Rect getValidSourceHintRect(ActivityManager.RunningTaskInfo info, Rect sourceBounds) {
- final Rect sourceHintRect = info.pictureInPictureParams != null
- && info.pictureInPictureParams.hasSourceBoundsHint()
- ? info.pictureInPictureParams.getSourceRectHint()
+ private Rect getValidSourceHintRect(PictureInPictureParams params, Rect sourceBounds) {
+ final Rect sourceHintRect = params != null
+ && params.hasSourceBoundsHint()
+ ? params.getSourceRectHint()
: null;
if (sourceHintRect != null && sourceBounds.contains(sourceHintRect)) {
return sourceHintRect;
@@ -686,13 +711,14 @@ public class PipTaskOrganizer implements ShellTaskOrganizer.TaskListener,
@Override
public void onTaskInfoChanged(ActivityManager.RunningTaskInfo info) {
Objects.requireNonNull(mToken, "onTaskInfoChanged requires valid existing mToken");
+ mPipBoundsState.setLastPipComponentName(info.topActivity);
final PictureInPictureParams newParams = info.pictureInPictureParams;
if (newParams == null || !applyPictureInPictureParams(newParams)) {
Log.d(TAG, "Ignored onTaskInfoChanged with PiP param: " + newParams);
return;
}
final Rect destinationBounds = mPipBoundsHandler.getDestinationBounds(
- info.topActivity, getAspectRatioOrDefault(newParams),
+ getAspectRatioOrDefault(newParams),
mPipBoundsState.getBounds(), getMinimalSize(info.topActivityInfo),
true /* userCurrentMinEdgeSize */);
Objects.requireNonNull(destinationBounds, "Missing destination bounds");
@@ -709,7 +735,7 @@ public class PipTaskOrganizer implements ShellTaskOrganizer.TaskListener,
public void onFixedRotationFinished(int displayId) {
if (mShouldDeferEnteringPip && mState.isInPip()) {
final Rect destinationBounds = mPipBoundsHandler.getDestinationBounds(
- mTaskInfo.topActivity, getAspectRatioOrDefault(mPictureInPictureParams),
+ getAspectRatioOrDefault(mPictureInPictureParams),
null /* bounds */, getMinimalSize(mTaskInfo.topActivityInfo));
// schedule a regular animation to ensure all the callbacks are still being sent
enterPipWithAlphaAnimation(destinationBounds, 0 /* durationMs */);
@@ -783,7 +809,7 @@ public class PipTaskOrganizer implements ShellTaskOrganizer.TaskListener,
}
final Rect newDestinationBounds = mPipBoundsHandler.getDestinationBounds(
- mTaskInfo.topActivity, getAspectRatioOrDefault(mPictureInPictureParams),
+ getAspectRatioOrDefault(mPictureInPictureParams),
null /* bounds */, getMinimalSize(mTaskInfo.topActivityInfo));
if (newDestinationBounds.equals(currentDestinationBounds)) return;
if (animator.getAnimationType() == ANIM_TYPE_BOUNDS) {
@@ -1123,6 +1149,7 @@ public class PipTaskOrganizer implements ShellTaskOrganizer.TaskListener,
/**
* Dumps internal states.
*/
+ @Override
public void dump(PrintWriter pw, String prefix) {
final String innerPrefix = prefix + " ";
pw.println(prefix + TAG);
@@ -1140,6 +1167,11 @@ public class PipTaskOrganizer implements ShellTaskOrganizer.TaskListener,
}
}
+ @Override
+ public String toString() {
+ return TAG + ":" + taskListenerTypeToString(TASK_LISTENER_TYPE_PIP);
+ }
+
/**
* Callback interface for PiP transitions (both from and to PiP mode)
*/
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipController.java
index 13f5ac3edc60..a08983740f9a 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipController.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipController.java
@@ -173,7 +173,13 @@ public class PipController implements Pip, PipTaskOrganizer.PipTransitionCallbac
@Override
public void onActivityHidden(ComponentName componentName) {
- mHandler.post(() -> mPipBoundsHandler.onResetReentryBounds(componentName));
+ mHandler.post(() -> {
+ if (componentName.equals(mPipBoundsState.getLastPipComponentName())) {
+ // The activity was removed, we don't want to restore to the reentry state
+ // saved for this component anymore.
+ mPipBoundsState.setLastPipComponentName(null);
+ }
+ });
}
@Override
@@ -222,6 +228,14 @@ public class PipController implements Pip, PipTaskOrganizer.PipTransitionCallbac
mPipBoundsState = pipBoundsState;
mPipTaskOrganizer = pipTaskOrganizer;
mPipTaskOrganizer.registerPipTransitionCallback(this);
+ mPipTaskOrganizer.registerOnDisplayIdChangeCallback((int displayId) -> {
+ final DisplayInfo newDisplayInfo = new DisplayInfo();
+ displayController.getDisplay(displayId).getDisplayInfo(newDisplayInfo);
+ mPipBoundsHandler.onDisplayInfoChanged(newDisplayInfo);
+ updateMovementBounds(null /* toBounds */, false /* fromRotation */,
+ false /* fromImeAdjustment */, false /* fromShelfAdustment */,
+ null /* wct */);
+ });
mMediaController = pipMediaController;
mMenuController = pipMenuActivityController;
mTouchHandler = pipTouchHandler;
@@ -384,7 +398,8 @@ public class PipController implements Pip, PipTaskOrganizer.PipTransitionCallbac
if (isOutPipDirection(direction)) {
// Exiting PIP, save the reentry bounds to restore to when re-entering.
updateReentryBounds(pipBounds);
- mPipBoundsHandler.onSaveReentryBounds(activity, mReentryBounds);
+ final float snapFraction = mPipBoundsHandler.getSnapFraction(mReentryBounds);
+ mPipBoundsState.saveReentryState(mReentryBounds, snapFraction);
}
// Disable touches while the animation is running
mTouchHandler.setTouchEnabled(false);
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/tv/PipController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/tv/PipController.java
index 8eac005425bc..4f2d4e50f76d 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/tv/PipController.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/tv/PipController.java
@@ -19,6 +19,10 @@ package com.android.wm.shell.pip.tv;
import static android.app.ActivityTaskManager.INVALID_STACK_ID;
import static android.app.WindowConfiguration.ACTIVITY_TYPE_UNDEFINED;
import static android.app.WindowConfiguration.WINDOWING_MODE_PINNED;
+import static android.content.Intent.ACTION_MEDIA_RESOURCE_GRANTED;
+
+import static com.android.wm.shell.pip.tv.PipNotification.ACTION_CLOSE;
+import static com.android.wm.shell.pip.tv.PipNotification.ACTION_MENU;
import android.app.ActivityManager;
import android.app.ActivityTaskManager;
@@ -140,17 +144,26 @@ public class PipController implements Pip, PipTaskOrganizer.PipTransitionCallbac
private final BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
- String action = intent.getAction();
- if (Intent.ACTION_MEDIA_RESOURCE_GRANTED.equals(action)) {
- String[] packageNames = intent.getStringArrayExtra(Intent.EXTRA_PACKAGES);
- int resourceType = intent.getIntExtra(Intent.EXTRA_MEDIA_RESOURCE_TYPE,
- INVALID_RESOURCE_TYPE);
- if (packageNames != null && packageNames.length > 0
- && resourceType == Intent.EXTRA_MEDIA_RESOURCE_TYPE_VIDEO_CODEC) {
- handleMediaResourceGranted(packageNames);
- }
+ if (DEBUG) {
+ Log.d(TAG, "mBroadcastReceiver, action: " + intent.getAction());
+ }
+ switch (intent.getAction()) {
+ case ACTION_MENU:
+ showPictureInPictureMenu();
+ break;
+ case ACTION_CLOSE:
+ closePip();
+ break;
+ case ACTION_MEDIA_RESOURCE_GRANTED:
+ String[] packageNames = intent.getStringArrayExtra(Intent.EXTRA_PACKAGES);
+ int resourceType = intent.getIntExtra(Intent.EXTRA_MEDIA_RESOURCE_TYPE,
+ INVALID_RESOURCE_TYPE);
+ if (packageNames != null && packageNames.length > 0
+ && resourceType == Intent.EXTRA_MEDIA_RESOURCE_TYPE_VIDEO_CODEC) {
+ handleMediaResourceGranted(packageNames);
+ }
+ break;
}
-
}
};
private final MediaSessionManager.OnActiveSessionsChangedListener mActiveMediaSessionListener =
@@ -233,8 +246,11 @@ public class PipController implements Pip, PipTaskOrganizer.PipTransitionCallbac
mPipTaskOrganizer = pipTaskOrganizer;
mPipTaskOrganizer.registerPipTransitionCallback(this);
mActivityTaskManager = ActivityTaskManager.getService();
- IntentFilter intentFilter = new IntentFilter();
- intentFilter.addAction(Intent.ACTION_MEDIA_RESOURCE_GRANTED);
+
+ final IntentFilter intentFilter = new IntentFilter();
+ intentFilter.addAction(ACTION_CLOSE);
+ intentFilter.addAction(ACTION_MENU);
+ intentFilter.addAction(ACTION_MEDIA_RESOURCE_GRANTED);
mContext.registerReceiver(mBroadcastReceiver, intentFilter, UserHandle.USER_ALL);
// Initialize the last orientation and apply the current configuration
@@ -249,10 +265,10 @@ public class PipController implements Pip, PipTaskOrganizer.PipTransitionCallbac
} catch (RemoteException e) {
Log.e(TAG, "Failed to register pinned stack listener", e);
}
- }
- // TODO(b/169395392) Refactor PipMenuActivity to PipMenuView
- PipMenuActivity.setPipController(this);
+ // TODO(b/169395392) Refactor PipMenuActivity to PipMenuView
+ PipMenuActivity.setPipController(this);
+ }
}
private void loadConfigurationsAndApply(Configuration newConfig) {
@@ -564,6 +580,7 @@ public class PipController implements Pip, PipTaskOrganizer.PipTransitionCallbac
} catch (RemoteException e) {
Log.e(TAG, "getRootTaskInfo failed", e);
}
+ if (DEBUG) Log.d(TAG, "getPinnedTaskInfo(), taskInfo=" + taskInfo);
return taskInfo;
}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/tv/PipMenuActivity.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/tv/PipMenuActivity.java
index 06d2408c95f4..e185a9604449 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/tv/PipMenuActivity.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/tv/PipMenuActivity.java
@@ -35,7 +35,7 @@ import java.util.Collections;
*/
public class PipMenuActivity extends Activity implements PipController.Listener {
private static final String TAG = "PipMenuActivity";
- private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
+ private static final boolean DEBUG = PipController.DEBUG;
static final String EXTRA_CUSTOM_ACTIONS = "custom_actions";
@@ -51,7 +51,7 @@ public class PipMenuActivity extends Activity implements PipController.Listener
if (DEBUG) Log.d(TAG, "onCreate()");
super.onCreate(bundle);
- if (sPipController == null || sPipController.isPipShown()) {
+ if (sPipController == null) {
finish();
}
setContentView(R.layout.tv_pip_menu);
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/tv/PipNotification.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/tv/PipNotification.java
index 7433085e6fcb..f5bbd23fa1d6 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/tv/PipNotification.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/tv/PipNotification.java
@@ -20,10 +20,8 @@ import android.app.Notification;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.app.RemoteAction;
-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.PackageManager;
import android.content.pm.ParceledListSlice;
@@ -32,9 +30,7 @@ import android.graphics.Bitmap;
import android.media.MediaMetadata;
import android.media.session.MediaController;
import android.media.session.PlaybackState;
-import android.os.UserHandle;
import android.text.TextUtils;
-import android.util.Log;
import com.android.internal.messages.nano.SystemMessageProto.SystemMessage;
import com.android.wm.shell.R;
@@ -49,8 +45,8 @@ public class PipNotification {
private static final String NOTIFICATION_TAG = PipNotification.class.getSimpleName();
private static final boolean DEBUG = PipController.DEBUG;
- private static final String ACTION_MENU = "PipNotification.menu";
- private static final String ACTION_CLOSE = "PipNotification.close";
+ static final String ACTION_MENU = "PipNotification.menu";
+ static final String ACTION_CLOSE = "PipNotification.close";
public static final String NOTIFICATION_CHANNEL_TVPIP = "TPP";
@@ -147,23 +143,6 @@ public class PipNotification {
}
};
- private final BroadcastReceiver mEventReceiver = new BroadcastReceiver() {
- @Override
- public void onReceive(Context context, Intent intent) {
- if (DEBUG) {
- Log.d(TAG, "Received " + intent.getAction() + " from the notification UI");
- }
- switch (intent.getAction()) {
- case ACTION_MENU:
- mPipController.showPictureInPictureMenu();
- break;
- case ACTION_CLOSE:
- mPipController.closePip();
- break;
- }
- }
- };
-
public PipNotification(Context context, PipController pipController) {
mPackageManager = context.getPackageManager();
@@ -182,11 +161,6 @@ public class PipNotification {
pipController.addListener(mPipListener);
pipController.addMediaListener(mPipMediaListener);
- IntentFilter intentFilter = new IntentFilter();
- intentFilter.addAction(ACTION_MENU);
- intentFilter.addAction(ACTION_CLOSE);
- context.registerReceiver(mEventReceiver, intentFilter, UserHandle.USER_ALL);
-
onConfigurationChanged(context);
}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitScreenTaskOrganizer.java b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitScreenTaskOrganizer.java
index 8660702a2509..0a1aadc90a62 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitScreenTaskOrganizer.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitScreenTaskOrganizer.java
@@ -24,6 +24,7 @@ import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_SECOND
import static android.view.Display.DEFAULT_DISPLAY;
import static com.android.wm.shell.ShellTaskOrganizer.TASK_LISTENER_TYPE_SPLIT_SCREEN;
+import static com.android.wm.shell.ShellTaskOrganizer.taskListenerTypeToString;
import android.app.ActivityManager.RunningTaskInfo;
import android.graphics.Rect;
@@ -32,9 +33,14 @@ import android.util.Log;
import android.view.Display;
import android.view.SurfaceControl;
import android.view.SurfaceSession;
+import android.window.TaskAppearedInfo;
+
+import androidx.annotation.NonNull;
import com.android.wm.shell.ShellTaskOrganizer;
+import java.io.PrintWriter;
+
class SplitScreenTaskOrganizer implements ShellTaskOrganizer.TaskListener {
private static final String TAG = "SplitScreenTaskOrg";
private static final boolean DEBUG = SplitScreenController.DEBUG;
@@ -57,16 +63,21 @@ class SplitScreenTaskOrganizer implements ShellTaskOrganizer.TaskListener {
ShellTaskOrganizer shellTaskOrganizer) {
mSplitScreenController = splitScreenController;
mTaskOrganizer = shellTaskOrganizer;
- mTaskOrganizer.addListener(this, TASK_LISTENER_TYPE_SPLIT_SCREEN);
+ mTaskOrganizer.addListenerForType(this, TASK_LISTENER_TYPE_SPLIT_SCREEN);
}
void init() throws RemoteException {
synchronized (this) {
try {
- mPrimary = mTaskOrganizer.createRootTask(Display.DEFAULT_DISPLAY,
- WINDOWING_MODE_SPLIT_SCREEN_PRIMARY);
- mSecondary = mTaskOrganizer.createRootTask(Display.DEFAULT_DISPLAY,
- WINDOWING_MODE_SPLIT_SCREEN_SECONDARY);
+ final TaskAppearedInfo primary = mTaskOrganizer.createRootTask(
+ Display.DEFAULT_DISPLAY, WINDOWING_MODE_SPLIT_SCREEN_PRIMARY, this);
+ final TaskAppearedInfo secondary = mTaskOrganizer.createRootTask(
+ Display.DEFAULT_DISPLAY, WINDOWING_MODE_SPLIT_SCREEN_SECONDARY, this);
+ mPrimary = primary.getTaskInfo();
+ mPrimarySurface = primary.getLeash();
+ mSecondary = secondary.getTaskInfo();
+ mSecondarySurface = secondary.getLeash();
+ enableSplitScreenSupportIfNeeded();
} catch (Exception e) {
// teardown to prevent callbacks
mTaskOrganizer.removeListener(this);
@@ -87,43 +98,29 @@ class SplitScreenTaskOrganizer implements ShellTaskOrganizer.TaskListener {
mSplitScreenController.mTransactionPool.release(t);
}
- @Override
- public void onTaskAppeared(RunningTaskInfo taskInfo, SurfaceControl leash) {
- synchronized (this) {
- if (mPrimary == null || mSecondary == null) {
- Log.w(TAG, "Received onTaskAppeared before creating root tasks " + taskInfo);
- return;
- }
-
- if (taskInfo.token.equals(mPrimary.token)) {
- mPrimarySurface = leash;
- } else if (taskInfo.token.equals(mSecondary.token)) {
- mSecondarySurface = leash;
- }
-
- if (!mSplitScreenSupported && mPrimarySurface != null && mSecondarySurface != null) {
- mSplitScreenSupported = true;
-
- // Initialize dim surfaces:
- mPrimaryDim = new SurfaceControl.Builder(mSurfaceSession)
- .setParent(mPrimarySurface).setColorLayer()
- .setName("Primary Divider Dim")
- .setCallsite("SplitScreenTaskOrganizer.onTaskAppeared")
- .build();
- mSecondaryDim = new SurfaceControl.Builder(mSurfaceSession)
- .setParent(mSecondarySurface).setColorLayer()
- .setName("Secondary Divider Dim")
- .setCallsite("SplitScreenTaskOrganizer.onTaskAppeared")
- .build();
- SurfaceControl.Transaction t = getTransaction();
- t.setLayer(mPrimaryDim, Integer.MAX_VALUE);
- t.setColor(mPrimaryDim, new float[]{0f, 0f, 0f});
- t.setLayer(mSecondaryDim, Integer.MAX_VALUE);
- t.setColor(mSecondaryDim, new float[]{0f, 0f, 0f});
- t.apply();
- releaseTransaction(t);
- }
- }
+ private void enableSplitScreenSupportIfNeeded() {
+ if (mSplitScreenSupported || mPrimarySurface == null || mSecondarySurface == null) return;
+
+ mSplitScreenSupported = true;
+
+ // Initialize dim surfaces:
+ mPrimaryDim = new SurfaceControl.Builder(mSurfaceSession)
+ .setParent(mPrimarySurface).setColorLayer()
+ .setName("Primary Divider Dim")
+ .setCallsite("SplitScreenTaskOrganizer.onTaskAppeared")
+ .build();
+ mSecondaryDim = new SurfaceControl.Builder(mSurfaceSession)
+ .setParent(mSecondarySurface).setColorLayer()
+ .setName("Secondary Divider Dim")
+ .setCallsite("SplitScreenTaskOrganizer.onTaskAppeared")
+ .build();
+ SurfaceControl.Transaction t = getTransaction();
+ t.setLayer(mPrimaryDim, Integer.MAX_VALUE);
+ t.setColor(mPrimaryDim, new float[]{0f, 0f, 0f});
+ t.setLayer(mSecondaryDim, Integer.MAX_VALUE);
+ t.setColor(mSecondaryDim, new float[]{0f, 0f, 0f});
+ t.apply();
+ releaseTransaction(t);
}
@Override
@@ -229,4 +226,16 @@ class SplitScreenTaskOrganizer implements ShellTaskOrganizer.TaskListener {
mSplitScreenController.ensureNormalSplit();
}
}
+
+ @Override
+ public void dump(@NonNull PrintWriter pw, String prefix) {
+ final String innerPrefix = prefix + " ";
+ final String childPrefix = innerPrefix + " ";
+ pw.println(prefix + this);
+ }
+
+ @Override
+ public String toString() {
+ return TAG + ":" + taskListenerTypeToString(TASK_LISTENER_TYPE_SPLIT_SCREEN);
+ }
}
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/ShellTaskOrganizerTests.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/ShellTaskOrganizerTests.java
index 5418a5b21680..07a6bda239c7 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/ShellTaskOrganizerTests.java
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/ShellTaskOrganizerTests.java
@@ -24,8 +24,8 @@ import static com.android.wm.shell.ShellTaskOrganizer.TASK_LISTENER_TYPE_PIP;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.doReturn;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.spy;
-import static com.android.dx.mockito.inline.extended.ExtendedMockito.when;
+import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
import static org.mockito.ArgumentMatchers.any;
@@ -34,6 +34,8 @@ import static org.mockito.Mockito.verify;
import android.app.ActivityManager.RunningTaskInfo;
import android.content.pm.ParceledListSlice;
+import android.os.Binder;
+import android.os.IBinder;
import android.os.RemoteException;
import android.view.SurfaceControl;
import android.window.ITaskOrganizer;
@@ -89,11 +91,6 @@ public class ShellTaskOrganizerTests {
public void onTaskVanished(RunningTaskInfo taskInfo) {
vanished.add(taskInfo);
}
-
- @Override
- public void onBackPressedOnTaskRoot(RunningTaskInfo taskInfo) {
- // Not currently used
- }
}
@Before
@@ -116,9 +113,10 @@ public class ShellTaskOrganizerTests {
@Test
public void testOneListenerPerType() {
- mOrganizer.addListener(new TrackingTaskListener(), TASK_LISTENER_TYPE_MULTI_WINDOW);
+ mOrganizer.addListenerForType(new TrackingTaskListener(), TASK_LISTENER_TYPE_MULTI_WINDOW);
try {
- mOrganizer.addListener(new TrackingTaskListener(), TASK_LISTENER_TYPE_MULTI_WINDOW);
+ mOrganizer.addListenerForType(
+ new TrackingTaskListener(), TASK_LISTENER_TYPE_MULTI_WINDOW);
fail("Expected exception due to already registered listener");
} catch (Exception e) {
// Expected failure
@@ -141,7 +139,7 @@ public class ShellTaskOrganizerTests {
// Check that the tasks are next reported when the listener is added
TrackingTaskListener listener = new TrackingTaskListener();
- mOrganizer.addListener(listener, TASK_LISTENER_TYPE_MULTI_WINDOW);
+ mOrganizer.addListenerForType(listener, TASK_LISTENER_TYPE_MULTI_WINDOW);
assertTrue(listener.appeared.contains(task1));
assertTrue(listener.appeared.contains(task2));
}
@@ -150,7 +148,7 @@ public class ShellTaskOrganizerTests {
public void testAppearedVanished() {
RunningTaskInfo taskInfo = createTaskInfo(1, WINDOWING_MODE_MULTI_WINDOW);
TrackingTaskListener listener = new TrackingTaskListener();
- mOrganizer.addListener(listener, TASK_LISTENER_TYPE_MULTI_WINDOW);
+ mOrganizer.addListenerForType(listener, TASK_LISTENER_TYPE_MULTI_WINDOW);
mOrganizer.onTaskAppeared(taskInfo, null);
assertTrue(listener.appeared.contains(taskInfo));
@@ -164,7 +162,7 @@ public class ShellTaskOrganizerTests {
mOrganizer.onTaskAppeared(taskInfo, null);
TrackingTaskListener listener = new TrackingTaskListener();
- mOrganizer.addListener(listener, TASK_LISTENER_TYPE_MULTI_WINDOW);
+ mOrganizer.addListenerForType(listener, TASK_LISTENER_TYPE_MULTI_WINDOW);
assertTrue(listener.appeared.contains(taskInfo));
}
@@ -173,8 +171,8 @@ public class ShellTaskOrganizerTests {
RunningTaskInfo taskInfo = createTaskInfo(1, WINDOWING_MODE_MULTI_WINDOW);
TrackingTaskListener mwListener = new TrackingTaskListener();
TrackingTaskListener pipListener = new TrackingTaskListener();
- mOrganizer.addListener(mwListener, TASK_LISTENER_TYPE_MULTI_WINDOW);
- mOrganizer.addListener(pipListener, TASK_LISTENER_TYPE_PIP);
+ mOrganizer.addListenerForType(mwListener, TASK_LISTENER_TYPE_MULTI_WINDOW);
+ mOrganizer.addListenerForType(pipListener, TASK_LISTENER_TYPE_PIP);
mOrganizer.onTaskAppeared(taskInfo, null);
assertTrue(mwListener.appeared.contains(taskInfo));
assertTrue(pipListener.appeared.isEmpty());
@@ -185,6 +183,65 @@ public class ShellTaskOrganizerTests {
assertTrue(pipListener.appeared.contains(taskInfo));
}
+ @Test
+ public void testAddListenerForTaskId_afterTypeListener() {
+ RunningTaskInfo task1 = createTaskInfo(1, WINDOWING_MODE_MULTI_WINDOW);
+ TrackingTaskListener mwListener = new TrackingTaskListener();
+ TrackingTaskListener task1Listener = new TrackingTaskListener();
+ mOrganizer.addListenerForType(mwListener, TASK_LISTENER_TYPE_MULTI_WINDOW);
+ mOrganizer.onTaskAppeared(task1, null);
+ assertTrue(mwListener.appeared.contains(task1));
+
+ // Add task 1 specific listener
+ mOrganizer.addListenerForTaskId(task1Listener, 1);
+ assertTrue(mwListener.vanished.contains(task1));
+ assertTrue(task1Listener.appeared.contains(task1));
+ }
+
+ @Test
+ public void testAddListenerForTaskId_beforeTypeListener() {
+ RunningTaskInfo task1 = createTaskInfo(1, WINDOWING_MODE_MULTI_WINDOW);
+ TrackingTaskListener mwListener = new TrackingTaskListener();
+ TrackingTaskListener task1Listener = new TrackingTaskListener();
+ mOrganizer.onTaskAppeared(task1, null);
+ mOrganizer.addListenerForTaskId(task1Listener, 1);
+ assertTrue(task1Listener.appeared.contains(task1));
+
+ mOrganizer.addListenerForType(mwListener, TASK_LISTENER_TYPE_MULTI_WINDOW);
+ assertFalse(mwListener.appeared.contains(task1));
+ }
+
+ @Test
+ public void testGetTaskListener() {
+ RunningTaskInfo task1 = createTaskInfo(1, WINDOWING_MODE_MULTI_WINDOW);
+
+ TrackingTaskListener mwListener = new TrackingTaskListener();
+ mOrganizer.addListenerForType(mwListener, TASK_LISTENER_TYPE_MULTI_WINDOW);
+
+ TrackingTaskListener cookieListener = new TrackingTaskListener();
+ IBinder cookie = new Binder();
+ task1.addLaunchCookie(cookie);
+ mOrganizer.setPendingLaunchCookieListener(cookie, cookieListener);
+
+ // Priority goes to the cookie listener so we would expect the task appear to show up there
+ // instead of the multi-window type listener.
+ mOrganizer.onTaskAppeared(task1, null);
+ assertTrue(cookieListener.appeared.contains(task1));
+ assertFalse(mwListener.appeared.contains(task1));
+
+ TrackingTaskListener task1Listener = new TrackingTaskListener();
+
+ boolean gotException = false;
+ try {
+ mOrganizer.addListenerForTaskId(task1Listener, 1);
+ } catch (Exception e) {
+ gotException = true;
+ }
+ // It should not be possible to add a task id listener for a task already mapped to a
+ // listener through cookie.
+ assertTrue(gotException);
+ }
+
private RunningTaskInfo createTaskInfo(int taskId, int windowingMode) {
RunningTaskInfo taskInfo = new RunningTaskInfo();
taskInfo.taskId = taskId;
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/pip/PipBoundsHandlerTest.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/pip/PipBoundsHandlerTest.java
index d9e3148913b3..e0ac8e24756d 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/pip/PipBoundsHandlerTest.java
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/pip/PipBoundsHandlerTest.java
@@ -20,7 +20,6 @@ import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
-import android.content.ComponentName;
import android.graphics.Rect;
import android.testing.AndroidTestingRunner;
import android.testing.TestableLooper;
@@ -58,15 +57,13 @@ public class PipBoundsHandlerTest extends PipTestCase {
private PipBoundsHandler mPipBoundsHandler;
private DisplayInfo mDefaultDisplayInfo;
- private ComponentName mTestComponentName1;
- private ComponentName mTestComponentName2;
+ private PipBoundsState mPipBoundsState;
@Before
public void setUp() throws Exception {
initializeMockResources();
- mPipBoundsHandler = new PipBoundsHandler(mContext);
- mTestComponentName1 = new ComponentName(mContext, "component1");
- mTestComponentName2 = new ComponentName(mContext, "component2");
+ mPipBoundsState = new PipBoundsState();
+ mPipBoundsHandler = new PipBoundsHandler(mContext, mPipBoundsState);
mPipBoundsHandler.onDisplayInfoChanged(mDefaultDisplayInfo);
}
@@ -126,8 +123,8 @@ public class PipBoundsHandlerTest extends PipTestCase {
(MAX_ASPECT_RATIO + DEFAULT_ASPECT_RATIO) / 2
};
for (float aspectRatio : aspectRatios) {
- final Rect destinationBounds = mPipBoundsHandler.getDestinationBounds(
- mTestComponentName1, aspectRatio, EMPTY_CURRENT_BOUNDS, EMPTY_MINIMAL_SIZE);
+ final Rect destinationBounds = mPipBoundsHandler.getDestinationBounds(aspectRatio,
+ EMPTY_CURRENT_BOUNDS, EMPTY_MINIMAL_SIZE);
final float actualAspectRatio =
destinationBounds.width() / (destinationBounds.height() * 1f);
assertEquals("Destination bounds matches the given aspect ratio",
@@ -142,8 +139,8 @@ public class PipBoundsHandlerTest extends PipTestCase {
MAX_ASPECT_RATIO * 2
};
for (float aspectRatio : invalidAspectRatios) {
- final Rect destinationBounds = mPipBoundsHandler.getDestinationBounds(
- mTestComponentName1, aspectRatio, EMPTY_CURRENT_BOUNDS, EMPTY_MINIMAL_SIZE);
+ final Rect destinationBounds = mPipBoundsHandler.getDestinationBounds(aspectRatio,
+ EMPTY_CURRENT_BOUNDS, EMPTY_MINIMAL_SIZE);
final float actualAspectRatio =
destinationBounds.width() / (destinationBounds.height() * 1f);
assertEquals("Destination bounds fallbacks to default aspect ratio",
@@ -158,8 +155,8 @@ public class PipBoundsHandlerTest extends PipTestCase {
final Rect currentBounds = new Rect(0, 0, 0, 100);
currentBounds.right = (int) (currentBounds.height() * aspectRatio) + currentBounds.left;
- final Rect destinationBounds = mPipBoundsHandler.getDestinationBounds(
- mTestComponentName1, aspectRatio, currentBounds, EMPTY_MINIMAL_SIZE);
+ final Rect destinationBounds = mPipBoundsHandler.getDestinationBounds(aspectRatio,
+ currentBounds, EMPTY_MINIMAL_SIZE);
final float actualAspectRatio =
destinationBounds.width() / (destinationBounds.height() * 1f);
@@ -182,8 +179,8 @@ public class PipBoundsHandlerTest extends PipTestCase {
for (int i = 0; i < aspectRatios.length; i++) {
final float aspectRatio = aspectRatios[i];
final Size minimalSize = minimalSizes[i];
- final Rect destinationBounds = mPipBoundsHandler.getDestinationBounds(
- mTestComponentName1, aspectRatio, EMPTY_CURRENT_BOUNDS, minimalSize);
+ final Rect destinationBounds = mPipBoundsHandler.getDestinationBounds(aspectRatio,
+ EMPTY_CURRENT_BOUNDS, minimalSize);
assertTrue("Destination bounds is no smaller than minimal requirement",
(destinationBounds.width() == minimalSize.getWidth()
&& destinationBounds.height() >= minimalSize.getHeight())
@@ -203,8 +200,8 @@ public class PipBoundsHandlerTest extends PipTestCase {
currentBounds.right = (int) (currentBounds.height() * aspectRatio) + currentBounds.left;
final Size minSize = new Size(currentBounds.width() / 2, currentBounds.height() / 2);
- final Rect destinationBounds = mPipBoundsHandler.getDestinationBounds(
- mTestComponentName1, aspectRatio, currentBounds, minSize);
+ final Rect destinationBounds = mPipBoundsHandler.getDestinationBounds(aspectRatio,
+ currentBounds, minSize);
assertTrue("Destination bounds ignores minimal size",
destinationBounds.width() > minSize.getWidth()
@@ -212,28 +209,44 @@ public class PipBoundsHandlerTest extends PipTestCase {
}
@Test
- public void getDestinationBounds_withDifferentComponentName_ignoreLastPosition() {
- final Rect oldPosition = mPipBoundsHandler.getDestinationBounds(mTestComponentName1,
- DEFAULT_ASPECT_RATIO, EMPTY_CURRENT_BOUNDS, EMPTY_MINIMAL_SIZE);
+ public void getDestinationBounds_reentryStateExists_restoreLastSize() {
+ final Rect reentryBounds = mPipBoundsHandler.getDestinationBounds(DEFAULT_ASPECT_RATIO,
+ EMPTY_CURRENT_BOUNDS, EMPTY_MINIMAL_SIZE);
+ reentryBounds.scale(1.25f);
+ final float reentrySnapFraction = mPipBoundsHandler.getSnapFraction(reentryBounds);
+
+ mPipBoundsState.saveReentryState(reentryBounds, reentrySnapFraction);
+ final Rect destinationBounds = mPipBoundsHandler.getDestinationBounds(DEFAULT_ASPECT_RATIO,
+ EMPTY_CURRENT_BOUNDS, EMPTY_MINIMAL_SIZE);
+
+ assertEquals(reentryBounds.width(), destinationBounds.width());
+ assertEquals(reentryBounds.height(), destinationBounds.height());
+ }
+
+ @Test
+ public void getDestinationBounds_reentryStateExists_restoreLastPosition() {
+ final Rect reentryBounds = mPipBoundsHandler.getDestinationBounds(DEFAULT_ASPECT_RATIO,
+ EMPTY_CURRENT_BOUNDS, EMPTY_MINIMAL_SIZE);
+ reentryBounds.offset(0, -100);
+ final float reentrySnapFraction = mPipBoundsHandler.getSnapFraction(reentryBounds);
- oldPosition.offset(0, -100);
- mPipBoundsHandler.onSaveReentryBounds(mTestComponentName1, oldPosition);
+ mPipBoundsState.saveReentryState(reentryBounds, reentrySnapFraction);
- final Rect newPosition = mPipBoundsHandler.getDestinationBounds(mTestComponentName2,
- DEFAULT_ASPECT_RATIO, EMPTY_CURRENT_BOUNDS, EMPTY_MINIMAL_SIZE);
+ final Rect destinationBounds = mPipBoundsHandler.getDestinationBounds(DEFAULT_ASPECT_RATIO,
+ EMPTY_CURRENT_BOUNDS, EMPTY_MINIMAL_SIZE);
- assertNonBoundsInclusionWithMargin("ignore saved bounds", oldPosition, newPosition);
+ assertBoundsInclusionWithMargin("restoreLastPosition", reentryBounds, destinationBounds);
}
@Test
public void setShelfHeight_offsetBounds() {
final int shelfHeight = 100;
- final Rect oldPosition = mPipBoundsHandler.getDestinationBounds(mTestComponentName1,
- DEFAULT_ASPECT_RATIO, EMPTY_CURRENT_BOUNDS, EMPTY_MINIMAL_SIZE);
+ final Rect oldPosition = mPipBoundsHandler.getDestinationBounds(DEFAULT_ASPECT_RATIO,
+ EMPTY_CURRENT_BOUNDS, EMPTY_MINIMAL_SIZE);
mPipBoundsHandler.setShelfHeight(true, shelfHeight);
- final Rect newPosition = mPipBoundsHandler.getDestinationBounds(mTestComponentName1,
- DEFAULT_ASPECT_RATIO, EMPTY_CURRENT_BOUNDS, EMPTY_MINIMAL_SIZE);
+ final Rect newPosition = mPipBoundsHandler.getDestinationBounds(DEFAULT_ASPECT_RATIO,
+ EMPTY_CURRENT_BOUNDS, EMPTY_MINIMAL_SIZE);
oldPosition.offset(0, -shelfHeight);
assertBoundsInclusionWithMargin("offsetBounds by shelf", oldPosition, newPosition);
@@ -242,92 +255,30 @@ public class PipBoundsHandlerTest extends PipTestCase {
@Test
public void onImeVisibilityChanged_offsetBounds() {
final int imeHeight = 100;
- final Rect oldPosition = mPipBoundsHandler.getDestinationBounds(mTestComponentName1,
- DEFAULT_ASPECT_RATIO, EMPTY_CURRENT_BOUNDS, EMPTY_MINIMAL_SIZE);
+ final Rect oldPosition = mPipBoundsHandler.getDestinationBounds(DEFAULT_ASPECT_RATIO,
+ EMPTY_CURRENT_BOUNDS, EMPTY_MINIMAL_SIZE);
mPipBoundsHandler.onImeVisibilityChanged(true, imeHeight);
- final Rect newPosition = mPipBoundsHandler.getDestinationBounds(mTestComponentName1,
- DEFAULT_ASPECT_RATIO, EMPTY_CURRENT_BOUNDS, EMPTY_MINIMAL_SIZE);
+ final Rect newPosition = mPipBoundsHandler.getDestinationBounds(DEFAULT_ASPECT_RATIO,
+ EMPTY_CURRENT_BOUNDS, EMPTY_MINIMAL_SIZE);
oldPosition.offset(0, -imeHeight);
assertBoundsInclusionWithMargin("offsetBounds by IME", oldPosition, newPosition);
}
@Test
- public void onSaveReentryBounds_restoreLastPosition() {
- final Rect oldPosition = mPipBoundsHandler.getDestinationBounds(mTestComponentName1,
- DEFAULT_ASPECT_RATIO, EMPTY_CURRENT_BOUNDS, EMPTY_MINIMAL_SIZE);
-
- oldPosition.offset(0, -100);
- mPipBoundsHandler.onSaveReentryBounds(mTestComponentName1, oldPosition);
-
- final Rect newPosition = mPipBoundsHandler.getDestinationBounds(mTestComponentName1,
- DEFAULT_ASPECT_RATIO, EMPTY_CURRENT_BOUNDS, EMPTY_MINIMAL_SIZE);
-
- assertBoundsInclusionWithMargin("restoreLastPosition", oldPosition, newPosition);
- }
-
- @Test
- public void onSaveReentryBounds_restoreLastSize() {
- final Rect oldSize = mPipBoundsHandler.getDestinationBounds(mTestComponentName1,
- DEFAULT_ASPECT_RATIO, EMPTY_CURRENT_BOUNDS, EMPTY_MINIMAL_SIZE);
+ public void getDestinationBounds_noReentryState_useDefaultBounds() {
+ final Rect defaultBounds = mPipBoundsHandler.getDestinationBounds(DEFAULT_ASPECT_RATIO,
+ EMPTY_CURRENT_BOUNDS, EMPTY_MINIMAL_SIZE);
- oldSize.scale(1.25f);
- mPipBoundsHandler.onSaveReentryBounds(mTestComponentName1, oldSize);
+ mPipBoundsState.clearReentryState();
- final Rect newSize = mPipBoundsHandler.getDestinationBounds(mTestComponentName1,
- DEFAULT_ASPECT_RATIO, EMPTY_CURRENT_BOUNDS, EMPTY_MINIMAL_SIZE);
-
- assertEquals(oldSize.width(), newSize.width());
- assertEquals(oldSize.height(), newSize.height());
- }
-
- @Test
- public void onResetReentryBounds_useDefaultBounds() {
- final Rect defaultBounds = mPipBoundsHandler.getDestinationBounds(mTestComponentName1,
- DEFAULT_ASPECT_RATIO, EMPTY_CURRENT_BOUNDS, EMPTY_MINIMAL_SIZE);
- final Rect newBounds = new Rect(defaultBounds);
- newBounds.offset(0, -100);
- mPipBoundsHandler.onSaveReentryBounds(mTestComponentName1, newBounds);
-
- mPipBoundsHandler.onResetReentryBounds(mTestComponentName1);
- final Rect actualBounds = mPipBoundsHandler.getDestinationBounds(mTestComponentName1,
- DEFAULT_ASPECT_RATIO, EMPTY_CURRENT_BOUNDS, EMPTY_MINIMAL_SIZE);
+ final Rect actualBounds = mPipBoundsHandler.getDestinationBounds(DEFAULT_ASPECT_RATIO,
+ EMPTY_CURRENT_BOUNDS, EMPTY_MINIMAL_SIZE);
assertBoundsInclusionWithMargin("useDefaultBounds", defaultBounds, actualBounds);
}
- @Test
- public void onResetReentryBounds_componentMismatch_restoreLastPosition() {
- final Rect defaultBounds = mPipBoundsHandler.getDestinationBounds(mTestComponentName1,
- DEFAULT_ASPECT_RATIO, EMPTY_CURRENT_BOUNDS, EMPTY_MINIMAL_SIZE);
- final Rect newBounds = new Rect(defaultBounds);
- newBounds.offset(0, -100);
- mPipBoundsHandler.onSaveReentryBounds(mTestComponentName1, newBounds);
-
- mPipBoundsHandler.onResetReentryBounds(mTestComponentName2);
- final Rect actualBounds = mPipBoundsHandler.getDestinationBounds(mTestComponentName1,
- DEFAULT_ASPECT_RATIO, EMPTY_CURRENT_BOUNDS, EMPTY_MINIMAL_SIZE);
-
- assertBoundsInclusionWithMargin("restoreLastPosition", newBounds, actualBounds);
- }
-
- @Test
- public void onSaveReentryBounds_componentMismatch_restoreLastSize() {
- final Rect oldSize = mPipBoundsHandler.getDestinationBounds(mTestComponentName1,
- DEFAULT_ASPECT_RATIO, EMPTY_CURRENT_BOUNDS, EMPTY_MINIMAL_SIZE);
-
- oldSize.scale(1.25f);
- mPipBoundsHandler.onSaveReentryBounds(mTestComponentName1, oldSize);
-
- mPipBoundsHandler.onResetReentryBounds(mTestComponentName2);
- final Rect newSize = mPipBoundsHandler.getDestinationBounds(mTestComponentName1,
- DEFAULT_ASPECT_RATIO, EMPTY_CURRENT_BOUNDS, EMPTY_MINIMAL_SIZE);
-
- assertEquals(oldSize.width(), newSize.width());
- assertEquals(oldSize.height(), newSize.height());
- }
-
private void assertBoundsInclusionWithMargin(String from, Rect expected, Rect actual) {
final Rect expectedWithMargin = new Rect(expected);
expectedWithMargin.inset(-ROUNDING_ERROR_MARGIN, -ROUNDING_ERROR_MARGIN);
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/pip/PipBoundsStateTest.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/pip/PipBoundsStateTest.java
new file mode 100644
index 000000000000..dc9399edaa3b
--- /dev/null
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/pip/PipBoundsStateTest.java
@@ -0,0 +1,110 @@
+/*
+ * 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.pip;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+
+import android.content.ComponentName;
+import android.graphics.Rect;
+import android.testing.AndroidTestingRunner;
+import android.testing.TestableLooper;
+import android.util.Size;
+
+import androidx.test.filters.SmallTest;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+/**
+ * Tests for {@link PipBoundsState}.
+ */
+@RunWith(AndroidTestingRunner.class)
+@TestableLooper.RunWithLooper
+@SmallTest
+public class PipBoundsStateTest extends PipTestCase {
+
+ private static final Rect DEFAULT_BOUNDS = new Rect(0, 0, 10, 10);
+ private static final float DEFAULT_SNAP_FRACTION = 1.0f;
+
+ private PipBoundsState mPipBoundsState;
+ private ComponentName mTestComponentName1;
+ private ComponentName mTestComponentName2;
+
+ @Before
+ public void setUp() {
+ mPipBoundsState = new PipBoundsState();
+ mTestComponentName1 = new ComponentName(mContext, "component1");
+ mTestComponentName2 = new ComponentName(mContext, "component2");
+ }
+
+ @Test
+ public void testSetBounds() {
+ final Rect bounds = new Rect(0, 0, 100, 100);
+ mPipBoundsState.setBounds(bounds);
+
+ assertEquals(bounds, mPipBoundsState.getBounds());
+ }
+
+ @Test
+ public void testSetReentryState() {
+ final Rect bounds = new Rect(0, 0, 100, 100);
+ final float snapFraction = 0.5f;
+
+ mPipBoundsState.saveReentryState(bounds, snapFraction);
+
+ final PipBoundsState.PipReentryState state = mPipBoundsState.getReentryState();
+ assertEquals(new Size(100, 100), state.getSize());
+ assertEquals(snapFraction, state.getSnapFraction(), 0.01);
+ }
+
+ @Test
+ public void testClearReentryState() {
+ final Rect bounds = new Rect(0, 0, 100, 100);
+ final float snapFraction = 0.5f;
+
+ mPipBoundsState.saveReentryState(bounds, snapFraction);
+ mPipBoundsState.clearReentryState();
+
+ assertNull(mPipBoundsState.getReentryState());
+ }
+
+ @Test
+ public void testSetLastPipComponentName_notChanged_doesNotClearReentryState() {
+ mPipBoundsState.setLastPipComponentName(mTestComponentName1);
+ mPipBoundsState.saveReentryState(DEFAULT_BOUNDS, DEFAULT_SNAP_FRACTION);
+
+ mPipBoundsState.setLastPipComponentName(mTestComponentName1);
+
+ final PipBoundsState.PipReentryState state = mPipBoundsState.getReentryState();
+ assertNotNull(state);
+ assertEquals(new Size(DEFAULT_BOUNDS.width(), DEFAULT_BOUNDS.height()), state.getSize());
+ assertEquals(DEFAULT_SNAP_FRACTION, state.getSnapFraction(), 0.01);
+ }
+
+ @Test
+ public void testSetLastPipComponentName_changed_clearReentryState() {
+ mPipBoundsState.setLastPipComponentName(mTestComponentName1);
+ mPipBoundsState.saveReentryState(DEFAULT_BOUNDS, DEFAULT_SNAP_FRACTION);
+
+ mPipBoundsState.setLastPipComponentName(mTestComponentName2);
+
+ assertNull(mPipBoundsState.getReentryState());
+ }
+}
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/pip/phone/PipTaskOrganizerTest.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/pip/PipTaskOrganizerTest.java
index 46ebbf3846df..54543d25b401 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/pip/phone/PipTaskOrganizerTest.java
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/pip/PipTaskOrganizerTest.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package com.android.wm.shell.pip.phone;
+package com.android.wm.shell.pip;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyInt;
@@ -27,12 +27,6 @@ import android.testing.TestableLooper;
import com.android.wm.shell.ShellTaskOrganizer;
import com.android.wm.shell.common.DisplayController;
-import com.android.wm.shell.pip.PipBoundsHandler;
-import com.android.wm.shell.pip.PipBoundsState;
-import com.android.wm.shell.pip.PipSurfaceTransactionHelper;
-import com.android.wm.shell.pip.PipTaskOrganizer;
-import com.android.wm.shell.pip.PipTestCase;
-import com.android.wm.shell.pip.PipUiEventLogger;
import com.android.wm.shell.splitscreen.SplitScreen;
import org.junit.Before;
@@ -70,7 +64,7 @@ public class PipTaskOrganizerTest extends PipTestCase {
@Test
public void instantiatePipTaskOrganizer_addsTaskListener() {
- verify(mMockShellTaskOrganizer).addListener(any(), anyInt());
+ verify(mMockShellTaskOrganizer).addListenerForType(any(), anyInt());
}
@Test
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/pip/phone/PipTouchHandlerTest.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/pip/phone/PipTouchHandlerTest.java
index 4713142118a8..3f60cc01f20b 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/pip/phone/PipTouchHandlerTest.java
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/pip/phone/PipTouchHandlerTest.java
@@ -93,7 +93,7 @@ public class PipTouchHandlerTest extends PipTestCase {
public void setUp() throws Exception {
MockitoAnnotations.initMocks(this);
mPipBoundsState = new PipBoundsState();
- mPipBoundsHandler = new PipBoundsHandler(mContext);
+ mPipBoundsHandler = new PipBoundsHandler(mContext, mPipBoundsState);
mPipSnapAlgorithm = mPipBoundsHandler.getSnapAlgorithm();
mPipSnapAlgorithm = new PipSnapAlgorithm(mContext);
mPipTouchHandler = new PipTouchHandler(mContext, mPipMenuActivityController,
diff --git a/libs/androidfw/Android.bp b/libs/androidfw/Android.bp
index 8ab7da5257ab..903ca2aa0783 100644
--- a/libs/androidfw/Android.bp
+++ b/libs/androidfw/Android.bp
@@ -155,11 +155,12 @@ cc_test {
android: {
srcs: [
"tests/BackupData_test.cpp",
- "tests/BackupHelpers_test.cpp",
+ "tests/BackupHelpers_test.cpp",
+ "tests/CursorWindow_test.cpp",
"tests/ObbFile_test.cpp",
"tests/PosixUtils_test.cpp",
],
- shared_libs: common_test_libs + ["libui"],
+ shared_libs: common_test_libs + ["libbinder", "liblog", "libui"],
},
host: {
static_libs: common_test_libs + ["liblog", "libz"],
@@ -185,9 +186,28 @@ cc_benchmark {
// Actual benchmarks.
"tests/AssetManager2_bench.cpp",
"tests/AttributeResolution_bench.cpp",
+ "tests/CursorWindow_bench.cpp",
"tests/SparseEntry_bench.cpp",
"tests/Theme_bench.cpp",
],
shared_libs: common_test_libs,
data: ["tests/data/**/*.apk"],
}
+
+cc_library {
+ name: "libandroidfw_fuzzer_lib",
+ defaults: ["libandroidfw_defaults"],
+ host_supported: true,
+ srcs: [
+ "CursorWindow.cpp",
+ ],
+ export_include_dirs: ["include"],
+ target: {
+ android: {
+ shared_libs: common_test_libs + ["libbinder", "liblog"],
+ },
+ host: {
+ static_libs: common_test_libs + ["libbinder", "liblog"],
+ },
+ },
+}
diff --git a/libs/androidfw/AssetManager2.cpp b/libs/androidfw/AssetManager2.cpp
index b9765ea7212c..99dd3134ff8a 100644
--- a/libs/androidfw/AssetManager2.cpp
+++ b/libs/androidfw/AssetManager2.cpp
@@ -39,10 +39,8 @@
namespace android {
struct FindEntryResult {
- // A pointer to the resource table entry for this resource.
- // If the size of the entry is > sizeof(ResTable_entry), it can be cast to
- // a ResTable_map_entry and processed as a bag/map.
- ResTable_entry_handle entry;
+ // A pointer to the value of the resource table entry.
+ std::variant<Res_value, const ResTable_map_entry*> entry;
// The configuration for which the resulting entry was defined. This is already swapped to host
// endianness.
@@ -554,11 +552,9 @@ ApkAssetsCookie AssetManager2::FindEntry(uint32_t resid, uint16_t density_overri
if (!overlay_entry) {
// No id map entry exists for this target resource.
continue;
- }
-
- if (overlay_entry.IsTableEntry()) {
+ } else if (overlay_entry.IsInlineValue()) {
// The target resource is overlaid by an inline value not represented by a resource.
- out_entry->entry = overlay_entry.GetTableEntry();
+ out_entry->entry = overlay_entry.GetInlineValue();
out_entry->dynamic_ref_table = id_map.overlay_res_maps_.GetOverlayDynamicRefTable();
cookie = id_map.cookie;
continue;
@@ -580,7 +576,7 @@ ApkAssetsCookie AssetManager2::FindEntry(uint32_t resid, uint16_t density_overri
}
cookie = overlay_cookie;
- out_entry->entry = std::move(overlay_result.entry);
+ out_entry->entry = overlay_result.entry;
out_entry->config = overlay_result.config;
out_entry->dynamic_ref_table = id_map.overlay_res_maps_.GetOverlayDynamicRefTable();
if (resource_resolution_logging_enabled_) {
@@ -761,7 +757,19 @@ ApkAssetsCookie AssetManager2::FindEntryInternal(const PackageGroup& package_gro
return kInvalidCookie;
}
- out_entry->entry = ResTable_entry_handle::unmanaged(best_entry);
+ const uint16_t entry_size = dtohs(best_entry->size);
+ if (entry_size >= sizeof(ResTable_map_entry) &&
+ (dtohs(best_entry->flags) & ResTable_entry::FLAG_COMPLEX)) {
+ // The entry represents a bag/map.
+ out_entry->entry = reinterpret_cast<const ResTable_map_entry*>(best_entry);
+ } else {
+ // The entry represents a value.
+ Res_value value;
+ value.copyFrom_dtoh(*reinterpret_cast<const Res_value*>(
+ reinterpret_cast<const uint8_t*>(best_entry) + entry_size));
+ out_entry->entry = value;
+ }
+
out_entry->config = *best_config;
out_entry->type_flags = type_flags;
out_entry->package_name = &best_package->GetPackageName();
@@ -905,8 +913,8 @@ ApkAssetsCookie AssetManager2::GetResource(uint32_t resid, bool may_be_bag,
return kInvalidCookie;
}
- const ResTable_entry* table_entry = *entry.entry;
- if (dtohs(table_entry->flags) & ResTable_entry::FLAG_COMPLEX) {
+ auto result_map_entry = std::get_if<const ResTable_map_entry*>(&entry.entry);
+ if (result_map_entry != nullptr) {
if (!may_be_bag) {
LOG(ERROR) << base::StringPrintf("Resource %08x is a complex map type.", resid);
return kInvalidCookie;
@@ -920,11 +928,8 @@ ApkAssetsCookie AssetManager2::GetResource(uint32_t resid, bool may_be_bag,
return cookie;
}
- const Res_value* device_value = reinterpret_cast<const Res_value*>(
- reinterpret_cast<const uint8_t*>(table_entry) + dtohs(table_entry->size));
- out_value->copyFrom_dtoh(*device_value);
-
// Convert the package ID to the runtime assigned package ID.
+ *out_value = std::get<Res_value>(entry.entry);
entry.dynamic_ref_table->lookupResourceValue(out_value);
*out_selected_config = entry.config;
@@ -1004,19 +1009,15 @@ const ResolvedBag* AssetManager2::GetBag(uint32_t resid, std::vector<uint32_t>&
return nullptr;
}
- // Check that the size of the entry header is at least as big as
- // the desired ResTable_map_entry. Also verify that the entry
- // was intended to be a map.
- const ResTable_entry* table_entry = *entry.entry;
- if (dtohs(table_entry->size) < sizeof(ResTable_map_entry) ||
- (dtohs(table_entry->flags) & ResTable_entry::FLAG_COMPLEX) == 0) {
+ auto result_map_entry = std::get_if<const ResTable_map_entry*>(&entry.entry);
+ if (result_map_entry == nullptr) {
// Not a bag, nothing to do.
return nullptr;
}
- const ResTable_map_entry* map = reinterpret_cast<const ResTable_map_entry*>(table_entry);
- const ResTable_map* map_entry =
- reinterpret_cast<const ResTable_map*>(reinterpret_cast<const uint8_t*>(map) + map->size);
+ auto map = reinterpret_cast<const ResTable_map_entry*>(*result_map_entry);
+ auto map_entry = reinterpret_cast<const ResTable_map*>(
+ reinterpret_cast<const uint8_t*>(map) + map->size);
const ResTable_map* const map_entry_end = map_entry + dtohl(map->count);
// Keep track of ids that have already been seen to prevent infinite loops caused by circular
diff --git a/libs/androidfw/CursorWindow.cpp b/libs/androidfw/CursorWindow.cpp
index 71c8e1f6121f..1b8db46c54b6 100644
--- a/libs/androidfw/CursorWindow.cpp
+++ b/libs/androidfw/CursorWindow.cpp
@@ -14,19 +14,14 @@
* limitations under the License.
*/
-#undef LOG_TAG
#define LOG_TAG "CursorWindow"
#include <androidfw/CursorWindow.h>
-#include <binder/Parcel.h>
-#include <utils/Log.h>
-#include <cutils/ashmem.h>
#include <sys/mman.h>
-#include <assert.h>
-#include <string.h>
-#include <stdlib.h>
+#include "android-base/logging.h"
+#include "cutils/ashmem.h"
namespace android {
@@ -36,11 +31,10 @@ namespace android {
*/
static constexpr const size_t kInlineSize = 16384;
-CursorWindow::CursorWindow(const String8& name, int ashmemFd, void* data, size_t size,
- size_t inflatedSize, bool readOnly) :
- mName(name), mAshmemFd(ashmemFd), mData(data), mSize(size),
- mInflatedSize(inflatedSize), mReadOnly(readOnly) {
- mHeader = static_cast<Header*>(mData);
+static constexpr const size_t kSlotShift = 4;
+static constexpr const size_t kSlotSizeBytes = 1 << kSlotShift;
+
+CursorWindow::CursorWindow() {
}
CursorWindow::~CursorWindow() {
@@ -52,234 +46,243 @@ CursorWindow::~CursorWindow() {
}
}
-status_t CursorWindow::create(const String8& name, size_t inflatedSize,
- CursorWindow** outCursorWindow) {
- *outCursorWindow = nullptr;
-
- size_t size = std::min(kInlineSize, inflatedSize);
- void* data = calloc(size, 1);
- if (!data) return NO_MEMORY;
-
- CursorWindow* window = new CursorWindow(name, -1, data, size,
- inflatedSize, false /*readOnly*/);
- status_t result = window->clear();
- if (!result) {
- LOG_WINDOW("Created new CursorWindow: freeOffset=%d, "
- "numRows=%d, numColumns=%d, mSize=%zu, mData=%p",
- window->mHeader->freeOffset,
- window->mHeader->numRows,
- window->mHeader->numColumns,
- window->mSize, window->mData);
- *outCursorWindow = window;
- return OK;
- }
+status_t CursorWindow::create(const String8 &name, size_t inflatedSize, CursorWindow **outWindow) {
+ *outWindow = nullptr;
+
+ CursorWindow* window = new CursorWindow();
+ if (!window) goto fail;
+
+ window->mName = name;
+ window->mSize = std::min(kInlineSize, inflatedSize);
+ window->mInflatedSize = inflatedSize;
+ window->mData = malloc(window->mSize);
+ if (!window->mData) goto fail;
+ window->mReadOnly = false;
+
+ window->clear();
+ window->updateSlotsData();
+
+ LOG(DEBUG) << "Created: " << window->toString();
+ *outWindow = window;
+ return OK;
+
+fail:
+ LOG(ERROR) << "Failed create";
+fail_silent:
delete window;
- return result;
+ return UNKNOWN_ERROR;
}
-status_t CursorWindow::inflate() {
- // Shortcut when we can't expand any further
- if (mSize == mInflatedSize) return INVALID_OPERATION;
+status_t CursorWindow::maybeInflate() {
+ int ashmemFd = 0;
+ void* newData = nullptr;
+
+ // Bail early when we can't expand any further
+ if (mReadOnly || mSize == mInflatedSize) {
+ return INVALID_OPERATION;
+ }
String8 ashmemName("CursorWindow: ");
ashmemName.append(mName);
- status_t result;
- int ashmemFd = ashmem_create_region(ashmemName.string(), mInflatedSize);
+ ashmemFd = ashmem_create_region(ashmemName.string(), mInflatedSize);
if (ashmemFd < 0) {
- result = -errno;
- ALOGE("CursorWindow: ashmem_create_region() failed: errno=%d.", errno);
- } else {
- result = ashmem_set_prot_region(ashmemFd, PROT_READ | PROT_WRITE);
- if (result < 0) {
- ALOGE("CursorWindow: ashmem_set_prot_region() failed: errno=%d",errno);
- } else {
- void* data = ::mmap(NULL, mInflatedSize, PROT_READ | PROT_WRITE,
- MAP_SHARED, ashmemFd, 0);
- if (data == MAP_FAILED) {
- result = -errno;
- ALOGE("CursorWindow: mmap() failed: errno=%d.", errno);
- } else {
- result = ashmem_set_prot_region(ashmemFd, PROT_READ);
- if (result < 0) {
- ALOGE("CursorWindow: ashmem_set_prot_region() failed: errno=%d.", errno);
- } else {
- // Move inline contents into new ashmem region
- memcpy(data, mData, mSize);
- free(mData);
- mAshmemFd = ashmemFd;
- mData = data;
- mHeader = static_cast<Header*>(mData);
- mSize = mInflatedSize;
- LOG_WINDOW("Inflated CursorWindow: freeOffset=%d, "
- "numRows=%d, numColumns=%d, mSize=%zu, mData=%p",
- mHeader->freeOffset,
- mHeader->numRows,
- mHeader->numColumns,
- mSize, mData);
- return OK;
- }
- }
- ::munmap(data, mInflatedSize);
- }
- ::close(ashmemFd);
+ PLOG(ERROR) << "Failed ashmem_create_region";
+ goto fail_silent;
}
- return result;
-}
-status_t CursorWindow::createFromParcel(Parcel* parcel, CursorWindow** outCursorWindow) {
- *outCursorWindow = nullptr;
+ if (ashmem_set_prot_region(ashmemFd, PROT_READ | PROT_WRITE) < 0) {
+ PLOG(ERROR) << "Failed ashmem_set_prot_region";
+ goto fail_silent;
+ }
- String8 name;
- status_t result = parcel->readString8(&name);
- if (result) return result;
+ newData = ::mmap(nullptr, mInflatedSize, PROT_READ | PROT_WRITE, MAP_SHARED, ashmemFd, 0);
+ if (newData == MAP_FAILED) {
+ PLOG(ERROR) << "Failed mmap";
+ goto fail_silent;
+ }
- bool isAshmem;
- result = parcel->readBool(&isAshmem);
- if (result) return result;
+ if (ashmem_set_prot_region(ashmemFd, PROT_READ) < 0) {
+ PLOG(ERROR) << "Failed ashmem_set_prot_region";
+ goto fail_silent;
+ }
- if (isAshmem) {
- return createFromParcelAshmem(parcel, name, outCursorWindow);
- } else {
- return createFromParcelInline(parcel, name, outCursorWindow);
+ {
+ // Migrate existing contents into new ashmem region
+ uint32_t slotsSize = mSize - mSlotsOffset;
+ uint32_t newSlotsOffset = mInflatedSize - slotsSize;
+ memcpy(static_cast<uint8_t*>(newData),
+ static_cast<uint8_t*>(mData), mAllocOffset);
+ memcpy(static_cast<uint8_t*>(newData) + newSlotsOffset,
+ static_cast<uint8_t*>(mData) + mSlotsOffset, slotsSize);
+
+ free(mData);
+ mAshmemFd = ashmemFd;
+ mData = newData;
+ mSize = mInflatedSize;
+ mSlotsOffset = newSlotsOffset;
+
+ updateSlotsData();
}
+
+ LOG(DEBUG) << "Inflated: " << this->toString();
+ return OK;
+
+fail:
+ LOG(ERROR) << "Failed maybeInflate";
+fail_silent:
+ ::munmap(newData, mInflatedSize);
+ ::close(ashmemFd);
+ return UNKNOWN_ERROR;
}
-status_t CursorWindow::createFromParcelAshmem(Parcel* parcel, String8& name,
- CursorWindow** outCursorWindow) {
- status_t result;
- int actualSize;
- int ashmemFd = parcel->readFileDescriptor();
- if (ashmemFd == int(BAD_TYPE)) {
- result = BAD_TYPE;
- ALOGE("CursorWindow: readFileDescriptor() failed");
+status_t CursorWindow::createFromParcel(Parcel* parcel, CursorWindow** outWindow) {
+ *outWindow = nullptr;
+
+ CursorWindow* window = new CursorWindow();
+ if (!window) goto fail;
+
+ if (parcel->readString8(&window->mName)) goto fail;
+ if (parcel->readUint32(&window->mNumRows)) goto fail;
+ if (parcel->readUint32(&window->mNumColumns)) goto fail;
+ if (parcel->readUint32(&window->mSize)) goto fail;
+
+ if ((window->mNumRows * window->mNumColumns * kSlotSizeBytes) > window->mSize) {
+ LOG(ERROR) << "Unexpected size " << window->mSize << " for " << window->mNumRows
+ << " rows and " << window->mNumColumns << " columns";
+ goto fail_silent;
+ }
+
+ bool isAshmem;
+ if (parcel->readBool(&isAshmem)) goto fail;
+ if (isAshmem) {
+ window->mAshmemFd = parcel->readFileDescriptor();
+ if (window->mAshmemFd < 0) {
+ LOG(ERROR) << "Failed readFileDescriptor";
+ goto fail_silent;
+ }
+
+ window->mAshmemFd = ::fcntl(window->mAshmemFd, F_DUPFD_CLOEXEC, 0);
+ if (window->mAshmemFd < 0) {
+ PLOG(ERROR) << "Failed F_DUPFD_CLOEXEC";
+ goto fail_silent;
+ }
+
+ window->mData = ::mmap(nullptr, window->mSize, PROT_READ, MAP_SHARED, window->mAshmemFd, 0);
+ if (window->mData == MAP_FAILED) {
+ PLOG(ERROR) << "Failed mmap";
+ goto fail_silent;
+ }
} else {
- ssize_t size = ashmem_get_size_region(ashmemFd);
- if (size < 0) {
- result = UNKNOWN_ERROR;
- ALOGE("CursorWindow: ashmem_get_size_region() failed: errno=%d.", errno);
- } else {
- int dupAshmemFd = ::fcntl(ashmemFd, F_DUPFD_CLOEXEC, 0);
- if (dupAshmemFd < 0) {
- result = -errno;
- ALOGE("CursorWindow: fcntl() failed: errno=%d.", errno);
- } else {
- // the size of the ashmem descriptor can be modified between ashmem_get_size_region
- // call and mmap, so we'll check again immediately after memory is mapped
- void* data = ::mmap(NULL, size, PROT_READ, MAP_SHARED, dupAshmemFd, 0);
- if (data == MAP_FAILED) {
- result = -errno;
- ALOGE("CursorWindow: mmap() failed: errno=%d.", errno);
- } else if ((actualSize = ashmem_get_size_region(dupAshmemFd)) != size) {
- ::munmap(data, size);
- result = BAD_VALUE;
- ALOGE("CursorWindow: ashmem_get_size_region() returned %d, expected %d"
- " errno=%d",
- actualSize, (int) size, errno);
- } else {
- CursorWindow* window = new CursorWindow(name, dupAshmemFd,
- data, size, size, true /*readOnly*/);
- LOG_WINDOW("Created CursorWindow from ashmem parcel: freeOffset=%d, "
- "numRows=%d, numColumns=%d, mSize=%zu, mData=%p",
- window->mHeader->freeOffset,
- window->mHeader->numRows,
- window->mHeader->numColumns,
- window->mSize, window->mData);
- *outCursorWindow = window;
- return OK;
- }
- ::close(dupAshmemFd);
- }
+ window->mAshmemFd = -1;
+
+ if (window->mSize > kInlineSize) {
+ LOG(ERROR) << "Unexpected size " << window->mSize << " for inline window";
+ goto fail_silent;
}
+
+ window->mData = malloc(window->mSize);
+ if (!window->mData) goto fail;
+
+ if (parcel->read(window->mData, window->mSize)) goto fail;
}
- *outCursorWindow = NULL;
- return result;
-}
-status_t CursorWindow::createFromParcelInline(Parcel* parcel, String8& name,
- CursorWindow** outCursorWindow) {
- uint32_t sentSize;
- status_t result = parcel->readUint32(&sentSize);
- if (result) return result;
- if (sentSize > kInlineSize) return NO_MEMORY;
-
- void* data = calloc(sentSize, 1);
- if (!data) return NO_MEMORY;
-
- result = parcel->read(data, sentSize);
- if (result) return result;
-
- CursorWindow* window = new CursorWindow(name, -1, data, sentSize,
- sentSize, true /*readOnly*/);
- LOG_WINDOW("Created CursorWindow from inline parcel: freeOffset=%d, "
- "numRows=%d, numColumns=%d, mSize=%zu, mData=%p",
- window->mHeader->freeOffset,
- window->mHeader->numRows,
- window->mHeader->numColumns,
- window->mSize, window->mData);
- *outCursorWindow = window;
+ // We just came from a remote source, so we're read-only
+ // and we can't inflate ourselves
+ window->mInflatedSize = window->mSize;
+ window->mReadOnly = true;
+
+ window->updateSlotsData();
+
+ LOG(DEBUG) << "Created from parcel: " << window->toString();
+ *outWindow = window;
return OK;
+
+fail:
+ LOG(ERROR) << "Failed createFromParcel";
+fail_silent:
+ delete window;
+ return UNKNOWN_ERROR;
}
status_t CursorWindow::writeToParcel(Parcel* parcel) {
- LOG_WINDOW("Writing CursorWindow: freeOffset=%d, "
- "numRows=%d, numColumns=%d, mSize=%zu, mData=%p",
- mHeader->freeOffset,
- mHeader->numRows,
- mHeader->numColumns,
- mSize, mData);
-
- status_t result = parcel->writeString8(mName);
- if (result) return result;
+ LOG(DEBUG) << "Writing to parcel: " << this->toString();
+ if (parcel->writeString8(mName)) goto fail;
+ if (parcel->writeUint32(mNumRows)) goto fail;
+ if (parcel->writeUint32(mNumColumns)) goto fail;
if (mAshmemFd != -1) {
- result = parcel->writeBool(true);
- if (result) return result;
- return writeToParcelAshmem(parcel);
+ if (parcel->writeUint32(mSize)) goto fail;
+ if (parcel->writeBool(true)) goto fail;
+ if (parcel->writeDupFileDescriptor(mAshmemFd)) goto fail;
} else {
- result = parcel->writeBool(false);
- if (result) return result;
- return writeToParcelInline(parcel);
+ // Since we know we're going to be read-only on the remote side,
+ // we can compact ourselves on the wire, with just enough padding
+ // to ensure our slots stay aligned
+ size_t slotsSize = mSize - mSlotsOffset;
+ size_t compactedSize = mAllocOffset + slotsSize;
+ compactedSize = (compactedSize + 3) & ~3;
+ if (parcel->writeUint32(compactedSize)) goto fail;
+ if (parcel->writeBool(false)) goto fail;
+ void* dest = parcel->writeInplace(compactedSize);
+ if (!dest) goto fail;
+ memcpy(static_cast<uint8_t*>(dest),
+ static_cast<uint8_t*>(mData), mAllocOffset);
+ memcpy(static_cast<uint8_t*>(dest) + compactedSize - slotsSize,
+ static_cast<uint8_t*>(mData) + mSlotsOffset, slotsSize);
}
-}
-
-status_t CursorWindow::writeToParcelAshmem(Parcel* parcel) {
- return parcel->writeDupFileDescriptor(mAshmemFd);
-}
-
-status_t CursorWindow::writeToParcelInline(Parcel* parcel) {
- status_t result = parcel->writeUint32(mHeader->freeOffset);
- if (result) return result;
+ return OK;
- return parcel->write(mData, mHeader->freeOffset);
+fail:
+ LOG(ERROR) << "Failed writeToParcel";
+fail_silent:
+ return UNKNOWN_ERROR;
}
status_t CursorWindow::clear() {
if (mReadOnly) {
return INVALID_OPERATION;
}
+ mAllocOffset = 0;
+ mSlotsOffset = mSize;
+ mNumRows = 0;
+ mNumColumns = 0;
+ return OK;
+}
- mHeader->freeOffset = sizeof(Header) + sizeof(RowSlotChunk);
- mHeader->firstChunkOffset = sizeof(Header);
- mHeader->numRows = 0;
- mHeader->numColumns = 0;
+void CursorWindow::updateSlotsData() {
+ mSlotsStart = static_cast<uint8_t*>(mData) + mSize - kSlotSizeBytes;
+ mSlotsEnd = static_cast<uint8_t*>(mData) + mSlotsOffset;
+}
- RowSlotChunk* firstChunk = static_cast<RowSlotChunk*>(offsetToPtr(mHeader->firstChunkOffset));
- firstChunk->nextChunkOffset = 0;
- return OK;
+void* CursorWindow::offsetToPtr(uint32_t offset, uint32_t bufferSize = 0) {
+ if (offset > mSize) {
+ LOG(ERROR) << "Offset " << offset
+ << " out of bounds, max value " << mSize;
+ return nullptr;
+ }
+ if (offset + bufferSize > mSize) {
+ LOG(ERROR) << "End offset " << (offset + bufferSize)
+ << " out of bounds, max value " << mSize;
+ return nullptr;
+ }
+ return static_cast<uint8_t*>(mData) + offset;
+}
+
+uint32_t CursorWindow::offsetFromPtr(void* ptr) {
+ return static_cast<uint8_t*>(ptr) - static_cast<uint8_t*>(mData);
}
status_t CursorWindow::setNumColumns(uint32_t numColumns) {
if (mReadOnly) {
return INVALID_OPERATION;
}
-
- uint32_t cur = mHeader->numColumns;
- if ((cur > 0 || mHeader->numRows > 0) && cur != numColumns) {
- ALOGE("Trying to go from %d columns to %d", cur, numColumns);
+ uint32_t cur = mNumColumns;
+ if ((cur > 0 || mNumRows > 0) && cur != numColumns) {
+ LOG(ERROR) << "Trying to go from " << cur << " columns to " << numColumns;
return INVALID_OPERATION;
}
- mHeader->numColumns = numColumns;
+ mNumColumns = numColumns;
return OK;
}
@@ -287,30 +290,19 @@ status_t CursorWindow::allocRow() {
if (mReadOnly) {
return INVALID_OPERATION;
}
-
- // Fill in the row slot
- RowSlot* rowSlot = allocRowSlot();
- if (rowSlot == NULL) {
- return NO_MEMORY;
- }
- uint32_t rowSlotOffset = offsetFromPtr(rowSlot);
-
- // Allocate the slots for the field directory
- size_t fieldDirSize = mHeader->numColumns * sizeof(FieldSlot);
- uint32_t fieldDirOffset = alloc(fieldDirSize, true /*aligned*/);
- if (!fieldDirOffset) {
- mHeader->numRows--;
- LOG_WINDOW("The row failed, so back out the new row accounting "
- "from allocRowSlot %d", mHeader->numRows);
- return NO_MEMORY;
+ size_t size = mNumColumns * kSlotSizeBytes;
+ int32_t newOffset = mSlotsOffset - size;
+ if (newOffset < (int32_t) mAllocOffset) {
+ maybeInflate();
+ newOffset = mSlotsOffset - size;
+ if (newOffset < (int32_t) mAllocOffset) {
+ return NO_MEMORY;
+ }
}
- FieldSlot* fieldDir = static_cast<FieldSlot*>(offsetToPtr(fieldDirOffset));
- memset(fieldDir, 0, fieldDirSize);
-
- LOG_WINDOW("Allocated row %u, rowSlot is at offset %u, fieldDir is %zu bytes at offset %u\n",
- mHeader->numRows - 1, rowSlotOffset, fieldDirSize, fieldDirOffset);
- rowSlot = static_cast<RowSlot*>(offsetToPtr(rowSlotOffset));
- rowSlot->offset = fieldDirOffset;
+ memset(offsetToPtr(newOffset), 0, size);
+ mSlotsOffset = newOffset;
+ updateSlotsData();
+ mNumRows++;
return OK;
}
@@ -318,90 +310,48 @@ status_t CursorWindow::freeLastRow() {
if (mReadOnly) {
return INVALID_OPERATION;
}
-
- if (mHeader->numRows > 0) {
- mHeader->numRows--;
+ size_t size = mNumColumns * kSlotSizeBytes;
+ size_t newOffset = mSlotsOffset + size;
+ if (newOffset > mSize) {
+ return NO_MEMORY;
}
+ mSlotsOffset = newOffset;
+ updateSlotsData();
+ mNumRows--;
return OK;
}
-uint32_t CursorWindow::alloc(size_t size, bool aligned) {
- uint32_t padding;
- if (aligned) {
- // 4 byte alignment
- padding = (~mHeader->freeOffset + 1) & 3;
- } else {
- padding = 0;
- }
-
- uint32_t offset = mHeader->freeOffset + padding;
- uint32_t nextFreeOffset = offset + size;
- if (nextFreeOffset > mSize) {
- // Try inflating to ashmem before finally giving up
- inflate();
- if (nextFreeOffset > mSize) {
- ALOGW("Window is full: requested allocation %zu bytes, "
- "free space %zu bytes, window size %zu bytes",
- size, freeSpace(), mSize);
- return 0;
- }
- }
-
- mHeader->freeOffset = nextFreeOffset;
- return offset;
-}
-
-CursorWindow::RowSlot* CursorWindow::getRowSlot(uint32_t row) {
- uint32_t chunkPos = row;
- RowSlotChunk* chunk = static_cast<RowSlotChunk*>(
- offsetToPtr(mHeader->firstChunkOffset));
- while (chunkPos >= ROW_SLOT_CHUNK_NUM_ROWS) {
- chunk = static_cast<RowSlotChunk*>(offsetToPtr(chunk->nextChunkOffset));
- chunkPos -= ROW_SLOT_CHUNK_NUM_ROWS;
- }
- return &chunk->slots[chunkPos];
-}
-
-CursorWindow::RowSlot* CursorWindow::allocRowSlot() {
- uint32_t chunkPos = mHeader->numRows;
- RowSlotChunk* chunk = static_cast<RowSlotChunk*>(
- offsetToPtr(mHeader->firstChunkOffset));
- while (chunkPos > ROW_SLOT_CHUNK_NUM_ROWS) {
- chunk = static_cast<RowSlotChunk*>(offsetToPtr(chunk->nextChunkOffset));
- chunkPos -= ROW_SLOT_CHUNK_NUM_ROWS;
+status_t CursorWindow::alloc(size_t size, uint32_t* outOffset) {
+ if (mReadOnly) {
+ return INVALID_OPERATION;
}
- if (chunkPos == ROW_SLOT_CHUNK_NUM_ROWS) {
- if (!chunk->nextChunkOffset) {
- uint32_t chunkOffset = offsetFromPtr(chunk);
- uint32_t newChunk = alloc(sizeof(RowSlotChunk), true /*aligned*/);
- chunk = static_cast<RowSlotChunk*>(offsetToPtr(chunkOffset));
- chunk->nextChunkOffset = newChunk;
- if (!chunk->nextChunkOffset) {
- return NULL;
- }
+ size_t alignedSize = (size + 3) & ~3;
+ size_t newOffset = mAllocOffset + alignedSize;
+ if (newOffset > mSlotsOffset) {
+ maybeInflate();
+ newOffset = mAllocOffset + alignedSize;
+ if (newOffset > mSlotsOffset) {
+ return NO_MEMORY;
}
- chunk = static_cast<RowSlotChunk*>(offsetToPtr(chunk->nextChunkOffset));
- chunk->nextChunkOffset = 0;
- chunkPos = 0;
}
- mHeader->numRows += 1;
- return &chunk->slots[chunkPos];
+ *outOffset = mAllocOffset;
+ mAllocOffset = newOffset;
+ return OK;
}
CursorWindow::FieldSlot* CursorWindow::getFieldSlot(uint32_t row, uint32_t column) {
- if (row >= mHeader->numRows || column >= mHeader->numColumns) {
- ALOGE("Failed to read row %d, column %d from a CursorWindow which "
- "has %d rows, %d columns.",
- row, column, mHeader->numRows, mHeader->numColumns);
- return NULL;
- }
- RowSlot* rowSlot = getRowSlot(row);
- if (!rowSlot) {
- ALOGE("Failed to find rowSlot for row %d.", row);
- return NULL;
+ // This is carefully tuned to use as few cycles as
+ // possible, since this is an extremely hot code path;
+ // see CursorWindow_bench.cpp for more details
+ void *result = static_cast<uint8_t*>(mSlotsStart)
+ - (((row * mNumColumns) + column) << kSlotShift);
+ if (result < mSlotsEnd || result > mSlotsStart || column >= mNumColumns) {
+ LOG(ERROR) << "Failed to read row " << row << ", column " << column
+ << " from a window with " << mNumRows << " rows, " << mNumColumns << " columns";
+ return nullptr;
+ } else {
+ return static_cast<FieldSlot*>(result);
}
- FieldSlot* fieldDir = static_cast<FieldSlot*>(offsetToPtr(rowSlot->offset));
- return &fieldDir[column];
}
status_t CursorWindow::putBlob(uint32_t row, uint32_t column, const void* value, size_t size) {
@@ -423,16 +373,15 @@ status_t CursorWindow::putBlobOrString(uint32_t row, uint32_t column,
if (!fieldSlot) {
return BAD_VALUE;
}
- uint32_t fieldSlotOffset = offsetFromPtr(fieldSlot);
- uint32_t offset = alloc(size);
- if (!offset) {
+ uint32_t offset;
+ if (alloc(size, &offset)) {
return NO_MEMORY;
}
memcpy(offsetToPtr(offset), value, size);
- fieldSlot = static_cast<FieldSlot*>(offsetToPtr(fieldSlotOffset));
+ fieldSlot = getFieldSlot(row, column);
fieldSlot->type = type;
fieldSlot->data.buffer.offset = offset;
fieldSlot->data.buffer.size = size;
diff --git a/libs/androidfw/Idmap.cpp b/libs/androidfw/Idmap.cpp
index 5f231ffe4786..4e03ce5d9584 100644
--- a/libs/androidfw/Idmap.cpp
+++ b/libs/androidfw/Idmap.cpp
@@ -36,16 +36,12 @@ using ::android::base::StringPrintf;
namespace android {
-static bool compare_target_entries(const Idmap_target_entry &e1, const uint32_t target_id) {
- return dtohl(e1.target_id) < target_id;
-}
-
-static bool compare_overlay_entries(const Idmap_overlay_entry& e1, const uint32_t overlay_id) {
- return dtohl(e1.overlay_id) < overlay_id;
+uint32_t round_to_4_bytes(uint32_t size) {
+ return size + (4U - (size % 4U)) % 4U;
}
size_t Idmap_header::Size() const {
- return sizeof(Idmap_header) + sizeof(uint8_t) * dtohl(debug_info_size);
+ return sizeof(Idmap_header) + sizeof(uint8_t) * round_to_4_bytes(dtohl(debug_info_size));
}
OverlayStringPool::OverlayStringPool(const LoadedIdmap* loaded_idmap)
@@ -88,7 +84,10 @@ OverlayDynamicRefTable::OverlayDynamicRefTable(const Idmap_data_header* data_hea
status_t OverlayDynamicRefTable::lookupResourceId(uint32_t* resId) const {
const Idmap_overlay_entry* first_entry = entries_;
const Idmap_overlay_entry* end_entry = entries_ + dtohl(data_header_->overlay_entry_count);
- auto entry = std::lower_bound(first_entry, end_entry, *resId, compare_overlay_entries);
+ auto entry = std::lower_bound(first_entry, end_entry, *resId,
+ [](const Idmap_overlay_entry& e1, const uint32_t overlay_id) {
+ return dtohl(e1.overlay_id) < overlay_id;
+ });
if (entry == end_entry || dtohl(entry->overlay_id) != *resId) {
// A mapping for the target resource id could not be found.
@@ -96,7 +95,7 @@ status_t OverlayDynamicRefTable::lookupResourceId(uint32_t* resId) const {
}
*resId = (0x00FFFFFFU & dtohl(entry->target_id))
- | (((uint32_t) target_assigned_package_id_) << 24);
+ | (((uint32_t) target_assigned_package_id_) << 24U);
return NO_ERROR;
}
@@ -106,62 +105,58 @@ status_t OverlayDynamicRefTable::lookupResourceIdNoRewrite(uint32_t* resId) cons
IdmapResMap::IdmapResMap(const Idmap_data_header* data_header,
const Idmap_target_entry* entries,
+ const Idmap_target_entry_inline* inline_entries,
uint8_t target_assigned_package_id,
const OverlayDynamicRefTable* overlay_ref_table)
: data_header_(data_header),
entries_(entries),
+ inline_entries_(inline_entries),
target_assigned_package_id_(target_assigned_package_id),
- overlay_ref_table_(overlay_ref_table) { };
+ overlay_ref_table_(overlay_ref_table) { }
IdmapResMap::Result IdmapResMap::Lookup(uint32_t target_res_id) const {
- if ((target_res_id >> 24) != target_assigned_package_id_) {
+ if ((target_res_id >> 24U) != target_assigned_package_id_) {
// The resource id must have the same package id as the target package.
return {};
}
// The resource ids encoded within the idmap are build-time resource ids.
target_res_id = (0x00FFFFFFU & target_res_id)
- | (((uint32_t) data_header_->target_package_id) << 24);
-
- const Idmap_target_entry* first_entry = entries_;
- const Idmap_target_entry* end_entry = entries_ + dtohl(data_header_->target_entry_count);
- auto entry = std::lower_bound(first_entry, end_entry, target_res_id, compare_target_entries);
-
- if (entry == end_entry || dtohl(entry->target_id) != target_res_id) {
- // A mapping for the target resource id could not be found.
- return {};
- }
-
- // A reference should be treated as an alias of the resource. Instead of returning the table
- // entry, return the alias resource id to look up. The alias resource might not reside within the
- // overlay package, so the resource id must be fixed with the dynamic reference table of the
- // overlay before returning.
- if (entry->type == Res_value::TYPE_REFERENCE
- || entry->type == Res_value::TYPE_DYNAMIC_REFERENCE) {
- uint32_t overlay_resource_id = dtohl(entry->value);
-
+ | (((uint32_t) data_header_->target_package_id) << 24U);
+
+ // Check if the target resource is mapped to an overlay resource.
+ auto first_entry = entries_;
+ auto end_entry = entries_ + dtohl(data_header_->target_entry_count);
+ auto entry = std::lower_bound(first_entry, end_entry, target_res_id,
+ [](const Idmap_target_entry &e, const uint32_t target_id) {
+ return dtohl(e.target_id) < target_id;
+ });
+
+ if (entry != end_entry && dtohl(entry->target_id) == target_res_id) {
+ uint32_t overlay_resource_id = dtohl(entry->overlay_id);
// Lookup the resource without rewriting the overlay resource id back to the target resource id
// being looked up.
overlay_ref_table_->lookupResourceIdNoRewrite(&overlay_resource_id);
return Result(overlay_resource_id);
}
- // Copy the type and value into the ResTable_entry structure needed by asset manager.
- uint16_t malloc_size = sizeof(ResTable_entry) + sizeof(Res_value);
- auto table_entry = reinterpret_cast<ResTable_entry*>(malloc(malloc_size));
- memset(table_entry, 0, malloc_size);
- table_entry->size = htods(sizeof(ResTable_entry));
-
- auto table_value = reinterpret_cast<Res_value*>(reinterpret_cast<uint8_t*>(table_entry)
- + sizeof(ResTable_entry));
- table_value->dataType = entry->type;
- table_value->data = entry->value;
-
- return Result(ResTable_entry_handle::managed(table_entry, [](auto p) { free(p); }));
+ // Check if the target resources is mapped to an inline table entry.
+ auto first_inline_entry = inline_entries_;
+ auto end_inline_entry = inline_entries_ + dtohl(data_header_->target_inline_entry_count);
+ auto inline_entry = std::lower_bound(first_inline_entry, end_inline_entry, target_res_id,
+ [](const Idmap_target_entry_inline &e,
+ const uint32_t target_id) {
+ return dtohl(e.target_id) < target_id;
+ });
+
+ if (inline_entry != end_inline_entry && dtohl(inline_entry->target_id) == target_res_id) {
+ return Result(inline_entry->value);
+ }
+ return {};
}
static bool is_word_aligned(const void* data) {
- return (reinterpret_cast<uintptr_t>(data) & 0x03) == 0;
+ return (reinterpret_cast<uintptr_t>(data) & 0x03U) == 0U;
}
static bool IsValidIdmapHeader(const StringPiece& data) {
@@ -175,7 +170,7 @@ static bool IsValidIdmapHeader(const StringPiece& data) {
return false;
}
- const Idmap_header* header = reinterpret_cast<const Idmap_header*>(data.data());
+ auto header = reinterpret_cast<const Idmap_header*>(data.data());
if (dtohl(header->magic) != kIdmapMagic) {
LOG(ERROR) << StringPrintf("Invalid Idmap file: bad magic value (was 0x%08x, expected 0x%08x)",
dtohl(header->magic), kIdmapMagic);
@@ -198,11 +193,13 @@ LoadedIdmap::LoadedIdmap(std::string&& idmap_path,
const Idmap_header* header,
const Idmap_data_header* data_header,
const Idmap_target_entry* target_entries,
+ const Idmap_target_entry_inline* target_inline_entries,
const Idmap_overlay_entry* overlay_entries,
ResStringPool* string_pool)
: header_(header),
data_header_(data_header),
target_entries_(target_entries),
+ target_inline_entries_(target_inline_entries),
overlay_entries_(overlay_entries),
string_pool_(string_pool),
idmap_path_(std::move(idmap_path)),
@@ -233,7 +230,7 @@ std::unique_ptr<const LoadedIdmap> LoadedIdmap::Load(const StringPiece& idmap_pa
data_ptr += sizeof(*data_header);
data_size -= sizeof(*data_header);
- // Make sure there is enough space for the target entries declared in the header.
+ // Make sure there is enough space for the target entries declared in the header
const auto target_entries = reinterpret_cast<const Idmap_target_entry*>(data_ptr);
if (data_size / sizeof(Idmap_target_entry) <
static_cast<size_t>(dtohl(data_header->target_entry_count))) {
@@ -248,6 +245,21 @@ std::unique_ptr<const LoadedIdmap> LoadedIdmap::Load(const StringPiece& idmap_pa
data_ptr += target_entry_size_bytes;
data_size -= target_entry_size_bytes;
+ // Make sure there is enough space for the target entries declared in the header.
+ const auto target_inline_entries = reinterpret_cast<const Idmap_target_entry_inline*>(data_ptr);
+ if (data_size / sizeof(Idmap_target_entry_inline) <
+ static_cast<size_t>(dtohl(data_header->target_inline_entry_count))) {
+ LOG(ERROR) << StringPrintf("Idmap too small for the number of target inline entries (%d)",
+ (int)dtohl(data_header->target_inline_entry_count));
+ return {};
+ }
+
+ // Advance the data pointer past the target entries.
+ const size_t target_inline_entry_size_bytes =
+ (dtohl(data_header->target_inline_entry_count) * sizeof(Idmap_target_entry_inline));
+ data_ptr += target_inline_entry_size_bytes;
+ data_size -= target_inline_entry_size_bytes;
+
// Make sure there is enough space for the overlay entries declared in the header.
const auto overlay_entries = reinterpret_cast<const Idmap_overlay_entry*>(data_ptr);
if (data_size / sizeof(Idmap_overlay_entry) <
@@ -257,22 +269,26 @@ std::unique_ptr<const LoadedIdmap> LoadedIdmap::Load(const StringPiece& idmap_pa
return {};
}
- // Advance the data pointer past the target entries.
+ // Advance the data pointer past the overlay entries.
const size_t overlay_entry_size_bytes =
(dtohl(data_header->overlay_entry_count) * sizeof(Idmap_overlay_entry));
data_ptr += overlay_entry_size_bytes;
data_size -= overlay_entry_size_bytes;
// Read the idmap string pool that holds the value of inline string entries.
- if (data_size < dtohl(data_header->string_pool_length)) {
+ uint32_t string_pool_size = dtohl(*reinterpret_cast<const uint32_t*>(data_ptr));
+ data_ptr += sizeof(uint32_t);
+ data_size -= sizeof(uint32_t);
+
+ if (data_size < string_pool_size) {
LOG(ERROR) << StringPrintf("Idmap too small for string pool (length %d)",
- (int)dtohl(data_header->string_pool_length));
+ (int)string_pool_size);
return {};
}
auto idmap_string_pool = util::make_unique<ResStringPool>();
- if (dtohl(data_header->string_pool_length) > 0) {
- status_t err = idmap_string_pool->setTo(data_ptr, dtohl(data_header->string_pool_length));
+ if (string_pool_size > 0) {
+ status_t err = idmap_string_pool->setTo(data_ptr, string_pool_size);
if (err != NO_ERROR) {
LOG(ERROR) << "idmap string pool corrupt.";
return {};
@@ -280,9 +296,10 @@ std::unique_ptr<const LoadedIdmap> LoadedIdmap::Load(const StringPiece& idmap_pa
}
// Can't use make_unique because LoadedIdmap constructor is private.
- std::unique_ptr<LoadedIdmap> loaded_idmap = std::unique_ptr<LoadedIdmap>(
+ auto loaded_idmap = std::unique_ptr<LoadedIdmap>(
new LoadedIdmap(idmap_path.to_string(), getFileModDate(idmap_path.data()), header,
- data_header, target_entries, overlay_entries, idmap_string_pool.release()));
+ data_header, target_entries, target_inline_entries, overlay_entries,
+ idmap_string_pool.release()));
return std::move(loaded_idmap);
}
diff --git a/libs/androidfw/fuzz/cursorwindow_fuzzer/Android.bp b/libs/androidfw/fuzz/cursorwindow_fuzzer/Android.bp
new file mode 100644
index 000000000000..2dac47b0dac6
--- /dev/null
+++ b/libs/androidfw/fuzz/cursorwindow_fuzzer/Android.bp
@@ -0,0 +1,31 @@
+cc_fuzz {
+ name: "cursorwindow_fuzzer",
+ srcs: [
+ "cursorwindow_fuzzer.cpp",
+ ],
+ host_supported: true,
+ corpus: ["corpus/*"],
+ static_libs: ["libgmock"],
+ target: {
+ android: {
+ shared_libs: [
+ "libandroidfw_fuzzer_lib",
+ "libbase",
+ "libbinder",
+ "libcutils",
+ "liblog",
+ "libutils",
+ ],
+ },
+ host: {
+ static_libs: [
+ "libandroidfw_fuzzer_lib",
+ "libbase",
+ "libbinder",
+ "libcutils",
+ "liblog",
+ "libutils",
+ ],
+ },
+ },
+}
diff --git a/libs/androidfw/fuzz/cursorwindow_fuzzer/corpus/typical.bin b/libs/androidfw/fuzz/cursorwindow_fuzzer/corpus/typical.bin
new file mode 100644
index 000000000000..c7e22dd26ea7
--- /dev/null
+++ b/libs/androidfw/fuzz/cursorwindow_fuzzer/corpus/typical.bin
Binary files differ
diff --git a/libs/androidfw/fuzz/cursorwindow_fuzzer/cursorwindow_fuzzer.cpp b/libs/androidfw/fuzz/cursorwindow_fuzzer/cursorwindow_fuzzer.cpp
new file mode 100644
index 000000000000..8dce21220199
--- /dev/null
+++ b/libs/androidfw/fuzz/cursorwindow_fuzzer/cursorwindow_fuzzer.cpp
@@ -0,0 +1,78 @@
+/*
+ * 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.
+ */
+
+#include <stddef.h>
+#include <stdint.h>
+#include <string.h>
+#include <string>
+#include <memory>
+
+#include "android-base/logging.h"
+#include "androidfw/CursorWindow.h"
+#include "binder/Parcel.h"
+
+#include <fuzzer/FuzzedDataProvider.h>
+
+using android::CursorWindow;
+using android::Parcel;
+
+extern "C" int LLVMFuzzerInitialize(int *, char ***) {
+ setenv("ANDROID_LOG_TAGS", "*:s", 1);
+ android::base::InitLogging(nullptr, &android::base::StderrLogger);
+ return 0;
+}
+
+extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
+ Parcel p;
+ p.setData(data, size);
+
+ CursorWindow* w = nullptr;
+ if (!CursorWindow::createFromParcel(&p, &w)) {
+ LOG(WARNING) << "Valid cursor with " << w->getNumRows() << " rows, "
+ << w->getNumColumns() << " cols";
+
+ // Try obtaining heap allocations for most items; we trim the
+ // search space to speed things up
+ auto rows = std::min(w->getNumRows(), static_cast<uint32_t>(128));
+ auto cols = std::min(w->getNumColumns(), static_cast<uint32_t>(128));
+ for (auto row = 0; row < rows; row++) {
+ for (auto col = 0; col < cols; col++) {
+ auto field = w->getFieldSlot(row, col);
+ if (!field) continue;
+ switch (w->getFieldSlotType(field)) {
+ case CursorWindow::FIELD_TYPE_STRING: {
+ size_t size;
+ w->getFieldSlotValueString(field, &size);
+ break;
+ }
+ case CursorWindow::FIELD_TYPE_BLOB: {
+ size_t size;
+ w->getFieldSlotValueBlob(field, &size);
+ break;
+ }
+ }
+ }
+ }
+
+ // Finally, try obtaining the furthest valid field
+ if (rows > 0 && cols > 0) {
+ w->getFieldSlot(w->getNumRows() - 1, w->getNumColumns() - 1);
+ }
+ }
+ delete w;
+
+ return 0;
+}
diff --git a/libs/androidfw/include/androidfw/CursorWindow.h b/libs/androidfw/include/androidfw/CursorWindow.h
index 0bee60929cc9..6e55a9a0eb8b 100644
--- a/libs/androidfw/include/androidfw/CursorWindow.h
+++ b/libs/androidfw/include/androidfw/CursorWindow.h
@@ -20,38 +20,36 @@
#include <inttypes.h>
#include <stddef.h>
#include <stdint.h>
+#include <string>
-#include <binder/Parcel.h>
-#include <log/log.h>
-#include <utils/String8.h>
+#include "android-base/stringprintf.h"
+#include "binder/Parcel.h"
+#include "utils/String8.h"
-#if LOG_NDEBUG
-
-#define IF_LOG_WINDOW() if (false)
#define LOG_WINDOW(...)
-#else
-
-#define IF_LOG_WINDOW() IF_ALOG(LOG_DEBUG, "CursorWindow")
-#define LOG_WINDOW(...) ALOG(LOG_DEBUG, "CursorWindow", __VA_ARGS__)
-
-#endif
-
namespace android {
/**
- * This class stores a set of rows from a database in a buffer. The begining of the
- * window has first chunk of RowSlots, which are offsets to the row directory, followed by
- * an offset to the next chunk in a linked-list of additional chunk of RowSlots in case
- * the pre-allocated chunk isn't big enough to refer to all rows. Each row directory has a
- * FieldSlot per column, which has the size, offset, and type of the data for that field.
- * Note that the data types come from sqlite3.h.
+ * This class stores a set of rows from a database in a buffer. Internally
+ * data is structured as a "heap" of string/blob allocations at the bottom
+ * of the memory region, and a "stack" of FieldSlot allocations at the top
+ * of the memory region. Here's an example visual representation:
+ *
+ * +----------------------------------------------------------------+
+ * |heap\0of\0strings\0 222211110000| ...
+ * +-------------------+--------------------------------+-------+---+
+ * ^ ^ ^ ^ ^ ^
+ * | | | | | |
+ * | +- mAllocOffset mSlotsOffset -+ | | |
+ * +- mData mSlotsStart -+ | |
+ * mSize -+ |
+ * mInflatedSize -+
*
* Strings are stored in UTF-8.
*/
class CursorWindow {
- CursorWindow(const String8& name, int ashmemFd, void* data, size_t size,
- size_t inflatedSize, bool readOnly);
+ CursorWindow();
public:
/* Field types. */
@@ -88,9 +86,9 @@ public:
inline String8 name() { return mName; }
inline size_t size() { return mSize; }
- inline size_t freeSpace() { return mSize - mHeader->freeOffset; }
- inline uint32_t getNumRows() { return mHeader->numRows; }
- inline uint32_t getNumColumns() { return mHeader->numColumns; }
+ inline size_t freeSpace() { return mSlotsOffset - mAllocOffset; }
+ inline uint32_t getNumRows() { return mNumRows; }
+ inline uint32_t getNumColumns() { return mNumColumns; }
status_t clear();
status_t setNumColumns(uint32_t numColumns);
@@ -138,75 +136,57 @@ public:
return offsetToPtr(fieldSlot->data.buffer.offset, fieldSlot->data.buffer.size);
}
-private:
- static const size_t ROW_SLOT_CHUNK_NUM_ROWS = 100;
-
- struct Header {
- // Offset of the lowest unused byte in the window.
- uint32_t freeOffset;
-
- // Offset of the first row slot chunk.
- uint32_t firstChunkOffset;
-
- uint32_t numRows;
- uint32_t numColumns;
- };
-
- struct RowSlot {
- uint32_t offset;
- };
-
- struct RowSlotChunk {
- RowSlot slots[ROW_SLOT_CHUNK_NUM_ROWS];
- uint32_t nextChunkOffset;
- };
-
- String8 mName;
- int mAshmemFd;
- void* mData;
- size_t mSize;
- size_t mInflatedSize;
- bool mReadOnly;
- Header* mHeader;
-
- inline void* offsetToPtr(uint32_t offset, uint32_t bufferSize = 0) {
- if (offset > mSize) {
- ALOGE("Offset %" PRIu32 " out of bounds, max value %zu", offset, mSize);
- return NULL;
- }
- if (offset + bufferSize > mSize) {
- ALOGE("End offset %" PRIu32 " out of bounds, max value %zu",
- offset + bufferSize, mSize);
- return NULL;
- }
- return static_cast<uint8_t*>(mData) + offset;
+ inline std::string toString() const {
+ return android::base::StringPrintf("CursorWindow{name=%s, fd=%d, size=%d, inflatedSize=%d, "
+ "allocOffset=%d, slotsOffset=%d, numRows=%d, numColumns=%d}", mName.c_str(),
+ mAshmemFd, mSize, mInflatedSize, mAllocOffset, mSlotsOffset, mNumRows, mNumColumns);
}
- inline uint32_t offsetFromPtr(void* ptr) {
- return static_cast<uint8_t*>(ptr) - static_cast<uint8_t*>(mData);
- }
+private:
+ String8 mName;
+ int mAshmemFd = -1;
+ void* mData = nullptr;
+ /**
+ * Pointer to the first FieldSlot, used to optimize the extremely
+ * hot code path of getFieldSlot().
+ */
+ void* mSlotsStart = nullptr;
+ void* mSlotsEnd = nullptr;
+ uint32_t mSize = 0;
+ /**
+ * When a window starts as lightweight inline allocation, this value
+ * holds the "full" size to be created after ashmem inflation.
+ */
+ uint32_t mInflatedSize = 0;
+ /**
+ * Offset to the top of the "heap" of string/blob allocations. By
+ * storing these allocations at the bottom of our memory region we
+ * avoid having to rewrite offsets when inflating.
+ */
+ uint32_t mAllocOffset = 0;
+ /**
+ * Offset to the bottom of the "stack" of FieldSlot allocations.
+ */
+ uint32_t mSlotsOffset = 0;
+ uint32_t mNumRows = 0;
+ uint32_t mNumColumns = 0;
+ bool mReadOnly = false;
- static status_t createFromParcelAshmem(Parcel*, String8&, CursorWindow**);
- static status_t createFromParcelInline(Parcel*, String8&, CursorWindow**);
+ void updateSlotsData();
- status_t writeToParcelAshmem(Parcel*);
- status_t writeToParcelInline(Parcel*);
+ void* offsetToPtr(uint32_t offset, uint32_t bufferSize);
+ uint32_t offsetFromPtr(void* ptr);
/**
* By default windows are lightweight inline allocations; this method
* inflates the window into a larger ashmem region.
*/
- status_t inflate();
+ status_t maybeInflate();
/**
- * Allocate a portion of the window. Returns the offset
- * of the allocation, or 0 if there isn't enough space.
- * If aligned is true, the allocation gets 4 byte alignment.
+ * Allocate a portion of the window.
*/
- uint32_t alloc(size_t size, bool aligned = false);
-
- RowSlot* getRowSlot(uint32_t row);
- RowSlot* allocRowSlot();
+ status_t alloc(size_t size, uint32_t* outOffset);
status_t putBlobOrString(uint32_t row, uint32_t column,
const void* value, size_t size, int32_t type);
diff --git a/libs/androidfw/include/androidfw/Idmap.h b/libs/androidfw/include/androidfw/Idmap.h
index ecc1ce65d124..ab0f47f025d2 100644
--- a/libs/androidfw/include/androidfw/Idmap.h
+++ b/libs/androidfw/include/androidfw/Idmap.h
@@ -77,40 +77,40 @@ class OverlayDynamicRefTable : public DynamicRefTable {
// A mapping of target resource ids to a values or resource ids that should overlay the target.
class IdmapResMap {
public:
- // Represents the result of a idmap lookup. The result can be one of three possibillities:
+ // Represents the result of a idmap lookup. The result can be one of three possibilities:
// 1) The result is a resource id which represents the overlay resource that should act as an
// alias of the target resource.
// 2) The result is a table entry which overlays the type and value of the target resource.
// 3) The result is neither and the target resource is not overlaid.
class Result {
public:
- Result() : data_(nullptr) {};
+ Result() = default;
explicit Result(uint32_t value) : data_(value) {};
- explicit Result(ResTable_entry_handle&& value) : data_(value) { };
+ explicit Result(const Res_value& value) : data_(value) { };
// Returns `true` if the resource is overlaid.
- inline explicit operator bool() const {
- return !std::get_if<nullptr_t>(&data_);
+ explicit operator bool() const {
+ return std::get_if<std::monostate>(&data_) == nullptr;
}
- inline bool IsResourceId() const {
- return std::get_if<uint32_t>(&data_);
+ bool IsResourceId() const {
+ return std::get_if<uint32_t>(&data_) != nullptr;
}
- inline uint32_t GetResourceId() const {
- return *std::get_if<uint32_t>(&data_);
+ uint32_t GetResourceId() const {
+ return std::get<uint32_t>(data_);
}
- inline bool IsTableEntry() const {
- return std::get_if<ResTable_entry_handle>(&data_);
+ bool IsInlineValue() const {
+ return std::get_if<Res_value>(&data_) != nullptr;
}
- inline const ResTable_entry_handle& GetTableEntry() const {
- return *std::get_if<ResTable_entry_handle>(&data_);
+ const Res_value& GetInlineValue() const {
+ return std::get<Res_value>(data_);
}
private:
- std::variant<uint32_t, nullptr_t, ResTable_entry_handle> data_;
+ std::variant<std::monostate, uint32_t, Res_value> data_;
};
// Looks up the value that overlays the target resource id.
@@ -123,11 +123,13 @@ class IdmapResMap {
private:
explicit IdmapResMap(const Idmap_data_header* data_header,
const Idmap_target_entry* entries,
+ const Idmap_target_entry_inline* inline_entries,
uint8_t target_assigned_package_id,
const OverlayDynamicRefTable* overlay_ref_table);
const Idmap_data_header* data_header_;
const Idmap_target_entry* entries_;
+ const Idmap_target_entry_inline* inline_entries_;
const uint8_t target_assigned_package_id_;
const OverlayDynamicRefTable* overlay_ref_table_;
@@ -163,8 +165,8 @@ class LoadedIdmap {
// Returns a mapping from target resource ids to overlay values.
inline const IdmapResMap GetTargetResourcesMap(
uint8_t target_assigned_package_id, const OverlayDynamicRefTable* overlay_ref_table) const {
- return IdmapResMap(data_header_, target_entries_, target_assigned_package_id,
- overlay_ref_table);
+ return IdmapResMap(data_header_, target_entries_, target_inline_entries_,
+ target_assigned_package_id, overlay_ref_table);
}
// Returns a dynamic reference table for a loaded overlay package.
@@ -184,6 +186,7 @@ class LoadedIdmap {
const Idmap_header* header_;
const Idmap_data_header* data_header_;
const Idmap_target_entry* target_entries_;
+ const Idmap_target_entry_inline* target_inline_entries_;
const Idmap_overlay_entry* overlay_entries_;
const std::unique_ptr<ResStringPool> string_pool_;
@@ -200,6 +203,7 @@ class LoadedIdmap {
const Idmap_header* header,
const Idmap_data_header* data_header,
const Idmap_target_entry* target_entries,
+ const Idmap_target_entry_inline* target_inline_entries,
const Idmap_overlay_entry* overlay_entries,
ResStringPool* string_pool);
diff --git a/libs/androidfw/include/androidfw/ResourceTypes.h b/libs/androidfw/include/androidfw/ResourceTypes.h
index e10a7f3f5c61..04ba78b6705d 100644
--- a/libs/androidfw/include/androidfw/ResourceTypes.h
+++ b/libs/androidfw/include/androidfw/ResourceTypes.h
@@ -41,7 +41,7 @@
namespace android {
constexpr const static uint32_t kIdmapMagic = 0x504D4449u;
-constexpr const static uint32_t kIdmapCurrentVersion = 0x00000004u;
+constexpr const static uint32_t kIdmapCurrentVersion = 0x00000005u;
/**
* In C++11, char16_t is defined as *at least* 16 bits. We do a lot of
@@ -1476,7 +1476,7 @@ struct ResTable_entry
// If set, this is a weak resource and may be overriden by strong
// resources of the same name/type. This is only useful during
// linking with other resource tables.
- FLAG_WEAK = 0x0004
+ FLAG_WEAK = 0x0004,
};
uint16_t flags;
@@ -1586,50 +1586,6 @@ struct ResTable_map
Res_value value;
};
-
-// A ResTable_entry variant that either holds an unmanaged pointer to a constant ResTable_entry or
-// holds a ResTable_entry which is tied to the lifetime of the handle.
-class ResTable_entry_handle {
- public:
- ResTable_entry_handle() = default;
-
- ResTable_entry_handle(const ResTable_entry_handle& handle) {
- entry_ = handle.entry_;
- }
-
- ResTable_entry_handle(ResTable_entry_handle&& handle) noexcept {
- entry_ = handle.entry_;
- }
-
- inline static ResTable_entry_handle managed(ResTable_entry* entry, void (*deleter)(void *)) {
- return ResTable_entry_handle(std::shared_ptr<const ResTable_entry>(entry, deleter));
- }
-
- inline static ResTable_entry_handle unmanaged(const ResTable_entry* entry) {
- return ResTable_entry_handle(std::shared_ptr<const ResTable_entry>(entry, [](auto /*p */){}));
- }
-
- inline ResTable_entry_handle& operator=(const ResTable_entry_handle& handle) noexcept {
- entry_ = handle.entry_;
- return *this;
- }
-
- inline ResTable_entry_handle& operator=(ResTable_entry_handle&& handle) noexcept {
- entry_ = handle.entry_;
- return *this;
- }
-
- inline const ResTable_entry* operator*() & {
- return entry_.get();
- }
-
- private:
- explicit ResTable_entry_handle(std::shared_ptr<const ResTable_entry> entry)
- : entry_(std::move(entry)) { }
-
- std::shared_ptr<const ResTable_entry> entry_;
-};
-
/**
* A package-id to package name mapping for any shared libraries used
* in this resource table. The package-id's encoded in this resource
@@ -1740,7 +1696,6 @@ inline ResTable_overlayable_policy_header::PolicyFlags& operator |=(
return first;
}
-#pragma pack(push, 1)
struct Idmap_header {
// Always 0x504D4449 ('IDMP')
uint32_t magic;
@@ -1751,7 +1706,7 @@ struct Idmap_header {
uint32_t overlay_crc32;
uint32_t fulfilled_policies;
- uint8_t enforce_overlayable;
+ uint32_t enforce_overlayable;
uint8_t target_path[256];
uint8_t overlay_path[256];
@@ -1765,23 +1720,31 @@ struct Idmap_header {
struct Idmap_data_header {
uint8_t target_package_id;
uint8_t overlay_package_id;
+
+ // Padding to ensure 4 byte alignment for target_entry_count
+ uint16_t p0;
+
uint32_t target_entry_count;
+ uint32_t target_inline_entry_count;
uint32_t overlay_entry_count;
+
uint32_t string_pool_index_offset;
- uint32_t string_pool_length;
};
struct Idmap_target_entry {
uint32_t target_id;
- uint8_t type;
- uint32_t value;
+ uint32_t overlay_id;
+};
+
+struct Idmap_target_entry_inline {
+ uint32_t target_id;
+ Res_value value;
};
struct Idmap_overlay_entry {
uint32_t overlay_id;
uint32_t target_id;
};
-#pragma pack(pop)
class AssetManager2;
diff --git a/libs/androidfw/tests/CursorWindow_bench.cpp b/libs/androidfw/tests/CursorWindow_bench.cpp
new file mode 100644
index 000000000000..f1191c3d7213
--- /dev/null
+++ b/libs/androidfw/tests/CursorWindow_bench.cpp
@@ -0,0 +1,86 @@
+/*
+ * 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.
+ */
+
+#include "benchmark/benchmark.h"
+
+#include "androidfw/CursorWindow.h"
+
+namespace android {
+
+static void BM_CursorWindowWrite(benchmark::State& state, size_t rows, size_t cols) {
+ CursorWindow* w;
+ CursorWindow::create(String8("test"), 1 << 21, &w);
+
+ while (state.KeepRunning()) {
+ w->clear();
+ w->setNumColumns(cols);
+ for (int row = 0; row < rows; row++) {
+ w->allocRow();
+ for (int col = 0; col < cols; col++) {
+ w->putLong(row, col, 0xcafe);
+ }
+ }
+ }
+}
+
+static void BM_CursorWindowWrite4x4(benchmark::State& state) {
+ BM_CursorWindowWrite(state, 4, 4);
+}
+BENCHMARK(BM_CursorWindowWrite4x4);
+
+static void BM_CursorWindowWrite1Kx4(benchmark::State& state) {
+ BM_CursorWindowWrite(state, 1024, 4);
+}
+BENCHMARK(BM_CursorWindowWrite1Kx4);
+
+static void BM_CursorWindowWrite16Kx4(benchmark::State& state) {
+ BM_CursorWindowWrite(state, 16384, 4);
+}
+BENCHMARK(BM_CursorWindowWrite16Kx4);
+
+static void BM_CursorWindowRead(benchmark::State& state, size_t rows, size_t cols) {
+ CursorWindow* w;
+ CursorWindow::create(String8("test"), 1 << 21, &w);
+ w->setNumColumns(cols);
+ for (int row = 0; row < rows; row++) {
+ w->allocRow();
+ }
+
+ while (state.KeepRunning()) {
+ for (int row = 0; row < rows; row++) {
+ for (int col = 0; col < cols; col++) {
+ w->getFieldSlot(row, col);
+ }
+ }
+ }
+}
+
+static void BM_CursorWindowRead4x4(benchmark::State& state) {
+ BM_CursorWindowRead(state, 4, 4);
+}
+BENCHMARK(BM_CursorWindowRead4x4);
+
+static void BM_CursorWindowRead1Kx4(benchmark::State& state) {
+ BM_CursorWindowRead(state, 1024, 4);
+}
+BENCHMARK(BM_CursorWindowRead1Kx4);
+
+static void BM_CursorWindowRead16Kx4(benchmark::State& state) {
+ BM_CursorWindowRead(state, 16384, 4);
+}
+BENCHMARK(BM_CursorWindowRead16Kx4);
+
+} // namespace android
diff --git a/libs/androidfw/tests/CursorWindow_test.cpp b/libs/androidfw/tests/CursorWindow_test.cpp
new file mode 100644
index 000000000000..15be80c48192
--- /dev/null
+++ b/libs/androidfw/tests/CursorWindow_test.cpp
@@ -0,0 +1,367 @@
+/*
+ * 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.
+ */
+
+#include <utility>
+
+#include "androidfw/CursorWindow.h"
+
+#include "TestHelpers.h"
+
+#define CREATE_WINDOW_1K \
+ CursorWindow* w; \
+ CursorWindow::create(String8("test"), 1 << 10, &w);
+
+#define CREATE_WINDOW_1K_3X3 \
+ CursorWindow* w; \
+ CursorWindow::create(String8("test"), 1 << 10, &w); \
+ ASSERT_EQ(w->setNumColumns(3), OK); \
+ ASSERT_EQ(w->allocRow(), OK); \
+ ASSERT_EQ(w->allocRow(), OK); \
+ ASSERT_EQ(w->allocRow(), OK);
+
+#define CREATE_WINDOW_2M \
+ CursorWindow* w; \
+ CursorWindow::create(String8("test"), 1 << 21, &w);
+
+static constexpr const size_t kHalfInlineSize = 8192;
+static constexpr const size_t kGiantSize = 1048576;
+
+namespace android {
+
+TEST(CursorWindowTest, Empty) {
+ CREATE_WINDOW_1K;
+
+ ASSERT_EQ(w->getNumRows(), 0);
+ ASSERT_EQ(w->getNumColumns(), 0);
+ ASSERT_EQ(w->size(), 1 << 10);
+ ASSERT_EQ(w->freeSpace(), 1 << 10);
+}
+
+TEST(CursorWindowTest, SetNumColumns) {
+ CREATE_WINDOW_1K;
+
+ // Once we've locked in columns, we can't adjust
+ ASSERT_EQ(w->getNumColumns(), 0);
+ ASSERT_EQ(w->setNumColumns(4), OK);
+ ASSERT_NE(w->setNumColumns(5), OK);
+ ASSERT_NE(w->setNumColumns(3), OK);
+ ASSERT_EQ(w->getNumColumns(), 4);
+}
+
+TEST(CursorWindowTest, SetNumColumnsAfterRow) {
+ CREATE_WINDOW_1K;
+
+ // Once we've locked in a row, we can't adjust columns
+ ASSERT_EQ(w->getNumColumns(), 0);
+ ASSERT_EQ(w->allocRow(), OK);
+ ASSERT_NE(w->setNumColumns(4), OK);
+ ASSERT_EQ(w->getNumColumns(), 0);
+}
+
+TEST(CursorWindowTest, AllocRow) {
+ CREATE_WINDOW_1K;
+
+ ASSERT_EQ(w->setNumColumns(4), OK);
+
+ // Rolling forward means we have less free space
+ ASSERT_EQ(w->getNumRows(), 0);
+ auto before = w->freeSpace();
+ ASSERT_EQ(w->allocRow(), OK);
+ ASSERT_LT(w->freeSpace(), before);
+ ASSERT_EQ(w->getNumRows(), 1);
+
+ // Verify we can unwind
+ ASSERT_EQ(w->freeLastRow(), OK);
+ ASSERT_EQ(w->freeSpace(), before);
+ ASSERT_EQ(w->getNumRows(), 0);
+
+ // Can't unwind when no rows left
+ ASSERT_NE(w->freeLastRow(), OK);
+}
+
+TEST(CursorWindowTest, AllocRowBounds) {
+ CREATE_WINDOW_1K;
+
+ // 60 columns is 960 bytes, which means only a single row can fit
+ ASSERT_EQ(w->setNumColumns(60), OK);
+ ASSERT_EQ(w->allocRow(), OK);
+ ASSERT_NE(w->allocRow(), OK);
+}
+
+TEST(CursorWindowTest, StoreNull) {
+ CREATE_WINDOW_1K_3X3;
+
+ ASSERT_EQ(w->putNull(1, 1), OK);
+ ASSERT_EQ(w->putNull(0, 0), OK);
+
+ {
+ auto field = w->getFieldSlot(1, 1);
+ ASSERT_EQ(w->getFieldSlotType(field), CursorWindow::FIELD_TYPE_NULL);
+ }
+ {
+ auto field = w->getFieldSlot(0, 0);
+ ASSERT_EQ(w->getFieldSlotType(field), CursorWindow::FIELD_TYPE_NULL);
+ }
+}
+
+TEST(CursorWindowTest, StoreLong) {
+ CREATE_WINDOW_1K_3X3;
+
+ ASSERT_EQ(w->putLong(1, 1, 0xf00d), OK);
+ ASSERT_EQ(w->putLong(0, 0, 0xcafe), OK);
+
+ {
+ auto field = w->getFieldSlot(1, 1);
+ ASSERT_EQ(w->getFieldSlotType(field), CursorWindow::FIELD_TYPE_INTEGER);
+ ASSERT_EQ(w->getFieldSlotValueLong(field), 0xf00d);
+ }
+ {
+ auto field = w->getFieldSlot(0, 0);
+ ASSERT_EQ(w->getFieldSlotType(field), CursorWindow::FIELD_TYPE_INTEGER);
+ ASSERT_EQ(w->getFieldSlotValueLong(field), 0xcafe);
+ }
+}
+
+TEST(CursorWindowTest, StoreString) {
+ CREATE_WINDOW_1K_3X3;
+
+ ASSERT_EQ(w->putString(1, 1, "food", 5), OK);
+ ASSERT_EQ(w->putString(0, 0, "cafe", 5), OK);
+
+ size_t size;
+ {
+ auto field = w->getFieldSlot(1, 1);
+ ASSERT_EQ(w->getFieldSlotType(field), CursorWindow::FIELD_TYPE_STRING);
+ auto actual = w->getFieldSlotValueString(field, &size);
+ ASSERT_EQ(std::string(actual), "food");
+ }
+ {
+ auto field = w->getFieldSlot(0, 0);
+ ASSERT_EQ(w->getFieldSlotType(field), CursorWindow::FIELD_TYPE_STRING);
+ auto actual = w->getFieldSlotValueString(field, &size);
+ ASSERT_EQ(std::string(actual), "cafe");
+ }
+}
+
+TEST(CursorWindowTest, StoreBounds) {
+ CREATE_WINDOW_1K_3X3;
+
+ // Can't work with values beyond bounds
+ ASSERT_NE(w->putLong(0, 3, 0xcafe), OK);
+ ASSERT_NE(w->putLong(3, 0, 0xcafe), OK);
+ ASSERT_NE(w->putLong(3, 3, 0xcafe), OK);
+ ASSERT_EQ(w->getFieldSlot(0, 3), nullptr);
+ ASSERT_EQ(w->getFieldSlot(3, 0), nullptr);
+ ASSERT_EQ(w->getFieldSlot(3, 3), nullptr);
+
+ // Can't work with invalid indexes
+ ASSERT_NE(w->putLong(-1, 0, 0xcafe), OK);
+ ASSERT_NE(w->putLong(0, -1, 0xcafe), OK);
+ ASSERT_NE(w->putLong(-1, -1, 0xcafe), OK);
+ ASSERT_EQ(w->getFieldSlot(-1, 0), nullptr);
+ ASSERT_EQ(w->getFieldSlot(0, -1), nullptr);
+ ASSERT_EQ(w->getFieldSlot(-1, -1), nullptr);
+}
+
+TEST(CursorWindowTest, Inflate) {
+ CREATE_WINDOW_2M;
+
+ auto before = w->size();
+ ASSERT_EQ(w->setNumColumns(4), OK);
+ ASSERT_EQ(w->allocRow(), OK);
+
+ // Scratch buffer that will fit before inflation
+ void* buf = malloc(kHalfInlineSize);
+
+ // Store simple value
+ ASSERT_EQ(w->putLong(0, 0, 0xcafe), OK);
+
+ // Store first object that fits inside
+ memset(buf, 42, kHalfInlineSize);
+ ASSERT_EQ(w->putBlob(0, 1, buf, kHalfInlineSize), OK);
+ ASSERT_EQ(w->size(), before);
+
+ // Store second simple value
+ ASSERT_EQ(w->putLong(0, 2, 0xface), OK);
+
+ // Store second object that requires inflation
+ memset(buf, 84, kHalfInlineSize);
+ ASSERT_EQ(w->putBlob(0, 3, buf, kHalfInlineSize), OK);
+ ASSERT_GT(w->size(), before);
+
+ // Verify data is intact
+ {
+ auto field = w->getFieldSlot(0, 0);
+ ASSERT_EQ(w->getFieldSlotType(field), CursorWindow::FIELD_TYPE_INTEGER);
+ ASSERT_EQ(w->getFieldSlotValueLong(field), 0xcafe);
+ }
+ {
+ auto field = w->getFieldSlot(0, 1);
+ ASSERT_EQ(w->getFieldSlotType(field), CursorWindow::FIELD_TYPE_BLOB);
+ size_t actualSize;
+ auto actual = w->getFieldSlotValueBlob(field, &actualSize);
+ ASSERT_EQ(actualSize, kHalfInlineSize);
+ memset(buf, 42, kHalfInlineSize);
+ ASSERT_NE(actual, buf);
+ ASSERT_EQ(memcmp(buf, actual, kHalfInlineSize), 0);
+ }
+ {
+ auto field = w->getFieldSlot(0, 2);
+ ASSERT_EQ(w->getFieldSlotType(field), CursorWindow::FIELD_TYPE_INTEGER);
+ ASSERT_EQ(w->getFieldSlotValueLong(field), 0xface);
+ }
+ {
+ auto field = w->getFieldSlot(0, 3);
+ ASSERT_EQ(w->getFieldSlotType(field), CursorWindow::FIELD_TYPE_BLOB);
+ size_t actualSize;
+ auto actual = w->getFieldSlotValueBlob(field, &actualSize);
+ ASSERT_EQ(actualSize, kHalfInlineSize);
+ memset(buf, 84, kHalfInlineSize);
+ ASSERT_NE(actual, buf);
+ ASSERT_EQ(memcmp(buf, actual, kHalfInlineSize), 0);
+ }
+}
+
+TEST(CursorWindowTest, ParcelEmpty) {
+ CREATE_WINDOW_2M;
+
+ Parcel p;
+ w->writeToParcel(&p);
+ p.setDataPosition(0);
+ w = nullptr;
+
+ ASSERT_EQ(CursorWindow::createFromParcel(&p, &w), OK);
+ ASSERT_EQ(w->getNumRows(), 0);
+ ASSERT_EQ(w->getNumColumns(), 0);
+ ASSERT_EQ(w->size(), 0);
+ ASSERT_EQ(w->freeSpace(), 0);
+
+ // We can't mutate the window after parceling
+ ASSERT_NE(w->setNumColumns(4), OK);
+ ASSERT_NE(w->allocRow(), OK);
+}
+
+TEST(CursorWindowTest, ParcelSmall) {
+ CREATE_WINDOW_2M;
+
+ auto before = w->size();
+ ASSERT_EQ(w->setNumColumns(4), OK);
+ ASSERT_EQ(w->allocRow(), OK);
+
+ // Scratch buffer that will fit before inflation
+ void* buf = malloc(kHalfInlineSize);
+
+ // Store simple value
+ ASSERT_EQ(w->putLong(0, 0, 0xcafe), OK);
+
+ // Store first object that fits inside
+ memset(buf, 42, kHalfInlineSize);
+ ASSERT_EQ(w->putBlob(0, 1, buf, kHalfInlineSize), OK);
+ ASSERT_EQ(w->size(), before);
+
+ // Store second object with zero length
+ ASSERT_EQ(w->putBlob(0, 2, buf, 0), OK);
+ ASSERT_EQ(w->size(), before);
+
+ // Force through a parcel
+ Parcel p;
+ w->writeToParcel(&p);
+ p.setDataPosition(0);
+ w = nullptr;
+
+ ASSERT_EQ(CursorWindow::createFromParcel(&p, &w), OK);
+ ASSERT_EQ(w->getNumRows(), 1);
+ ASSERT_EQ(w->getNumColumns(), 4);
+
+ // Verify data is intact
+ {
+ auto field = w->getFieldSlot(0, 0);
+ ASSERT_EQ(w->getFieldSlotType(field), CursorWindow::FIELD_TYPE_INTEGER);
+ ASSERT_EQ(w->getFieldSlotValueLong(field), 0xcafe);
+ }
+ {
+ auto field = w->getFieldSlot(0, 1);
+ ASSERT_EQ(w->getFieldSlotType(field), CursorWindow::FIELD_TYPE_BLOB);
+ size_t actualSize;
+ auto actual = w->getFieldSlotValueBlob(field, &actualSize);
+ ASSERT_EQ(actualSize, kHalfInlineSize);
+ memset(buf, 42, kHalfInlineSize);
+ ASSERT_NE(actual, buf);
+ ASSERT_EQ(memcmp(buf, actual, kHalfInlineSize), 0);
+ }
+ {
+ auto field = w->getFieldSlot(0, 2);
+ ASSERT_EQ(w->getFieldSlotType(field), CursorWindow::FIELD_TYPE_BLOB);
+ size_t actualSize;
+ auto actual = w->getFieldSlotValueBlob(field, &actualSize);
+ ASSERT_EQ(actualSize, 0);
+ ASSERT_NE(actual, nullptr);
+ }
+}
+
+TEST(CursorWindowTest, ParcelLarge) {
+ CREATE_WINDOW_2M;
+
+ ASSERT_EQ(w->setNumColumns(4), OK);
+ ASSERT_EQ(w->allocRow(), OK);
+
+ // Store simple value
+ ASSERT_EQ(w->putLong(0, 0, 0xcafe), OK);
+
+ // Store object that forces inflation
+ void* buf = malloc(kGiantSize);
+ memset(buf, 42, kGiantSize);
+ ASSERT_EQ(w->putBlob(0, 1, buf, kGiantSize), OK);
+
+ // Store second object with zero length
+ ASSERT_EQ(w->putBlob(0, 2, buf, 0), OK);
+
+ // Force through a parcel
+ Parcel p;
+ w->writeToParcel(&p);
+ p.setDataPosition(0);
+ w = nullptr;
+
+ ASSERT_EQ(CursorWindow::createFromParcel(&p, &w), OK);
+ ASSERT_EQ(w->getNumRows(), 1);
+ ASSERT_EQ(w->getNumColumns(), 4);
+
+ // Verify data is intact
+ {
+ auto field = w->getFieldSlot(0, 0);
+ ASSERT_EQ(w->getFieldSlotType(field), CursorWindow::FIELD_TYPE_INTEGER);
+ ASSERT_EQ(w->getFieldSlotValueLong(field), 0xcafe);
+ }
+ {
+ auto field = w->getFieldSlot(0, 1);
+ ASSERT_EQ(w->getFieldSlotType(field), CursorWindow::FIELD_TYPE_BLOB);
+ size_t actualSize;
+ auto actual = w->getFieldSlotValueBlob(field, &actualSize);
+ ASSERT_EQ(actualSize, kGiantSize);
+ memset(buf, 42, kGiantSize);
+ ASSERT_EQ(memcmp(buf, actual, kGiantSize), 0);
+ }
+ {
+ auto field = w->getFieldSlot(0, 2);
+ ASSERT_EQ(w->getFieldSlotType(field), CursorWindow::FIELD_TYPE_BLOB);
+ size_t actualSize;
+ auto actual = w->getFieldSlotValueBlob(field, &actualSize);
+ ASSERT_EQ(actualSize, 0);
+ ASSERT_NE(actual, nullptr);
+ }
+}
+
+} // android
diff --git a/libs/androidfw/tests/data/overlay/overlay.apk b/libs/androidfw/tests/data/overlay/overlay.apk
index f1ed59279fdb..c9bf2527c82a 100644
--- a/libs/androidfw/tests/data/overlay/overlay.apk
+++ b/libs/androidfw/tests/data/overlay/overlay.apk
Binary files differ
diff --git a/libs/androidfw/tests/data/overlay/overlay.idmap b/libs/androidfw/tests/data/overlay/overlay.idmap
index 29c5eb6a9ccf..3ab244eb084a 100644
--- a/libs/androidfw/tests/data/overlay/overlay.idmap
+++ b/libs/androidfw/tests/data/overlay/overlay.idmap
Binary files differ
diff --git a/location/java/android/location/Geofence.java b/location/java/android/location/Geofence.java
index 19b017b7dff9..10773f82fa43 100644
--- a/location/java/android/location/Geofence.java
+++ b/location/java/android/location/Geofence.java
@@ -58,7 +58,7 @@ public final class Geofence implements Parcelable {
Geofence(double latitude, double longitude, float radius, long expirationRealtimeMs) {
Preconditions.checkArgumentInRange(latitude, -90.0, 90.0, "latitude");
Preconditions.checkArgumentInRange(longitude, -180.0, 180.0, "latitude");
- Preconditions.checkArgument(radius > 0, "invalid radius: " + radius);
+ Preconditions.checkArgument(radius > 0, "invalid radius: %f", radius);
mLatitude = latitude;
mLongitude = longitude;
diff --git a/location/java/android/location/Location.java b/location/java/android/location/Location.java
index 46bd22148fb2..62b4bc173bb9 100644
--- a/location/java/android/location/Location.java
+++ b/location/java/android/location/Location.java
@@ -19,7 +19,6 @@ package android.location;
import static java.util.concurrent.TimeUnit.NANOSECONDS;
import android.annotation.SystemApi;
-import android.annotation.TestApi;
import android.compat.annotation.UnsupportedAppUsage;
import android.os.Build;
import android.os.Bundle;
@@ -75,7 +74,6 @@ public class Location implements Parcelable {
* gps locations separate from other locations for coarsening. Providers that do not need to
* support platforms below Android R should not use this constant.
*/
- @TestApi
@SystemApi
@Deprecated
public static final String EXTRA_NO_GPS_LOCATION = "noGPSLocation";
@@ -1074,7 +1072,6 @@ public class Location implements Parcelable {
* @see #isComplete
* @hide
*/
- @TestApi
@SystemApi
public void makeComplete() {
if (mProvider == null) mProvider = "?";
diff --git a/location/java/android/location/LocationManager.java b/location/java/android/location/LocationManager.java
index 30a4ada1b388..ac775ca05cab 100644
--- a/location/java/android/location/LocationManager.java
+++ b/location/java/android/location/LocationManager.java
@@ -575,7 +575,6 @@ public class LocationManager {
* @hide
*/
@SystemApi
- @TestApi
@RequiresPermission(WRITE_SECURE_SETTINGS)
public void setLocationEnabledForUser(boolean enabled, @NonNull UserHandle userHandle) {
try {
@@ -751,7 +750,6 @@ public class LocationManager {
*/
@Deprecated
@SystemApi
- @TestApi
@RequiresPermission(anyOf = {ACCESS_COARSE_LOCATION, ACCESS_FINE_LOCATION})
public void getCurrentLocation(@NonNull LocationRequest locationRequest,
@Nullable CancellationSignal cancellationSignal,
@@ -1192,7 +1190,6 @@ public class LocationManager {
*/
@Deprecated
@SystemApi
- @TestApi
@RequiresPermission(anyOf = {ACCESS_COARSE_LOCATION, ACCESS_FINE_LOCATION})
public void requestLocationUpdates(
@Nullable LocationRequest locationRequest,
@@ -1223,7 +1220,6 @@ public class LocationManager {
*/
@Deprecated
@SystemApi
- @TestApi
@RequiresPermission(anyOf = {ACCESS_COARSE_LOCATION, ACCESS_FINE_LOCATION})
public void requestLocationUpdates(
@Nullable LocationRequest locationRequest,
@@ -1255,7 +1251,6 @@ public class LocationManager {
*/
@Deprecated
@SystemApi
- @TestApi
@RequiresPermission(anyOf = {ACCESS_COARSE_LOCATION, ACCESS_FINE_LOCATION})
public void requestLocationUpdates(
@Nullable LocationRequest locationRequest,
diff --git a/location/java/android/location/LocationRequest.java b/location/java/android/location/LocationRequest.java
index 4977c2161be9..1adb2b47a884 100644
--- a/location/java/android/location/LocationRequest.java
+++ b/location/java/android/location/LocationRequest.java
@@ -27,7 +27,6 @@ import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.RequiresPermission;
import android.annotation.SystemApi;
-import android.annotation.TestApi;
import android.compat.annotation.ChangeId;
import android.compat.annotation.EnabledAfter;
import android.compat.annotation.UnsupportedAppUsage;
@@ -75,19 +74,27 @@ public final class LocationRequest implements Parcelable {
/**
* A quality constant indicating a location provider may choose to satisfy this request by
- * providing very accurate locations at the expense of potentially increased power usage.
+ * providing very accurate locations at the expense of potentially increased power usage. Each
+ * location provider may interpret this field differently, but as an example, the network
+ * provider may choose to return only wifi based locations rather than cell based locations in
+ * order to have greater accuracy when this flag is present.
*/
public static final int QUALITY_HIGH_ACCURACY = 100;
/**
* A quality constant indicating a location provider may choose to satisfy this request by
- * equally balancing power and accuracy constraints.
+ * equally balancing power and accuracy constraints. Each location provider may interpret this
+ * field differently, but location providers will generally use their default behavior when this
+ * flag is present.
*/
public static final int QUALITY_BALANCED_POWER_ACCURACY = 102;
/**
* A quality constant indicating a location provider may choose to satisfy this request by
- * providing less accurate locations in order to save power.
+ * providing less accurate locations in order to save power. Each location provider may
+ * interpret this field differently, but as an example, the network provider may choose to
+ * return cell based locations rather than wifi based locations in order to save power when this
+ * flag is present.
*/
public static final int QUALITY_LOW_POWER = 104;
@@ -101,7 +108,6 @@ public final class LocationRequest implements Parcelable {
*/
@Deprecated
@SystemApi
- @TestApi
public static final int ACCURACY_FINE = QUALITY_HIGH_ACCURACY;
/**
@@ -116,7 +122,6 @@ public final class LocationRequest implements Parcelable {
*/
@Deprecated
@SystemApi
- @TestApi
public static final int ACCURACY_BLOCK = QUALITY_BALANCED_POWER_ACCURACY;
/**
@@ -131,7 +136,6 @@ public final class LocationRequest implements Parcelable {
*/
@Deprecated
@SystemApi
- @TestApi
public static final int ACCURACY_CITY = QUALITY_LOW_POWER;
/**
@@ -159,7 +163,6 @@ public final class LocationRequest implements Parcelable {
*/
@Deprecated
@SystemApi
- @TestApi
public static final int POWER_LOW = 201;
/**
@@ -172,7 +175,6 @@ public final class LocationRequest implements Parcelable {
*/
@Deprecated
@SystemApi
- @TestApi
public static final int POWER_HIGH = 203;
private static final long IMPLICIT_MIN_UPDATE_INTERVAL = -1;
@@ -618,7 +620,6 @@ public final class LocationRequest implements Parcelable {
*
* @hide
*/
- @TestApi
@SystemApi
public boolean isHiddenFromAppOps() {
return mHideFromAppOps;
@@ -644,7 +645,6 @@ public final class LocationRequest implements Parcelable {
*
* @hide
*/
- @TestApi
@SystemApi
public boolean isLocationSettingsIgnored() {
return mLocationSettingsIgnored;
@@ -680,7 +680,6 @@ public final class LocationRequest implements Parcelable {
*
* @hide
*/
- @TestApi
@SystemApi
public boolean isLowPower() {
return mLowPower;
@@ -707,7 +706,6 @@ public final class LocationRequest implements Parcelable {
*
* @hide
*/
- @TestApi
@SystemApi
public @NonNull WorkSource getWorkSource() {
return mWorkSource;
@@ -936,7 +934,7 @@ public final class LocationRequest implements Parcelable {
Preconditions.checkArgument(
quality == QUALITY_LOW_POWER || quality == QUALITY_BALANCED_POWER_ACCURACY
|| quality == QUALITY_HIGH_ACCURACY,
- "quality must be a defined QUALITY constant, not " + quality);
+ "quality must be a defined QUALITY constant, not %d", quality);
mQuality = quality;
return this;
}
@@ -1038,7 +1036,6 @@ public final class LocationRequest implements Parcelable {
*
* @hide
*/
- @TestApi
@SystemApi
@RequiresPermission(Manifest.permission.UPDATE_APP_OPS_STATS)
public @NonNull Builder setHiddenFromAppOps(boolean hiddenFromAppOps) {
@@ -1057,7 +1054,6 @@ public final class LocationRequest implements Parcelable {
*
* @hide
*/
- @TestApi
@SystemApi
@RequiresPermission(Manifest.permission.WRITE_SECURE_SETTINGS)
public @NonNull Builder setLocationSettingsIgnored(boolean locationSettingsIgnored) {
@@ -1075,7 +1071,6 @@ public final class LocationRequest implements Parcelable {
*
* @hide
*/
- @TestApi
@SystemApi
@RequiresPermission(Manifest.permission.LOCATION_HARDWARE)
public @NonNull Builder setLowPower(boolean lowPower) {
@@ -1093,7 +1088,6 @@ public final class LocationRequest implements Parcelable {
*
* @hide
*/
- @TestApi
@SystemApi
@RequiresPermission(Manifest.permission.UPDATE_DEVICE_STATS)
public @NonNull Builder setWorkSource(@Nullable WorkSource workSource) {
diff --git a/media/Android.bp b/media/Android.bp
index 828707b70e7b..8b06bb26fcf7 100644
--- a/media/Android.bp
+++ b/media/Android.bp
@@ -1,7 +1,10 @@
aidl_interface {
name: "audio_common-aidl",
unstable: true,
+ host_supported: true,
+ vendor_available: true,
local_include_dir: "aidl",
+ double_loadable: true,
srcs: [
"aidl/android/media/audio/common/AudioChannelMask.aidl",
"aidl/android/media/audio/common/AudioConfig.aidl",
diff --git a/media/OWNERS b/media/OWNERS
index 0fc781c848f7..e74149019b11 100644
--- a/media/OWNERS
+++ b/media/OWNERS
@@ -1,4 +1,3 @@
-andrewlewis@google.com
chz@google.com
elaurent@google.com
essick@google.com
@@ -18,5 +17,12 @@ marcone@google.com
nchalko@google.com
philburk@google.com
quxiangfang@google.com
-sungsoo@google.com
wonsik@google.com
+
+# LON
+andrewlewis@google.com
+aquilescanta@google.com
+olly@google.com
+
+# SEO
+sungsoo@google.com
diff --git a/media/java/android/media/AudioFocusInfo.java b/media/java/android/media/AudioFocusInfo.java
index 675cf7360b82..3647b6ebcfbc 100644
--- a/media/java/android/media/AudioFocusInfo.java
+++ b/media/java/android/media/AudioFocusInfo.java
@@ -19,7 +19,6 @@ package android.media;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.SystemApi;
-import android.annotation.TestApi;
import android.os.Parcel;
import android.os.Parcelable;
@@ -29,7 +28,6 @@ import java.util.Objects;
* @hide
* A class to encapsulate information about an audio focus owner or request.
*/
-@TestApi
@SystemApi
public final class AudioFocusInfo implements Parcelable {
diff --git a/media/java/android/media/AudioManager.java b/media/java/android/media/AudioManager.java
index 22b5ca53e7e9..195122db146a 100644
--- a/media/java/android/media/AudioManager.java
+++ b/media/java/android/media/AudioManager.java
@@ -3916,7 +3916,6 @@ public class AudioManager {
* @param requestResult the result to the focus request to be passed to the requester
* @param ap a valid registered {@link AudioPolicy} configured as a focus policy.
*/
- @TestApi
@SystemApi
@RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING)
public void setFocusRequestResult(@NonNull AudioFocusInfo afi,
@@ -3956,7 +3955,6 @@ public class AudioManager {
* if there was an error sending the request.
* @throws NullPointerException if the {@link AudioFocusInfo} or {@link AudioPolicy} are null.
*/
- @TestApi
@SystemApi
@RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING)
public int dispatchAudioFocusChange(@NonNull AudioFocusInfo afi, int focusChange,
@@ -4219,7 +4217,6 @@ public class AudioManager {
* {@link android.Manifest.permission#MODIFY_AUDIO_ROUTING} permission,
* {@link #SUCCESS} otherwise.
*/
- @TestApi
@SystemApi
@RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING)
public int registerAudioPolicy(@NonNull AudioPolicy policy) {
@@ -4254,7 +4251,6 @@ public class AudioManager {
* Unregisters an {@link AudioPolicy} asynchronously.
* @param policy the non-null {@link AudioPolicy} to unregister.
*/
- @TestApi
@SystemApi
@RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING)
public void unregisterAudioPolicyAsync(@NonNull AudioPolicy policy) {
@@ -4281,7 +4277,6 @@ public class AudioManager {
* associated with mixes of this policy.
* @param policy the non-null {@link AudioPolicy} to unregister.
*/
- @TestApi
@SystemApi
@RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING)
public void unregisterAudioPolicy(@NonNull AudioPolicy policy) {
@@ -5619,7 +5614,6 @@ public class AudioManager {
*/
/** @hide */
- @TestApi
@SystemApi
public static final int SUCCESS = AudioSystem.SUCCESS;
/**
diff --git a/media/java/android/media/ExifInterface.java b/media/java/android/media/ExifInterface.java
index f9cbdd42bc4f..44890bee2291 100644
--- a/media/java/android/media/ExifInterface.java
+++ b/media/java/android/media/ExifInterface.java
@@ -31,6 +31,8 @@ import android.compat.annotation.UnsupportedAppUsage;
import android.content.res.AssetManager;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
+import android.os.FileUtils;
+import android.os.SystemProperties;
import android.system.ErrnoException;
import android.system.Os;
import android.system.OsConstants;
@@ -1523,6 +1525,11 @@ public class ExifInterface {
if (fileDescriptor == null) {
throw new NullPointerException("fileDescriptor cannot be null");
}
+ boolean optimize = SystemProperties.getBoolean("fuse.sys.transcode_exif_optimize", false);
+ FileDescriptor modernFd = optimize ? FileUtils.convertToModernFd(fileDescriptor) : null;
+ if (modernFd != null) {
+ fileDescriptor = modernFd;
+ }
mAssetInputStream = null;
mFilename = null;
@@ -2533,11 +2540,20 @@ public class ExifInterface {
private void initForFilename(String filename) throws IOException {
FileInputStream in = null;
+ FileInputStream legacyInputStream = null;
mAssetInputStream = null;
mFilename = filename;
mIsInputStream = false;
try {
in = new FileInputStream(filename);
+ boolean optimize = SystemProperties.getBoolean("fuse.sys.transcode_exif_optimize",
+ false);
+ FileDescriptor modernFd = optimize ? FileUtils.convertToModernFd(in.getFD()) : null;
+ if (modernFd != null) {
+ legacyInputStream = in;
+ in = new FileInputStream(modernFd);
+ }
+
if (isSeekableFD(in.getFD())) {
mSeekableFileDescriptor = in.getFD();
} else {
@@ -2546,6 +2562,7 @@ public class ExifInterface {
loadAttributes(in);
} finally {
closeQuietly(in);
+ closeQuietly(legacyInputStream);
}
}
diff --git a/media/java/android/media/MediaMetadataRetriever.java b/media/java/android/media/MediaMetadataRetriever.java
index 835a7091bb70..ca8b9b936e99 100644
--- a/media/java/android/media/MediaMetadataRetriever.java
+++ b/media/java/android/media/MediaMetadataRetriever.java
@@ -30,7 +30,10 @@ import android.content.res.AssetFileDescriptor;
import android.graphics.Bitmap;
import android.net.Uri;
import android.os.Build;
+import android.os.Bundle;
+import android.os.FileUtils;
import android.os.IBinder;
+import android.os.SystemProperties;
import android.text.TextUtils;
import java.io.FileDescriptor;
@@ -48,7 +51,6 @@ import java.util.Map;
* frame and meta data from an input media file.
*/
public class MediaMetadataRetriever implements AutoCloseable {
-
// borrowed from ExoPlayer
private static final String[] STANDARD_GENRES = new String[] {
// These are the official ID3v1 genres.
@@ -296,7 +298,19 @@ public class MediaMetadataRetriever implements AutoCloseable {
* non-negative.
* @throws IllegalArgumentException if the arguments are invalid
*/
- public native void setDataSource(FileDescriptor fd, long offset, long length)
+ public void setDataSource(FileDescriptor fd, long offset, long length)
+ throws IllegalArgumentException {
+ boolean optimize = SystemProperties.getBoolean("fuse.sys.transcode_retriever_optimize",
+ false);
+ FileDescriptor modernFd = optimize ? FileUtils.convertToModernFd(fd) : null;
+ if (modernFd == null) {
+ _setDataSource(fd, offset, length);
+ } else {
+ _setDataSource(modernFd, offset, length);
+ }
+ }
+
+ private native void _setDataSource(FileDescriptor fd, long offset, long length)
throws IllegalArgumentException;
/**
@@ -340,7 +354,12 @@ public class MediaMetadataRetriever implements AutoCloseable {
try {
ContentResolver resolver = context.getContentResolver();
try {
- fd = resolver.openAssetFileDescriptor(uri, "r");
+ boolean optimize =
+ SystemProperties.getBoolean("fuse.sys.transcode_retriever_optimize", false);
+ Bundle opts = new Bundle();
+ opts.putBoolean("android.provider.extra.ACCEPT_ORIGINAL_MEDIA_FORMAT", true);
+ fd = optimize ? resolver.openTypedAssetFileDescriptor(uri, "*/*", opts)
+ : resolver.openAssetFileDescriptor(uri, "r");
} catch(FileNotFoundException e) {
throw new IllegalArgumentException("could not access " + uri);
}
diff --git a/media/java/android/media/MediaPlayer.java b/media/java/android/media/MediaPlayer.java
index 851c1ec8ec1f..47d276a50034 100644
--- a/media/java/android/media/MediaPlayer.java
+++ b/media/java/android/media/MediaPlayer.java
@@ -31,6 +31,8 @@ import android.graphics.SurfaceTexture;
import android.media.SubtitleController.Anchor;
import android.media.SubtitleTrack.RenderingWidget;
import android.net.Uri;
+import android.os.Bundle;
+import android.os.FileUtils;
import android.os.Handler;
import android.os.HandlerThread;
import android.os.IBinder;
@@ -1104,7 +1106,13 @@ public class MediaPlayer extends PlayerBase
}
private boolean attemptDataSource(ContentResolver resolver, Uri uri) {
- try (AssetFileDescriptor afd = resolver.openAssetFileDescriptor(uri, "r")) {
+ boolean optimize = SystemProperties.getBoolean("fuse.sys.transcode_player_optimize",
+ false);
+ Bundle opts = new Bundle();
+ opts.putBoolean("android.provider.extra.ACCEPT_ORIGINAL_MEDIA_FORMAT", true);
+ try (AssetFileDescriptor afd = optimize
+ ? resolver.openTypedAssetFileDescriptor(uri, "*/*", opts)
+ : resolver.openAssetFileDescriptor(uri, "r")) {
setDataSource(afd);
return true;
} catch (NullPointerException | SecurityException | IOException ex) {
@@ -1245,7 +1253,13 @@ public class MediaPlayer extends PlayerBase
*/
public void setDataSource(FileDescriptor fd, long offset, long length)
throws IOException, IllegalArgumentException, IllegalStateException {
- _setDataSource(fd, offset, length);
+ boolean optimize = SystemProperties.getBoolean("fuse.sys.transcode_player_optimize", false);
+ FileDescriptor modernFd = optimize ? FileUtils.convertToModernFd(fd) : null;
+ if (modernFd == null) {
+ _setDataSource(fd, offset, length);
+ } else {
+ _setDataSource(modernFd, offset, length);
+ }
}
private native void _setDataSource(FileDescriptor fd, long offset, long length)
@@ -2899,8 +2913,13 @@ public class MediaPlayer extends PlayerBase
AssetFileDescriptor fd = null;
try {
+ boolean optimize = SystemProperties.getBoolean("fuse.sys.transcode_player_optimize",
+ false);
ContentResolver resolver = context.getContentResolver();
- fd = resolver.openAssetFileDescriptor(uri, "r");
+ Bundle opts = new Bundle();
+ opts.putBoolean("android.provider.extra.ACCEPT_ORIGINAL_MEDIA_FORMAT", true);
+ fd = optimize ? resolver.openTypedAssetFileDescriptor(uri, "*/*", opts)
+ : resolver.openAssetFileDescriptor(uri, "r");
if (fd == null) {
return;
}
diff --git a/media/java/android/media/MediaTranscodeManager.java b/media/java/android/media/MediaTranscodeManager.java
index 8676462c5c54..046403670693 100644
--- a/media/java/android/media/MediaTranscodeManager.java
+++ b/media/java/android/media/MediaTranscodeManager.java
@@ -22,7 +22,6 @@ import android.annotation.IntRange;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.SystemApi;
-import android.annotation.TestApi;
import android.content.ContentResolver;
import android.content.Context;
import android.content.res.AssetFileDescriptor;
@@ -101,7 +100,6 @@ import java.util.concurrent.Executors;
TODO(hkuang): Clarify whether supports framerate conversion.
@hide
*/
-@TestApi
@SystemApi
public final class MediaTranscodeManager {
private static final String TAG = "MediaTranscodeManager";
diff --git a/media/java/android/media/audiopolicy/AudioMix.java b/media/java/android/media/audiopolicy/AudioMix.java
index 61113bc858db..4e451c6e42b1 100644
--- a/media/java/android/media/audiopolicy/AudioMix.java
+++ b/media/java/android/media/audiopolicy/AudioMix.java
@@ -19,7 +19,6 @@ package android.media.audiopolicy;
import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.SystemApi;
-import android.annotation.TestApi;
import android.compat.annotation.UnsupportedAppUsage;
import android.media.AudioDeviceInfo;
import android.media.AudioFormat;
@@ -32,7 +31,6 @@ import java.util.Objects;
/**
* @hide
*/
-@TestApi
@SystemApi
public class AudioMix {
diff --git a/media/java/android/media/audiopolicy/AudioMixingRule.java b/media/java/android/media/audiopolicy/AudioMixingRule.java
index 68c9593d102d..f6f982a4ebe2 100644
--- a/media/java/android/media/audiopolicy/AudioMixingRule.java
+++ b/media/java/android/media/audiopolicy/AudioMixingRule.java
@@ -18,7 +18,6 @@ package android.media.audiopolicy;
import android.annotation.NonNull;
import android.annotation.SystemApi;
-import android.annotation.TestApi;
import android.compat.annotation.UnsupportedAppUsage;
import android.media.AudioAttributes;
import android.os.Parcel;
@@ -42,7 +41,6 @@ import java.util.Objects;
* .build();
* </pre>
*/
-@TestApi
@SystemApi
public class AudioMixingRule {
diff --git a/media/java/android/media/audiopolicy/AudioPolicy.java b/media/java/android/media/audiopolicy/AudioPolicy.java
index 8a17465c53b3..3e8d76ac7551 100644
--- a/media/java/android/media/audiopolicy/AudioPolicy.java
+++ b/media/java/android/media/audiopolicy/AudioPolicy.java
@@ -58,7 +58,6 @@ import java.util.Objects;
* @hide
* AudioPolicy provides access to the management of audio routing and audio focus.
*/
-@TestApi
@SystemApi
public class AudioPolicy {
@@ -418,7 +417,6 @@ public class AudioPolicy {
* @param devices list of devices to which the audio stream of the application may be routed.
* @return true if the change was successful, false otherwise.
*/
- @TestApi
@SystemApi
public boolean setUidDeviceAffinity(int uid, @NonNull List<AudioDeviceInfo> devices) {
if (devices == null) {
@@ -460,7 +458,6 @@ public class AudioPolicy {
* @param uid UID of the application affected.
* @return true if the change was successful, false otherwise.
*/
- @TestApi
@SystemApi
public boolean removeUidDeviceAffinity(int uid) {
synchronized (mLock) {
@@ -486,7 +483,6 @@ public class AudioPolicy {
* {@link UserHandle#getIdentifier}. Not to be confused with application uid.
* @return true if the change was successful, false otherwise.
*/
- @TestApi
@SystemApi
public boolean removeUserIdDeviceAffinity(@UserIdInt int userId) {
synchronized (mLock) {
@@ -519,7 +515,6 @@ public class AudioPolicy {
* @param devices list of devices to which the audio stream of the application may be routed.
* @return true if the change was successful, false otherwise.
*/
- @TestApi
@SystemApi
public boolean setUserIdDeviceAffinity(@UserIdInt int userId,
@NonNull List<AudioDeviceInfo> devices) {
diff --git a/media/java/android/media/musicrecognition/MusicRecognitionManager.java b/media/java/android/media/musicrecognition/MusicRecognitionManager.java
index c7f55dfe1c76..6bbcfd3b5b66 100644
--- a/media/java/android/media/musicrecognition/MusicRecognitionManager.java
+++ b/media/java/android/media/musicrecognition/MusicRecognitionManager.java
@@ -25,7 +25,6 @@ import android.annotation.Nullable;
import android.annotation.RequiresPermission;
import android.annotation.SystemApi;
import android.annotation.SystemService;
-import android.annotation.TestApi;
import android.content.Context;
import android.media.MediaMetadata;
import android.os.Bundle;
@@ -41,7 +40,6 @@ import java.util.concurrent.Executor;
* @hide
*/
@SystemApi
-@TestApi
@SystemService(Context.MUSIC_RECOGNITION_SERVICE)
public class MusicRecognitionManager {
diff --git a/media/java/android/media/musicrecognition/MusicRecognitionService.java b/media/java/android/media/musicrecognition/MusicRecognitionService.java
index b75d2c4f1e50..e2071b84c00b 100644
--- a/media/java/android/media/musicrecognition/MusicRecognitionService.java
+++ b/media/java/android/media/musicrecognition/MusicRecognitionService.java
@@ -21,7 +21,6 @@ import static com.android.internal.util.function.pooled.PooledLambda.obtainMessa
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.SystemApi;
-import android.annotation.TestApi;
import android.app.Service;
import android.content.Intent;
import android.media.AudioFormat;
@@ -41,7 +40,6 @@ import android.util.Log;
* @hide
*/
@SystemApi
-@TestApi
public abstract class MusicRecognitionService extends Service {
private static final String TAG = MusicRecognitionService.class.getSimpleName();
diff --git a/media/java/android/media/musicrecognition/RecognitionRequest.java b/media/java/android/media/musicrecognition/RecognitionRequest.java
index 65b2ccd37f79..e4f484873cd4 100644
--- a/media/java/android/media/musicrecognition/RecognitionRequest.java
+++ b/media/java/android/media/musicrecognition/RecognitionRequest.java
@@ -23,7 +23,6 @@ import static java.util.Objects.requireNonNull;
import android.annotation.NonNull;
import android.annotation.SystemApi;
-import android.annotation.TestApi;
import android.media.AudioAttributes;
import android.media.AudioFormat;
import android.media.AudioRecord;
@@ -37,7 +36,6 @@ import android.os.Parcelable;
* @hide
*/
@SystemApi
-@TestApi
public final class RecognitionRequest implements Parcelable {
@NonNull private final AudioAttributes mAudioAttributes;
@NonNull private final AudioFormat mAudioFormat;
@@ -82,7 +80,6 @@ public final class RecognitionRequest implements Parcelable {
* @hide
*/
@SystemApi
- @TestApi
public static final class Builder {
private AudioFormat mAudioFormat = new AudioFormat.Builder()
.setSampleRate(16000)
diff --git a/media/java/android/media/tv/tuner/Tuner.java b/media/java/android/media/tv/tuner/Tuner.java
index 56499e26bafe..1881e38a5010 100644
--- a/media/java/android/media/tv/tuner/Tuner.java
+++ b/media/java/android/media/tv/tuner/Tuner.java
@@ -775,7 +775,8 @@ public class Tuner implements AutoCloseable {
*
* <p>This retrieve the statuses of the frontend for given status types.
*
- * @param statusTypes an array of status types which the caller requests.
+ * @param statusTypes an array of status types which the caller requests. Any types that are not
+ * in {@link FrontendInfo.getStatusCapabilities()} would be ignored.
* @return statuses which response the caller's requests. {@code null} if the operation failed.
*/
@Nullable
@@ -1047,6 +1048,20 @@ public class Tuner implements AutoCloseable {
}
}
+ private void onModulationReported(int modulation) {
+ if (mScanCallbackExecutor != null && mScanCallback != null) {
+ mScanCallbackExecutor.execute(
+ () -> mScanCallback.onModulationReported(modulation));
+ }
+ }
+
+ private void onPriorityReported(boolean isHighPriority) {
+ if (mScanCallbackExecutor != null && mScanCallback != null) {
+ mScanCallbackExecutor.execute(
+ () -> mScanCallback.onPriorityReported(isHighPriority));
+ }
+ }
+
/**
* Opens a filter object based on the given types and buffer size.
*
diff --git a/media/java/android/media/tv/tuner/TunerVersionChecker.java b/media/java/android/media/tv/tuner/TunerVersionChecker.java
index 739f87dd711d..b40ba1e763c1 100644
--- a/media/java/android/media/tv/tuner/TunerVersionChecker.java
+++ b/media/java/android/media/tv/tuner/TunerVersionChecker.java
@@ -31,7 +31,6 @@ import java.lang.annotation.RetentionPolicy;
*
* @hide
*/
-@TestApi
@SystemApi
public final class TunerVersionChecker {
private static final String TAG = "TunerVersionChecker";
diff --git a/media/java/android/media/tv/tuner/filter/AvSettings.java b/media/java/android/media/tv/tuner/filter/AvSettings.java
index e9b3660ab12f..5d9d53174b3e 100644
--- a/media/java/android/media/tv/tuner/filter/AvSettings.java
+++ b/media/java/android/media/tv/tuner/filter/AvSettings.java
@@ -16,9 +16,15 @@
package android.media.tv.tuner.filter;
+import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.SystemApi;
+import android.hardware.tv.tuner.V1_1.Constants;
import android.media.tv.tuner.TunerUtils;
+import android.media.tv.tuner.TunerVersionChecker;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
/**
* Filter Settings for a Video and Audio.
@@ -27,15 +33,160 @@ import android.media.tv.tuner.TunerUtils;
*/
@SystemApi
public class AvSettings extends Settings {
+ /** @hide */
+ @IntDef(prefix = "VIDEO_STREAM_TYPE_",
+ value = {VIDEO_STREAM_TYPE_UNDEFINED, VIDEO_STREAM_TYPE_RESERVED,
+ VIDEO_STREAM_TYPE_MPEG1, VIDEO_STREAM_TYPE_MPEG2,
+ VIDEO_STREAM_TYPE_MPEG4P2, VIDEO_STREAM_TYPE_AVC, VIDEO_STREAM_TYPE_HEVC,
+ VIDEO_STREAM_TYPE_VC1, VIDEO_STREAM_TYPE_VP8, VIDEO_STREAM_TYPE_VP9,
+ VIDEO_STREAM_TYPE_AV1, VIDEO_STREAM_TYPE_AVS, VIDEO_STREAM_TYPE_AVS2})
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface VideoStreamType {}
+
+ /*
+ * Undefined Video stream type
+ */
+ public static final int VIDEO_STREAM_TYPE_UNDEFINED = Constants.VideoStreamType.UNDEFINED;
+ /*
+ * ITU-T | ISO/IEC Reserved
+ */
+ public static final int VIDEO_STREAM_TYPE_RESERVED = Constants.VideoStreamType.RESERVED;
+ /*
+ * ISO/IEC 11172
+ */
+ public static final int VIDEO_STREAM_TYPE_MPEG1 = Constants.VideoStreamType.MPEG1;
+ /*
+ * ITU-T Rec.H.262 and ISO/IEC 13818-2
+ */
+ public static final int VIDEO_STREAM_TYPE_MPEG2 = Constants.VideoStreamType.MPEG2;
+ /*
+ * ISO/IEC 14496-2 (MPEG-4 H.263 based video)
+ */
+ public static final int VIDEO_STREAM_TYPE_MPEG4P2 = Constants.VideoStreamType.MPEG4P2;
+ /*
+ * ITU-T Rec.H.264 and ISO/IEC 14496-10
+ */
+ public static final int VIDEO_STREAM_TYPE_AVC = Constants.VideoStreamType.AVC;
+ /*
+ * ITU-T Rec. H.265 and ISO/IEC 23008-2
+ */
+ public static final int VIDEO_STREAM_TYPE_HEVC = Constants.VideoStreamType.HEVC;
+ /*
+ * Microsoft VC.1
+ */
+ public static final int VIDEO_STREAM_TYPE_VC1 = Constants.VideoStreamType.VC1;
+ /*
+ * Google VP8
+ */
+ public static final int VIDEO_STREAM_TYPE_VP8 = Constants.VideoStreamType.VP8;
+ /*
+ * Google VP9
+ */
+ public static final int VIDEO_STREAM_TYPE_VP9 = Constants.VideoStreamType.VP9;
+ /*
+ * AOMedia Video 1
+ */
+ public static final int VIDEO_STREAM_TYPE_AV1 = Constants.VideoStreamType.AV1;
+ /*
+ * Chinese Standard
+ */
+ public static final int VIDEO_STREAM_TYPE_AVS = Constants.VideoStreamType.AVS;
+ /*
+ * New Chinese Standard
+ */
+ public static final int VIDEO_STREAM_TYPE_AVS2 = Constants.VideoStreamType.AVS2;
+
+ /** @hide */
+ @IntDef(prefix = "AUDIO_STREAM_TYPE_",
+ value = {AUDIO_STREAM_TYPE_UNDEFINED, AUDIO_STREAM_TYPE_PCM, AUDIO_STREAM_TYPE_MP3,
+ AUDIO_STREAM_TYPE_MPEG1, AUDIO_STREAM_TYPE_MPEG2, AUDIO_STREAM_TYPE_MPEGH,
+ AUDIO_STREAM_TYPE_AAC, AUDIO_STREAM_TYPE_AC3, AUDIO_STREAM_TYPE_EAC3,
+ AUDIO_STREAM_TYPE_AC4, AUDIO_STREAM_TYPE_DTS, AUDIO_STREAM_TYPE_DTS_HD,
+ AUDIO_STREAM_TYPE_WMA, AUDIO_STREAM_TYPE_OPUS, AUDIO_STREAM_TYPE_VORBIS,
+ AUDIO_STREAM_TYPE_DRA})
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface AudioStreamType {}
+
+ /*
+ * Undefined Audio stream type
+ */
+ public static final int AUDIO_STREAM_TYPE_UNDEFINED = Constants.AudioStreamType.UNDEFINED;
+ /*
+ * Uncompressed Audio
+ */
+ public static final int AUDIO_STREAM_TYPE_PCM = Constants.AudioStreamType.PCM;
+ /*
+ * MPEG Audio Layer III versions
+ */
+ public static final int AUDIO_STREAM_TYPE_MP3 = Constants.AudioStreamType.MP3;
+ /*
+ * ISO/IEC 11172 Audio
+ */
+ public static final int AUDIO_STREAM_TYPE_MPEG1 = Constants.AudioStreamType.MPEG1;
+ /*
+ * ISO/IEC 13818-3
+ */
+ public static final int AUDIO_STREAM_TYPE_MPEG2 = Constants.AudioStreamType.MPEG2;
+ /*
+ * ISO/IEC 23008-3 (MPEG-H Part 3)
+ */
+ public static final int AUDIO_STREAM_TYPE_MPEGH = Constants.AudioStreamType.MPEGH;
+ /*
+ * ISO/IEC 14496-3
+ */
+ public static final int AUDIO_STREAM_TYPE_AAC = Constants.AudioStreamType.AAC;
+ /*
+ * Dolby Digital
+ */
+ public static final int AUDIO_STREAM_TYPE_AC3 = Constants.AudioStreamType.AC3;
+ /*
+ * Dolby Digital Plus
+ */
+ public static final int AUDIO_STREAM_TYPE_EAC3 = Constants.AudioStreamType.EAC3;
+ /*
+ * Dolby AC-4
+ */
+ public static final int AUDIO_STREAM_TYPE_AC4 = Constants.AudioStreamType.AC4;
+ /*
+ * Basic DTS
+ */
+ public static final int AUDIO_STREAM_TYPE_DTS = Constants.AudioStreamType.DTS;
+ /*
+ * High Resolution DTS
+ */
+ public static final int AUDIO_STREAM_TYPE_DTS_HD = Constants.AudioStreamType.DTS_HD;
+ /*
+ * Windows Media Audio
+ */
+ public static final int AUDIO_STREAM_TYPE_WMA = Constants.AudioStreamType.WMA;
+ /*
+ * Opus Interactive Audio Codec
+ */
+ public static final int AUDIO_STREAM_TYPE_OPUS = Constants.AudioStreamType.OPUS;
+ /*
+ * VORBIS Interactive Audio Codec
+ */
+ public static final int AUDIO_STREAM_TYPE_VORBIS = Constants.AudioStreamType.VORBIS;
+ /*
+ * SJ/T 11368-2006
+ */
+ public static final int AUDIO_STREAM_TYPE_DRA = Constants.AudioStreamType.DRA;
+
+
private final boolean mIsPassthrough;
+ private int mAudioStreamType = AUDIO_STREAM_TYPE_UNDEFINED;
+ private int mVideoStreamType = VIDEO_STREAM_TYPE_UNDEFINED;
- private AvSettings(int mainType, boolean isAudio, boolean isPassthrough) {
+ private AvSettings(int mainType, boolean isAudio, boolean isPassthrough,
+ int audioStreamType, int videoStreamType) {
super(TunerUtils.getFilterSubtype(
mainType,
isAudio
? Filter.SUBTYPE_AUDIO
: Filter.SUBTYPE_VIDEO));
mIsPassthrough = isPassthrough;
+ mAudioStreamType = audioStreamType;
+ mVideoStreamType = videoStreamType;
}
/**
@@ -46,6 +197,20 @@ public class AvSettings extends Settings {
}
/**
+ * Get the Audio Stream Type.
+ */
+ public int getAudioStreamType() {
+ return mAudioStreamType;
+ }
+
+ /**
+ * Get the Video Stream Type.
+ */
+ public int getVideoStreamType() {
+ return mVideoStreamType;
+ }
+
+ /**
* Creates a builder for {@link AvSettings}.
*
* @param mainType the filter main type.
@@ -63,6 +228,8 @@ public class AvSettings extends Settings {
private final int mMainType;
private final boolean mIsAudio;
private boolean mIsPassthrough;
+ private int mAudioStreamType = AUDIO_STREAM_TYPE_UNDEFINED;
+ private int mVideoStreamType = VIDEO_STREAM_TYPE_UNDEFINED;
private Builder(int mainType, boolean isAudio) {
mMainType = mainType;
@@ -79,11 +246,48 @@ public class AvSettings extends Settings {
}
/**
+ * Sets the Audio Stream Type.
+ *
+ * <p>This API is only supported by Tuner HAL 1.1 or higher. Unsupported version would cause
+ * no-op. Use {@link TunerVersionChecker.getTunerVersion()} to check the version.
+ *
+ * @param audioStreamType the {@link AudioStreamType} to set.
+ */
+ @NonNull
+ public Builder setAudioStreamType(@AudioStreamType int audioStreamType) {
+ if (TunerVersionChecker.checkHigherOrEqualVersionTo(
+ TunerVersionChecker.TUNER_VERSION_1_1, "setAudioStreamType") && mIsAudio) {
+ mAudioStreamType = audioStreamType;
+ mVideoStreamType = VIDEO_STREAM_TYPE_UNDEFINED;
+ }
+ return this;
+ }
+
+ /**
+ * Sets the Video Stream Type.
+ *
+ * <p>This API is only supported by Tuner HAL 1.1 or higher. Unsupported version would cause
+ * no-op. Use {@link TunerVersionChecker.getTunerVersion()} to check the version.
+ *
+ * @param videoStreamType the {@link VideoStreamType} to set.
+ */
+ @NonNull
+ public Builder setVideoStreamType(@VideoStreamType int videoStreamType) {
+ if (TunerVersionChecker.checkHigherOrEqualVersionTo(
+ TunerVersionChecker.TUNER_VERSION_1_1, "setVideoStreamType") && !mIsAudio) {
+ mVideoStreamType = videoStreamType;
+ mAudioStreamType = AUDIO_STREAM_TYPE_UNDEFINED;
+ }
+ return this;
+ }
+
+ /**
* Builds a {@link AvSettings} object.
*/
@NonNull
public AvSettings build() {
- return new AvSettings(mMainType, mIsAudio, mIsPassthrough);
+ return new AvSettings(mMainType, mIsAudio, mIsPassthrough,
+ mAudioStreamType, mVideoStreamType);
}
}
}
diff --git a/media/java/android/media/tv/tuner/filter/IpFilterConfiguration.java b/media/java/android/media/tv/tuner/filter/IpFilterConfiguration.java
index 2649fcf5a642..62d55f54cb26 100644
--- a/media/java/android/media/tv/tuner/filter/IpFilterConfiguration.java
+++ b/media/java/android/media/tv/tuner/filter/IpFilterConfiguration.java
@@ -16,6 +16,7 @@
package android.media.tv.tuner.filter;
+import android.annotation.IntRange;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.Size;
@@ -101,6 +102,7 @@ public final class IpFilterConfiguration extends FilterConfiguration {
* <p>This API is only supported by Tuner HAL 1.1 or higher. Unsupported version would return
* default value. Use {@link TunerVersionChecker.getTunerVersion()} to check the version.
*/
+ @IntRange(from = 0, to = 0xefff)
public int getIpFilterContextId() {
return mIpFilterContextId;
}
diff --git a/media/java/android/media/tv/tuner/filter/MediaEvent.java b/media/java/android/media/tv/tuner/filter/MediaEvent.java
index 57a04fd70a0b..91be5c38d693 100644
--- a/media/java/android/media/tv/tuner/filter/MediaEvent.java
+++ b/media/java/android/media/tv/tuner/filter/MediaEvent.java
@@ -187,7 +187,6 @@ public class MediaEvent extends FilterEvent {
/**
* Releases the MediaEvent object.
- * @hide
*/
public void release() {
synchronized (mLock) {
diff --git a/media/java/android/media/tv/tuner/frontend/DvbsFrontendSettings.java b/media/java/android/media/tv/tuner/frontend/DvbsFrontendSettings.java
index 343dbb137dd6..fadc00475930 100644
--- a/media/java/android/media/tv/tuner/frontend/DvbsFrontendSettings.java
+++ b/media/java/android/media/tv/tuner/frontend/DvbsFrontendSettings.java
@@ -260,10 +260,12 @@ public class DvbsFrontendSettings extends FrontendSettings {
private final int mVcmMode;
// Dvbs scan type is only supported in Tuner 1.1 or higher.
private final int mScanType;
+ // isDiseqcRxMessage is only supported in Tuner 1.1 or higher.
+ private final boolean mIsDiseqcRxMessage;
private DvbsFrontendSettings(int frequency, int modulation, DvbsCodeRate codeRate,
int symbolRate, int rolloff, int pilot, int inputStreamId, int standard, int vcm,
- int scanType) {
+ int scanType, boolean isDiseqcRxMessage) {
super(frequency);
mModulation = modulation;
mCodeRate = codeRate;
@@ -274,6 +276,7 @@ public class DvbsFrontendSettings extends FrontendSettings {
mStandard = standard;
mVcmMode = vcm;
mScanType = scanType;
+ mIsDiseqcRxMessage = isDiseqcRxMessage;
}
/**
@@ -337,6 +340,15 @@ public class DvbsFrontendSettings extends FrontendSettings {
public int getScanType() {
return mScanType;
}
+ /**
+ * To receive Diseqc Message or not. Default value is false.
+ *
+ * The setter {@link Builder#setDiseqcRxMessage(boolean)} is only supported with Tuner HAL 1.1
+ * or higher.
+ */
+ public boolean isDiseqcRxMessage() {
+ return mIsDiseqcRxMessage;
+ }
/**
* Creates a builder for {@link DvbsFrontendSettings}.
@@ -360,6 +372,7 @@ public class DvbsFrontendSettings extends FrontendSettings {
private int mStandard = STANDARD_AUTO;
private int mVcmMode = VCM_MODE_UNDEFINED;
private int mScanType = SCAN_TYPE_UNDEFINED;
+ private boolean mIsDiseqcRxMessage = false;
private Builder() {
}
@@ -395,6 +408,21 @@ public class DvbsFrontendSettings extends FrontendSettings {
}
/**
+ * Set true to receive Diseqc Message.
+ *
+ * <p>This API is only supported by Tuner HAL 1.1 or higher. Unsupported version would cause
+ * no-op. Use {@link TunerVersionChecker.getTunerVersion()} to check the version.
+ */
+ @NonNull
+ public Builder setDiseqcRxMessage(boolean isDiseqcRxMessage) {
+ if (TunerVersionChecker.checkHigherOrEqualVersionTo(
+ TunerVersionChecker.TUNER_VERSION_1_1, "setDiseqcRxMessage")) {
+ mIsDiseqcRxMessage = isDiseqcRxMessage;
+ }
+ return this;
+ }
+
+ /**
* Sets Modulation.
*
* <p>Default value is {@link #MODULATION_UNDEFINED}.
@@ -481,7 +509,8 @@ public class DvbsFrontendSettings extends FrontendSettings {
@NonNull
public DvbsFrontendSettings build() {
return new DvbsFrontendSettings(mFrequency, mModulation, mCodeRate, mSymbolRate,
- mRolloff, mPilot, mInputStreamId, mStandard, mVcmMode, mScanType);
+ mRolloff, mPilot, mInputStreamId, mStandard, mVcmMode, mScanType,
+ mIsDiseqcRxMessage);
}
}
diff --git a/media/java/android/media/tv/tuner/frontend/FrontendStatus.java b/media/java/android/media/tv/tuner/frontend/FrontendStatus.java
index c265bb9e6050..dd9347cd6e5d 100644
--- a/media/java/android/media/tv/tuner/frontend/FrontendStatus.java
+++ b/media/java/android/media/tv/tuner/frontend/FrontendStatus.java
@@ -21,6 +21,7 @@ import android.annotation.NonNull;
import android.annotation.SystemApi;
import android.hardware.tv.tuner.V1_0.Constants;
import android.media.tv.tuner.Lnb;
+import android.media.tv.tuner.TunerVersionChecker;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
@@ -43,7 +44,13 @@ public class FrontendStatus {
FRONTEND_STATUS_TYPE_EWBS, FRONTEND_STATUS_TYPE_AGC, FRONTEND_STATUS_TYPE_LNA,
FRONTEND_STATUS_TYPE_LAYER_ERROR, FRONTEND_STATUS_TYPE_MER,
FRONTEND_STATUS_TYPE_FREQ_OFFSET, FRONTEND_STATUS_TYPE_HIERARCHY,
- FRONTEND_STATUS_TYPE_RF_LOCK, FRONTEND_STATUS_TYPE_ATSC3_PLP_INFO})
+ FRONTEND_STATUS_TYPE_RF_LOCK, FRONTEND_STATUS_TYPE_ATSC3_PLP_INFO,
+ FRONTEND_STATUS_TYPE_BERS, FRONTEND_STATUS_TYPE_CODERATES,
+ FRONTEND_STATUS_TYPE_BANDWIDTH, FRONTEND_STATUS_TYPE_GUARD_INTERVAL,
+ FRONTEND_STATUS_TYPE_TRANSMISSION_MODE, FRONTEND_STATUS_TYPE_UEC,
+ FRONTEND_STATUS_TYPE_T2_SYSTEM_ID, FRONTEND_STATUS_TYPE_INTERLEAVINGS,
+ FRONTEND_STATUS_TYPE_ISDBT_SEGMENTS, FRONTEND_STATUS_TYPE_TS_DATA_RATES,
+ FRONTEND_STATUS_TYPE_MODULATIONS_EXT})
@Retention(RetentionPolicy.SOURCE)
public @interface FrontendStatusType {}
@@ -145,10 +152,83 @@ public class FrontendStatus {
*/
public static final int FRONTEND_STATUS_TYPE_ATSC3_PLP_INFO =
Constants.FrontendStatusType.ATSC3_PLP_INFO;
-
+ /**
+ * BERS Type. Only supported in Tuner HAL 1.1 or higher.
+ */
+ public static final int FRONTEND_STATUS_TYPE_BERS =
+ android.hardware.tv.tuner.V1_1.Constants.FrontendStatusTypeExt1_1.BERS;
+ /**
+ * Coderate Type. Only supported in Tuner HAL 1.1 or higher.
+ */
+ public static final int FRONTEND_STATUS_TYPE_CODERATES =
+ android.hardware.tv.tuner.V1_1.Constants.FrontendStatusTypeExt1_1.CODERATES;
+ /**
+ * Bandwidth Type. Only supported in Tuner HAL 1.1 or higher.
+ */
+ public static final int FRONTEND_STATUS_TYPE_BANDWIDTH =
+ android.hardware.tv.tuner.V1_1.Constants.FrontendStatusTypeExt1_1.BANDWIDTH;
+ /**
+ * Guard Interval Type. Only supported in Tuner HAL 1.1 or higher.
+ */
+ public static final int FRONTEND_STATUS_TYPE_GUARD_INTERVAL =
+ android.hardware.tv.tuner.V1_1.Constants.FrontendStatusTypeExt1_1.GUARD_INTERVAL;
+ /**
+ * Transmission Mode Type. Only supported in Tuner HAL 1.1 or higher.
+ */
+ public static final int FRONTEND_STATUS_TYPE_TRANSMISSION_MODE =
+ android.hardware.tv.tuner.V1_1.Constants.FrontendStatusTypeExt1_1.TRANSMISSION_MODE;
+ /**
+ * UEC Type. Only supported in Tuner HAL 1.1 or higher.
+ */
+ public static final int FRONTEND_STATUS_TYPE_UEC =
+ android.hardware.tv.tuner.V1_1.Constants.FrontendStatusTypeExt1_1.UEC;
+ /**
+ * T2 System Id Type. Only supported in Tuner HAL 1.1 or higher.
+ */
+ public static final int FRONTEND_STATUS_TYPE_T2_SYSTEM_ID =
+ android.hardware.tv.tuner.V1_1.Constants.FrontendStatusTypeExt1_1.T2_SYSTEM_ID;
+ /**
+ * Interleavings Type. Only supported in Tuner HAL 1.1 or higher.
+ */
+ public static final int FRONTEND_STATUS_TYPE_INTERLEAVINGS =
+ android.hardware.tv.tuner.V1_1.Constants.FrontendStatusTypeExt1_1.INTERLEAVINGS;
+ /**
+ * ISDBT Segments Type. Only supported in Tuner HAL 1.1 or higher.
+ */
+ public static final int FRONTEND_STATUS_TYPE_ISDBT_SEGMENTS =
+ android.hardware.tv.tuner.V1_1.Constants.FrontendStatusTypeExt1_1.ISDBT_SEGMENTS;
+ /**
+ * TS Data Rates Type. Only supported in Tuner HAL 1.1 or higher.
+ */
+ public static final int FRONTEND_STATUS_TYPE_TS_DATA_RATES =
+ android.hardware.tv.tuner.V1_1.Constants.FrontendStatusTypeExt1_1.TS_DATA_RATES;
+ /**
+ * Extended Modulations Type. Only supported in Tuner HAL 1.1 or higher.
+ */
+ public static final int FRONTEND_STATUS_TYPE_MODULATIONS_EXT =
+ android.hardware.tv.tuner.V1_1.Constants.FrontendStatusTypeExt1_1.MODULATIONS;
/** @hide */
@IntDef(value = {
+ AtscFrontendSettings.MODULATION_UNDEFINED,
+ AtscFrontendSettings.MODULATION_AUTO,
+ AtscFrontendSettings.MODULATION_MOD_8VSB,
+ AtscFrontendSettings.MODULATION_MOD_16VSB,
+ Atsc3FrontendSettings.MODULATION_UNDEFINED,
+ Atsc3FrontendSettings.MODULATION_AUTO,
+ Atsc3FrontendSettings.MODULATION_MOD_QPSK,
+ Atsc3FrontendSettings.MODULATION_MOD_16QAM,
+ Atsc3FrontendSettings.MODULATION_MOD_64QAM,
+ Atsc3FrontendSettings.MODULATION_MOD_256QAM,
+ Atsc3FrontendSettings.MODULATION_MOD_1024QAM,
+ Atsc3FrontendSettings.MODULATION_MOD_4096QAM,
+ DtmbFrontendSettings.MODULATION_CONSTELLATION_UNDEFINED,
+ DtmbFrontendSettings.MODULATION_CONSTELLATION_AUTO,
+ DtmbFrontendSettings.MODULATION_CONSTELLATION_4QAM,
+ DtmbFrontendSettings.MODULATION_CONSTELLATION_4QAM_NR,
+ DtmbFrontendSettings.MODULATION_CONSTELLATION_16QAM,
+ DtmbFrontendSettings.MODULATION_CONSTELLATION_32QAM,
+ DtmbFrontendSettings.MODULATION_CONSTELLATION_64QAM,
DvbcFrontendSettings.MODULATION_UNDEFINED,
DvbcFrontendSettings.MODULATION_AUTO,
DvbcFrontendSettings.MODULATION_MOD_16QAM,
@@ -171,6 +251,16 @@ public class FrontendStatus {
DvbsFrontendSettings.MODULATION_MOD_128APSK,
DvbsFrontendSettings.MODULATION_MOD_256APSK,
DvbsFrontendSettings.MODULATION_MOD_RESERVED,
+ DvbtFrontendSettings.CONSTELLATION_UNDEFINED,
+ DvbtFrontendSettings.CONSTELLATION_AUTO,
+ DvbtFrontendSettings.CONSTELLATION_QPSK,
+ DvbtFrontendSettings.CONSTELLATION_16QAM,
+ DvbtFrontendSettings.CONSTELLATION_64QAM,
+ DvbtFrontendSettings.CONSTELLATION_256QAM,
+ DvbtFrontendSettings.CONSTELLATION_QPSK_R,
+ DvbtFrontendSettings.CONSTELLATION_16QAM_R,
+ DvbtFrontendSettings.CONSTELLATION_64QAM_R,
+ DvbtFrontendSettings.CONSTELLATION_256QAM_R,
IsdbsFrontendSettings.MODULATION_UNDEFINED,
IsdbsFrontendSettings.MODULATION_AUTO,
IsdbsFrontendSettings.MODULATION_MOD_BPSK,
@@ -192,6 +282,101 @@ public class FrontendStatus {
@Retention(RetentionPolicy.SOURCE)
public @interface FrontendModulation {}
+ /** @hide */
+ @IntDef(value = {
+ Atsc3FrontendSettings.TIME_INTERLEAVE_MODE_UNDEFINED,
+ Atsc3FrontendSettings.TIME_INTERLEAVE_MODE_AUTO,
+ Atsc3FrontendSettings.TIME_INTERLEAVE_MODE_CTI,
+ Atsc3FrontendSettings.TIME_INTERLEAVE_MODE_HTI,
+ DtmbFrontendSettings.TIME_INTERLEAVE_MODE_UNDEFINED,
+ DtmbFrontendSettings.TIME_INTERLEAVE_MODE_AUTO,
+ DtmbFrontendSettings.TIME_INTERLEAVE_MODE_TIMER_INT_240,
+ DtmbFrontendSettings.TIME_INTERLEAVE_MODE_TIMER_INT_720,
+ DvbcFrontendSettings.TIME_INTERLEAVE_MODE_UNDEFINED,
+ DvbcFrontendSettings.TIME_INTERLEAVE_MODE_AUTO,
+ DvbcFrontendSettings.TIME_INTERLEAVE_MODE_128_1_0,
+ DvbcFrontendSettings.TIME_INTERLEAVE_MODE_128_1_1,
+ DvbcFrontendSettings.TIME_INTERLEAVE_MODE_64_2,
+ DvbcFrontendSettings.TIME_INTERLEAVE_MODE_32_4,
+ DvbcFrontendSettings.TIME_INTERLEAVE_MODE_16_8,
+ DvbcFrontendSettings.TIME_INTERLEAVE_MODE_8_16,
+ DvbcFrontendSettings.TIME_INTERLEAVE_MODE_128_2,
+ DvbcFrontendSettings.TIME_INTERLEAVE_MODE_128_3,
+ DvbcFrontendSettings.TIME_INTERLEAVE_MODE_128_4})
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface FrontendInterleaveMode {}
+
+ /** @hide */
+ @IntDef(value = {
+ Atsc3FrontendSettings.BANDWIDTH_UNDEFINED,
+ Atsc3FrontendSettings.BANDWIDTH_AUTO,
+ Atsc3FrontendSettings.BANDWIDTH_BANDWIDTH_6MHZ,
+ Atsc3FrontendSettings.BANDWIDTH_BANDWIDTH_7MHZ,
+ Atsc3FrontendSettings.BANDWIDTH_BANDWIDTH_8MHZ,
+ DtmbFrontendSettings.BANDWIDTH_UNDEFINED,
+ DtmbFrontendSettings.BANDWIDTH_AUTO,
+ DtmbFrontendSettings.BANDWIDTH_6MHZ,
+ DtmbFrontendSettings.BANDWIDTH_8MHZ,
+ DvbtFrontendSettings.BANDWIDTH_UNDEFINED,
+ DvbtFrontendSettings.BANDWIDTH_AUTO,
+ DvbtFrontendSettings.BANDWIDTH_8MHZ,
+ DvbtFrontendSettings.BANDWIDTH_7MHZ,
+ DvbtFrontendSettings.BANDWIDTH_6MHZ,
+ DvbtFrontendSettings.BANDWIDTH_5MHZ,
+ DvbtFrontendSettings.BANDWIDTH_1_7MHZ,
+ DvbtFrontendSettings.BANDWIDTH_10MHZ,
+ IsdbtFrontendSettings.BANDWIDTH_UNDEFINED,
+ IsdbtFrontendSettings.BANDWIDTH_AUTO,
+ IsdbtFrontendSettings.BANDWIDTH_8MHZ,
+ IsdbtFrontendSettings.BANDWIDTH_7MHZ,
+ IsdbtFrontendSettings.BANDWIDTH_6MHZ})
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface FrontendBandwidth {}
+
+ /** @hide */
+ @IntDef(value = {
+ DtmbFrontendSettings.TRANSMISSION_MODE_UNDEFINED,
+ DtmbFrontendSettings.TRANSMISSION_MODE_AUTO,
+ DtmbFrontendSettings.TRANSMISSION_MODE_C1,
+ DtmbFrontendSettings.TRANSMISSION_MODE_C3780,
+ DvbtFrontendSettings.TRANSMISSION_MODE_UNDEFINED,
+ DvbtFrontendSettings.TRANSMISSION_MODE_AUTO,
+ DvbtFrontendSettings.TRANSMISSION_MODE_2K,
+ DvbtFrontendSettings.TRANSMISSION_MODE_8K,
+ DvbtFrontendSettings.TRANSMISSION_MODE_4K,
+ DvbtFrontendSettings.TRANSMISSION_MODE_1K,
+ DvbtFrontendSettings.TRANSMISSION_MODE_16K,
+ DvbtFrontendSettings.TRANSMISSION_MODE_32K,
+ IsdbtFrontendSettings.MODE_UNDEFINED,
+ IsdbtFrontendSettings.MODE_AUTO,
+ IsdbtFrontendSettings.MODE_1,
+ IsdbtFrontendSettings.MODE_2,
+ IsdbtFrontendSettings.MODE_3})
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface FrontendTransmissionMode {}
+
+ /** @hide */
+ @IntDef(value = {
+ DtmbFrontendSettings.GUARD_INTERVAL_UNDEFINED,
+ DtmbFrontendSettings.GUARD_INTERVAL_AUTO,
+ DtmbFrontendSettings.GUARD_INTERVAL_PN_420_VARIOUS,
+ DtmbFrontendSettings.GUARD_INTERVAL_PN_595_CONST,
+ DtmbFrontendSettings.GUARD_INTERVAL_PN_945_VARIOUS,
+ DtmbFrontendSettings.GUARD_INTERVAL_PN_420_CONST,
+ DtmbFrontendSettings.GUARD_INTERVAL_PN_945_CONST,
+ DtmbFrontendSettings.GUARD_INTERVAL_PN_RESERVED,
+ DvbtFrontendSettings.GUARD_INTERVAL_UNDEFINED,
+ DvbtFrontendSettings.GUARD_INTERVAL_AUTO,
+ DvbtFrontendSettings.GUARD_INTERVAL_1_32,
+ DvbtFrontendSettings.GUARD_INTERVAL_1_16,
+ DvbtFrontendSettings.GUARD_INTERVAL_1_8,
+ DvbtFrontendSettings.GUARD_INTERVAL_1_4,
+ DvbtFrontendSettings.GUARD_INTERVAL_1_128,
+ DvbtFrontendSettings.GUARD_INTERVAL_19_128,
+ DvbtFrontendSettings.GUARD_INTERVAL_19_256,
+ DvbtFrontendSettings.GUARD_INTERVAL_19_128})
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface FrontendGuardInterval {}
private Boolean mIsDemodLocked;
private Integer mSnr;
@@ -215,6 +400,18 @@ public class FrontendStatus {
private Integer mHierarchy;
private Boolean mIsRfLocked;
private Atsc3PlpTuningInfo[] mPlpInfo;
+ private int[] mBers;
+ private int[] mCodeRates;
+ private Integer mBandwidth;
+ private Integer mGuardInterval;
+ private Integer mTransmissionMode;
+ private Integer mUec;
+ private Integer mSystemId;
+ private int[] mInterleaving;
+ private int[] mTsDataRate;
+ private int[] mIsdbtSegment;
+ private int[] mModulationsExt;
+
// Constructed and fields set by JNI code.
private FrontendStatus() {
@@ -323,7 +520,7 @@ public class FrontendStatus {
/**
* Gets Spectral Inversion for DVBC.
*/
- @DvbcFrontendSettings.SpectralInversion
+ @FrontendSettings.FrontendSpectralInversion
public int getSpectralInversion() {
if (mInversion == null) {
throw new IllegalStateException();
@@ -437,6 +634,182 @@ public class FrontendStatus {
}
/**
+ * Gets an array of BERS status.
+ *
+ * <p>This status query is only supported by Tuner HAL 1.1 or higher. Use
+ * {@link TunerVersionChecker.getTunerVersion()} to check the version.
+ */
+ @NonNull
+ public int[] getBers() {
+ TunerVersionChecker.checkHigherOrEqualVersionTo(
+ TunerVersionChecker.TUNER_VERSION_1_1, "getBers status");
+ if (mBers == null) {
+ throw new IllegalStateException();
+ }
+ return mBers;
+ }
+
+ /**
+ * Gets an array of code rates status.
+ *
+ * <p>This status query is only supported by Tuner HAL 1.1 or higher. Use
+ * {@link TunerVersionChecker.getTunerVersion()} to check the version.
+ */
+ @NonNull
+ public int[] getCodeRates() {
+ TunerVersionChecker.checkHigherOrEqualVersionTo(
+ TunerVersionChecker.TUNER_VERSION_1_1, "getCodeRates status");
+ if (mCodeRates == null) {
+ throw new IllegalStateException();
+ }
+ return mCodeRates;
+ }
+
+ /**
+ * Gets bandwidth status.
+ *
+ * <p>This status query is only supported by Tuner HAL 1.1 or higher. Use
+ * {@link TunerVersionChecker.getTunerVersion()} to check the version.
+ */
+ @FrontendBandwidth
+ public int getBandwidth() {
+ TunerVersionChecker.checkHigherOrEqualVersionTo(
+ TunerVersionChecker.TUNER_VERSION_1_1, "getBandwidth status");
+ if (mBandwidth == null) {
+ throw new IllegalStateException();
+ }
+ return mBandwidth;
+ }
+
+ /**
+ * Gets guard interval status.
+ *
+ * <p>This status query is only supported by Tuner HAL 1.1 or higher. Use
+ * {@link TunerVersionChecker.getTunerVersion()} to check the version.
+ */
+ @FrontendGuardInterval
+ public int getGuardInterval() {
+ TunerVersionChecker.checkHigherOrEqualVersionTo(
+ TunerVersionChecker.TUNER_VERSION_1_1, "getGuardInterval status");
+ if (mGuardInterval == null) {
+ throw new IllegalStateException();
+ }
+ return mGuardInterval;
+ }
+
+ /**
+ * Gets tansmission mode status.
+ *
+ * <p>This status query is only supported by Tuner HAL 1.1 or higher. Use
+ * {@link TunerVersionChecker.getTunerVersion()} to check the version.
+ */
+ @FrontendTransmissionMode
+ public int getTransmissionMode() {
+ TunerVersionChecker.checkHigherOrEqualVersionTo(
+ TunerVersionChecker.TUNER_VERSION_1_1, "getTransmissionMode status");
+ if (mTransmissionMode == null) {
+ throw new IllegalStateException();
+ }
+ return mTransmissionMode;
+ }
+
+ /**
+ * Gets UEC status.
+ *
+ * <p>This status query is only supported by Tuner HAL 1.1 or higher. Use
+ * {@link TunerVersionChecker.getTunerVersion()} to check the version.
+ */
+ public int getUec() {
+ TunerVersionChecker.checkHigherOrEqualVersionTo(
+ TunerVersionChecker.TUNER_VERSION_1_1, "getUec status");
+ if (mUec == null) {
+ throw new IllegalStateException();
+ }
+ return mUec;
+ }
+
+ /**
+ * Gets system id status.
+ *
+ * <p>This status query is only supported by Tuner HAL 1.1 or higher. Use
+ * {@link TunerVersionChecker.getTunerVersion()} to check the version.
+ */
+ public int getSystemId() {
+ TunerVersionChecker.checkHigherOrEqualVersionTo(
+ TunerVersionChecker.TUNER_VERSION_1_1, "getSystemId status");
+ if (mSystemId == null) {
+ throw new IllegalStateException();
+ }
+ return mSystemId;
+ }
+
+ /**
+ * Gets an array of interleaving status. Array value should be withink {@link
+ * FrontendInterleaveMode}.
+ *
+ * <p>This status query is only supported by Tuner HAL 1.1 or higher. Use
+ * {@link TunerVersionChecker.getTunerVersion()} to check the version.
+ */
+ @NonNull
+ public int[] getInterleaving() {
+ TunerVersionChecker.checkHigherOrEqualVersionTo(
+ TunerVersionChecker.TUNER_VERSION_1_1, "getInterleaving status");
+ if (mInterleaving == null) {
+ throw new IllegalStateException();
+ }
+ return mInterleaving;
+ }
+
+ /**
+ * Gets an array of isdbt segment status.
+ *
+ * <p>This status query is only supported by Tuner HAL 1.1 or higher. Use
+ * {@link TunerVersionChecker.getTunerVersion()} to check the version.
+ */
+ @NonNull
+ public int[] getIsdbtSegment() {
+ TunerVersionChecker.checkHigherOrEqualVersionTo(
+ TunerVersionChecker.TUNER_VERSION_1_1, "getIsdbtSegment status");
+ if (mIsdbtSegment == null) {
+ throw new IllegalStateException();
+ }
+ return mIsdbtSegment;
+ }
+
+ /**
+ * Gets an array of TS data rate status.
+ *
+ * <p>This status query is only supported by Tuner HAL 1.1 or higher. Use
+ * {@link TunerVersionChecker.getTunerVersion()} to check the version.
+ */
+ @NonNull
+ public int[] getTsDataRate() {
+ TunerVersionChecker.checkHigherOrEqualVersionTo(
+ TunerVersionChecker.TUNER_VERSION_1_1, "getTsDataRate status");
+ if (mTsDataRate == null) {
+ throw new IllegalStateException();
+ }
+ return mTsDataRate;
+ }
+
+ /**
+ * Gets an array of the extended modulations status. Array value should be withink {@link
+ * FrontendModulation}.
+ *
+ * <p>This status query is only supported by Tuner HAL 1.1 or higher. Use
+ * {@link TunerVersionChecker.getTunerVersion()} to check the version.
+ */
+ @NonNull
+ public int[] getModulationsExt() {
+ TunerVersionChecker.checkHigherOrEqualVersionTo(
+ TunerVersionChecker.TUNER_VERSION_1_1, "getModulationsExt status");
+ if (mModulationsExt == null) {
+ throw new IllegalStateException();
+ }
+ return mModulationsExt;
+ }
+
+ /**
* Status for each tuning Physical Layer Pipes.
*/
public static class Atsc3PlpTuningInfo {
diff --git a/media/java/android/media/tv/tuner/frontend/ScanCallback.java b/media/java/android/media/tv/tuner/frontend/ScanCallback.java
index b0491fdbde1a..9bf7a5dd40cb 100644
--- a/media/java/android/media/tv/tuner/frontend/ScanCallback.java
+++ b/media/java/android/media/tv/tuner/frontend/ScanCallback.java
@@ -70,4 +70,9 @@ public interface ScanCallback {
/** Frontend signal type. */
void onSignalTypeReported(@AnalogFrontendSettings.SignalType int signalType);
+ /** Frontend modulation reported. */
+ default void onModulationReported(@FrontendStatus.FrontendModulation int modulation) {}
+
+ /** Frontend scan message priority reported. */
+ default void onPriorityReported(boolean isHighPriority) {}
}
diff --git a/media/jni/android_media_MediaMetadataRetriever.cpp b/media/jni/android_media_MediaMetadataRetriever.cpp
index 6fbd29cb8623..126897a908f8 100644
--- a/media/jni/android_media_MediaMetadataRetriever.cpp
+++ b/media/jni/android_media_MediaMetadataRetriever.cpp
@@ -704,7 +704,7 @@ static const JNINativeMethod nativeMethods[] = {
(void *)android_media_MediaMetadataRetriever_setDataSourceAndHeaders
},
- {"setDataSource", "(Ljava/io/FileDescriptor;JJ)V",
+ {"_setDataSource", "(Ljava/io/FileDescriptor;JJ)V",
(void *)android_media_MediaMetadataRetriever_setDataSourceFD},
{"_setDataSource", "(Landroid/media/MediaDataSource;)V",
(void *)android_media_MediaMetadataRetriever_setDataSourceCallback},
diff --git a/media/jni/android_media_tv_Tuner.cpp b/media/jni/android_media_tv_Tuner.cpp
index 6a1acede029f..1be0d4439e69 100644
--- a/media/jni/android_media_tv_Tuner.cpp
+++ b/media/jni/android_media_tv_Tuner.cpp
@@ -132,10 +132,13 @@ using ::android::hardware::tv::tuner::V1_0::LnbTone;
using ::android::hardware::tv::tuner::V1_0::LnbVoltage;
using ::android::hardware::tv::tuner::V1_0::PlaybackSettings;
using ::android::hardware::tv::tuner::V1_0::RecordSettings;
+using ::android::hardware::tv::tuner::V1_1::AudioStreamType;
+using ::android::hardware::tv::tuner::V1_1::AvStreamType;
using ::android::hardware::tv::tuner::V1_1::Constant;
using ::android::hardware::tv::tuner::V1_1::Constant64Bit;
using ::android::hardware::tv::tuner::V1_1::FrontendAnalogAftFlag;
using ::android::hardware::tv::tuner::V1_1::FrontendAnalogSettingsExt1_1;
+using ::android::hardware::tv::tuner::V1_1::FrontendBandwidth;
using ::android::hardware::tv::tuner::V1_1::FrontendCableTimeInterleaveMode;
using ::android::hardware::tv::tuner::V1_1::FrontendDvbsScanType;
using ::android::hardware::tv::tuner::V1_1::FrontendDvbcSettingsExt1_1;
@@ -149,7 +152,14 @@ using ::android::hardware::tv::tuner::V1_1::FrontendDtmbModulation;
using ::android::hardware::tv::tuner::V1_1::FrontendDtmbSettings;
using ::android::hardware::tv::tuner::V1_1::FrontendDtmbTimeInterleaveMode;
using ::android::hardware::tv::tuner::V1_1::FrontendDtmbTransmissionMode;
+using ::android::hardware::tv::tuner::V1_1::FrontendGuardInterval;
+using ::android::hardware::tv::tuner::V1_1::FrontendInterleaveMode;
+using ::android::hardware::tv::tuner::V1_1::FrontendModulation;
using ::android::hardware::tv::tuner::V1_1::FrontendSpectralInversion;
+using ::android::hardware::tv::tuner::V1_1::FrontendStatusExt1_1;
+using ::android::hardware::tv::tuner::V1_1::FrontendStatusTypeExt1_1;
+using ::android::hardware::tv::tuner::V1_1::FrontendTransmissionMode;
+using ::android::hardware::tv::tuner::V1_1::VideoStreamType;
struct fields_t {
jfieldID tunerContext;
@@ -986,6 +996,77 @@ Return<void> FrontendCallback::onScanMessage(FrontendScanMessageType type, const
return Void();
}
+Return<void> FrontendCallback::onScanMessageExt1_1(FrontendScanMessageTypeExt1_1 type,
+ const FrontendScanMessageExt1_1& message) {
+ ALOGD("FrontendCallback::onScanMessageExt1_1, type=%d", type);
+ JNIEnv *env = AndroidRuntime::getJNIEnv();
+ jclass clazz = env->FindClass("android/media/tv/tuner/Tuner");
+ switch(type) {
+ case FrontendScanMessageTypeExt1_1::MODULATION: {
+ jint modulation = -1;
+ switch (message.modulation().getDiscriminator()) {
+ case FrontendModulation::hidl_discriminator::dvbc: {
+ modulation = (jint) message.modulation().dvbc();
+ break;
+ }
+ case FrontendModulation::hidl_discriminator::dvbt: {
+ modulation = (jint) message.modulation().dvbt();
+ break;
+ }
+ case FrontendModulation::hidl_discriminator::dvbs: {
+ modulation = (jint) message.modulation().dvbs();
+ break;
+ }
+ case FrontendModulation::hidl_discriminator::isdbs: {
+ modulation = (jint) message.modulation().isdbs();
+ break;
+ }
+ case FrontendModulation::hidl_discriminator::isdbs3: {
+ modulation = (jint) message.modulation().isdbs3();
+ break;
+ }
+ case FrontendModulation::hidl_discriminator::isdbt: {
+ modulation = (jint) message.modulation().isdbt();
+ break;
+ }
+ case FrontendModulation::hidl_discriminator::atsc: {
+ modulation = (jint) message.modulation().atsc();
+ break;
+ }
+ case FrontendModulation::hidl_discriminator::atsc3: {
+ modulation = (jint) message.modulation().atsc3();
+ break;
+ }
+ case FrontendModulation::hidl_discriminator::dtmb: {
+ modulation = (jint) message.modulation().dtmb();
+ break;
+ }
+ default: {
+ break;
+ }
+ }
+ if (modulation > 0) {
+ env->CallVoidMethod(
+ mObject,
+ env->GetMethodID(clazz, "onModulationReported", "(I)V"),
+ modulation);
+ }
+ break;
+ }
+ case FrontendScanMessageTypeExt1_1::HIGH_PRIORITY: {
+ bool isHighPriority = message.isHighPriority();
+ env->CallVoidMethod(
+ mObject,
+ env->GetMethodID(clazz, "onPriorityReported", "([B)V"),
+ isHighPriority);
+ break;
+ }
+ default:
+ break;
+ }
+ return Void();
+}
+
/////////////// Tuner ///////////////////////
sp<ITuner> JTuner::mTuner;
@@ -1862,18 +1943,49 @@ jobject JTuner::getFrontendStatus(jintArray types) {
}
JNIEnv *env = AndroidRuntime::getJNIEnv();
jsize size = env->GetArrayLength(types);
- std::vector<FrontendStatusType> v(size);
- env->GetIntArrayRegion(types, 0, size, reinterpret_cast<jint*>(&v[0]));
+ jint intTypes[size];
+ env->GetIntArrayRegion(types, 0, size, intTypes);
+ std::vector<FrontendStatusType> v;
+ std::vector<FrontendStatusTypeExt1_1> v_1_1;
+ for (int i = 0; i < size; i++) {
+ if (isV1_1ExtendedStatusType(intTypes[i])) {
+ v_1_1.push_back(static_cast<FrontendStatusTypeExt1_1>(intTypes[i]));
+ } else {
+ v.push_back(static_cast<FrontendStatusType>(intTypes[i]));
+ }
+ }
Result res;
hidl_vec<FrontendStatus> status;
- mFe->getStatus(v,
- [&](Result r, const hidl_vec<FrontendStatus>& s) {
- res = r;
- status = s;
- });
- if (res != Result::SUCCESS) {
- return NULL;
+ hidl_vec<FrontendStatusExt1_1> status_1_1;
+
+ if (v.size() > 0) {
+ mFe->getStatus(v,
+ [&](Result r, const hidl_vec<FrontendStatus>& s) {
+ res = r;
+ status = s;
+ });
+ if (res != Result::SUCCESS) {
+ return NULL;
+ }
+ }
+
+ if (v_1_1.size() > 0) {
+ sp<::android::hardware::tv::tuner::V1_1::IFrontend> iFeSp_1_1;
+ iFeSp_1_1 = ::android::hardware::tv::tuner::V1_1::IFrontend::castFrom(mFe);
+
+ if (iFeSp_1_1 != NULL) {
+ iFeSp_1_1->getStatusExt1_1(v_1_1,
+ [&](Result r, const hidl_vec<FrontendStatusExt1_1>& s) {
+ res = r;
+ status_1_1 = s;
+ });
+ if (res != Result::SUCCESS) {
+ return NULL;
+ }
+ } else {
+ ALOGW("getStatusExt1_1 is not supported with the current HAL implementation.");
+ }
}
jclass clazz = env->FindClass("android/media/tv/tuner/frontend/FrontendStatus");
@@ -2101,9 +2213,274 @@ jobject JTuner::getFrontendStatus(jintArray types) {
}
}
+ for (auto s : status_1_1) {
+ switch(s.getDiscriminator()) {
+ case FrontendStatusExt1_1::hidl_discriminator::modulations: {
+ jfieldID field = env->GetFieldID(clazz, "mModulationsExt", "[I");
+ std::vector<FrontendModulation> v = s.modulations();
+
+ jintArray valObj = env->NewIntArray(v.size());
+ bool valid = false;
+ jint m[1];
+ for (int i = 0; i < v.size(); i++) {
+ auto modulation = v[i];
+ switch(modulation.getDiscriminator()) {
+ case FrontendModulation::hidl_discriminator::dvbc: {
+ m[0] = static_cast<jint>(modulation.dvbc());
+ env->SetIntArrayRegion(valObj, i, 1, m);
+ valid = true;
+ break;
+ }
+ case FrontendModulation::hidl_discriminator::dvbs: {
+ m[0] = static_cast<jint>(modulation.dvbs());
+ env->SetIntArrayRegion(valObj, i, 1, m);
+ valid = true;
+ break;
+ }
+ case FrontendModulation::hidl_discriminator::dvbt: {
+ m[0] = static_cast<jint>(modulation.dvbt());
+ env->SetIntArrayRegion(valObj, i, 1, m);
+ valid = true;
+ break;
+ }
+ case FrontendModulation::hidl_discriminator::isdbs: {
+ m[0] = static_cast<jint>(modulation.isdbs());
+ env->SetIntArrayRegion(valObj, i, 1, m);
+ valid = true;
+ break;
+ }
+ case FrontendModulation::hidl_discriminator::isdbs3: {
+ m[0] = static_cast<jint>(modulation.isdbs3());
+ env->SetIntArrayRegion(valObj, i, 1, m);
+ valid = true;
+ break;
+ }
+ case FrontendModulation::hidl_discriminator::isdbt: {
+ m[0] = static_cast<jint>(modulation.isdbt());
+ env->SetIntArrayRegion(valObj, i, 1, m);
+ valid = true;
+ break;
+ }
+ case FrontendModulation::hidl_discriminator::atsc: {
+ m[0] = static_cast<jint>(modulation.atsc());
+ env->SetIntArrayRegion(valObj, i, 1, m);
+ valid = true;
+ break;
+ }
+ case FrontendModulation::hidl_discriminator::atsc3: {
+ m[0] = static_cast<jint>(modulation.atsc3());
+ env->SetIntArrayRegion(valObj, i, 1, m);
+ valid = true;
+ break;
+ }
+ case FrontendModulation::hidl_discriminator::dtmb: {
+ m[0] = static_cast<jint>(modulation.dtmb());
+ env->SetIntArrayRegion(valObj, i, 1, m);
+ valid = true;
+ break;
+ }
+ default:
+ break;
+ }
+ }
+ if (valid) {
+ env->SetObjectField(statusObj, field, valObj);
+ }
+ break;
+ }
+ case FrontendStatusExt1_1::hidl_discriminator::bers: {
+ jfieldID field = env->GetFieldID(clazz, "mBers", "[I");
+ std::vector<uint32_t> v = s.bers();
+
+ jintArray valObj = env->NewIntArray(v.size());
+ env->SetIntArrayRegion(valObj, 0, v.size(), reinterpret_cast<jint*>(&v[0]));
+
+ env->SetObjectField(statusObj, field, valObj);
+ break;
+ }
+ case FrontendStatusExt1_1::hidl_discriminator::codeRates: {
+ jfieldID field = env->GetFieldID(clazz, "mCodeRates", "[I");
+ std::vector<::android::hardware::tv::tuner::V1_1::FrontendInnerFec> v
+ = s.codeRates();
+
+ jintArray valObj = env->NewIntArray(v.size());
+ env->SetIntArrayRegion(valObj, 0, v.size(), reinterpret_cast<jint*>(&v[0]));
+
+ env->SetObjectField(statusObj, field, valObj);
+ break;
+ }
+ case FrontendStatusExt1_1::hidl_discriminator::bandwidth: {
+ jfieldID field = env->GetFieldID(clazz, "mBandwidth", "Ljava/lang/Integer;");
+ auto bandwidth = s.bandwidth();
+ jint intBandwidth;
+ bool valid = true;
+ switch(bandwidth.getDiscriminator()) {
+ case FrontendBandwidth::hidl_discriminator::atsc3: {
+ intBandwidth = static_cast<jint>(bandwidth.atsc3());
+ break;
+ }
+ case FrontendBandwidth::hidl_discriminator::dvbt: {
+ intBandwidth = static_cast<jint>(bandwidth.dvbt());
+ break;
+ }
+ case FrontendBandwidth::hidl_discriminator::isdbt: {
+ intBandwidth = static_cast<jint>(bandwidth.isdbt());
+ break;
+ }
+ case FrontendBandwidth::hidl_discriminator::dtmb: {
+ intBandwidth = static_cast<jint>(bandwidth.dtmb());
+ break;
+ }
+ default:
+ valid = false;
+ break;
+ }
+ if (valid) {
+ jobject newIntegerObj = env->NewObject(intClazz, initInt, intBandwidth);
+ env->SetObjectField(statusObj, field, newIntegerObj);
+ }
+ break;
+ }
+ case FrontendStatusExt1_1::hidl_discriminator::interval: {
+ jfieldID field = env->GetFieldID(clazz, "mGuardInterval", "Ljava/lang/Integer;");
+ auto interval = s.interval();
+ jint intInterval;
+ bool valid = true;
+ switch(interval.getDiscriminator()) {
+ case FrontendGuardInterval::hidl_discriminator::dvbt: {
+ intInterval = static_cast<jint>(interval.dvbt());
+ break;
+ }
+ case FrontendGuardInterval::hidl_discriminator::isdbt: {
+ intInterval = static_cast<jint>(interval.isdbt());
+ break;
+ }
+ case FrontendGuardInterval::hidl_discriminator::dtmb: {
+ intInterval = static_cast<jint>(interval.dtmb());
+ break;
+ }
+ default:
+ valid = false;
+ break;
+ }
+ if (valid) {
+ jobject newIntegerObj = env->NewObject(intClazz, initInt, intInterval);
+ env->SetObjectField(statusObj, field, newIntegerObj);
+ }
+ break;
+ }
+ case FrontendStatusExt1_1::hidl_discriminator::transmissionMode: {
+ jfieldID field = env->GetFieldID(clazz, "mTransmissionMode", "Ljava/lang/Integer;");
+ auto transmissionMode = s.transmissionMode();
+ jint intTransmissionMode;
+ bool valid = true;
+ switch(transmissionMode.getDiscriminator()) {
+ case FrontendTransmissionMode::hidl_discriminator::dvbt: {
+ intTransmissionMode = static_cast<jint>(transmissionMode.dvbt());
+ break;
+ }
+ case FrontendTransmissionMode::hidl_discriminator::isdbt: {
+ intTransmissionMode = static_cast<jint>(transmissionMode.isdbt());
+ break;
+ }
+ case FrontendTransmissionMode::hidl_discriminator::dtmb: {
+ intTransmissionMode = static_cast<jint>(transmissionMode.dtmb());
+ break;
+ }
+ default:
+ valid = false;
+ break;
+ }
+ if (valid) {
+ jobject newIntegerObj = env->NewObject(intClazz, initInt, intTransmissionMode);
+ env->SetObjectField(statusObj, field, newIntegerObj);
+ }
+ break;
+ }
+ case FrontendStatusExt1_1::hidl_discriminator::uec: {
+ jfieldID field = env->GetFieldID(clazz, "mUec", "Ljava/lang/Integer;");
+ jobject newIntegerObj = env->NewObject(
+ intClazz, initInt, static_cast<jint>(s.uec()));
+ env->SetObjectField(statusObj, field, newIntegerObj);
+ break;
+ }
+ case FrontendStatusExt1_1::hidl_discriminator::systemId: {
+ jfieldID field = env->GetFieldID(clazz, "mSystemId", "Ljava/lang/Integer;");
+ jobject newIntegerObj = env->NewObject(
+ intClazz, initInt, static_cast<jint>(s.systemId()));
+ env->SetObjectField(statusObj, field, newIntegerObj);
+ break;
+ }
+ case FrontendStatusExt1_1::hidl_discriminator::interleaving: {
+ jfieldID field = env->GetFieldID(clazz, "mInterleaving", "[I");
+
+ std::vector<FrontendInterleaveMode> v = s.interleaving();
+ jintArray valObj = env->NewIntArray(v.size());
+ bool valid = false;
+ jint in[1];
+ for (int i = 0; i < v.size(); i++) {
+ auto interleaving = v[i];
+ switch(interleaving.getDiscriminator()) {
+ case FrontendInterleaveMode::hidl_discriminator::atsc3: {
+ in[0] = static_cast<jint>(interleaving.atsc3());
+ env->SetIntArrayRegion(valObj, i, 1, in);
+ valid = true;
+ break;
+ }
+ case FrontendInterleaveMode::hidl_discriminator::dvbc: {
+ in[0] = static_cast<jint>(interleaving.dvbc());
+ env->SetIntArrayRegion(valObj, i, 1, in);
+ valid = true;
+ break;
+ }
+ case FrontendInterleaveMode::hidl_discriminator::dtmb: {
+ in[0] = static_cast<jint>(interleaving.dtmb());
+ env->SetIntArrayRegion(valObj, i, 1, in);
+ valid = true;
+ break;
+ }
+ default:
+ break;
+ }
+ }
+ if (valid) {
+ env->SetObjectField(statusObj, field, valObj);
+ }
+ break;
+ }
+ case FrontendStatusExt1_1::hidl_discriminator::isdbtSegment: {
+ jfieldID field = env->GetFieldID(clazz, "mIsdbtSegment", "[I");
+ std::vector<uint8_t> v = s.isdbtSegment();
+
+ jintArray valObj = env->NewIntArray(v.size());
+ env->SetIntArrayRegion(valObj, 0, v.size(), reinterpret_cast<jint*>(&v[0]));
+
+ env->SetObjectField(statusObj, field, valObj);
+ break;
+ }
+ case FrontendStatusExt1_1::hidl_discriminator::tsDataRate: {
+ jfieldID field = env->GetFieldID(clazz, "mTsDataRate", "[I");
+ std::vector<uint32_t> v = s.tsDataRate();
+
+ jintArray valObj = env->NewIntArray(v.size());
+ env->SetIntArrayRegion(valObj, 0, v.size(), reinterpret_cast<jint*>(&v[0]));
+
+ env->SetObjectField(statusObj, field, valObj);
+ break;
+ }
+ default: {
+ break;
+ }
+ }
+ }
return statusObj;
}
+bool JTuner::isV1_1ExtendedStatusType(int type) {
+ return (type > static_cast<int>(FrontendStatusType::ATSC3_PLP_INFO)
+ && type <= static_cast<int>(FrontendStatusTypeExt1_1::TS_DATA_RATES));
+}
+
jint JTuner::closeFrontend() {
Result r = Result::SUCCESS;
if (mFe != NULL) {
@@ -3114,6 +3491,31 @@ static DemuxFilterAvSettings getFilterAvSettings(JNIEnv *env, const jobject& set
return filterAvSettings;
}
+static bool getAvStreamType(JNIEnv *env, jobject filterConfigObj, AvStreamType& type) {
+ jobject settingsObj =
+ env->GetObjectField(
+ filterConfigObj,
+ env->GetFieldID(
+ env->FindClass("android/media/tv/tuner/filter/FilterConfiguration"),
+ "mSettings",
+ "Landroid/media/tv/tuner/filter/Settings;"));
+ jclass clazz = env->FindClass("android/media/tv/tuner/filter/AvSettings");
+ AvStreamType streamType;
+ AudioStreamType audioStreamType = static_cast<AudioStreamType>(
+ env->GetIntField(settingsObj, env->GetFieldID(clazz, "mAudioStreamType", "I")));
+ if (audioStreamType != AudioStreamType::UNDEFINED) {
+ type.audio(audioStreamType);
+ return true;
+ }
+ VideoStreamType videoStreamType = static_cast<VideoStreamType>(
+ env->GetIntField(settingsObj, env->GetFieldID(clazz, "mVideoStreamType", "I")));
+ if (videoStreamType != VideoStreamType::UNDEFINED) {
+ type.video(videoStreamType);
+ return true;
+ }
+ return false;
+}
+
static DemuxFilterPesDataSettings getFilterPesDataSettings(JNIEnv *env, const jobject& settings) {
jclass clazz = env->FindClass("android/media/tv/tuner/filter/PesSettings");
uint16_t streamId = static_cast<uint16_t>(
@@ -3436,6 +3838,16 @@ static jint copyData(JNIEnv *env, std::unique_ptr<MQ>& mq, EventFlag* flag, jbyt
return size;
}
+static bool isAvFilterSettings(DemuxFilterSettings filterSettings) {
+ return (filterSettings.getDiscriminator() == DemuxFilterSettings::hidl_discriminator::ts
+ && filterSettings.ts().filterSettings.getDiscriminator()
+ == DemuxTsFilterSettings::FilterSettings::hidl_discriminator::av)
+ ||
+ (filterSettings.getDiscriminator() == DemuxFilterSettings::hidl_discriminator::mmtp
+ && filterSettings.mmtp().filterSettings.getDiscriminator()
+ == DemuxMmtpFilterSettings::FilterSettings::hidl_discriminator::av);
+}
+
static jint android_media_tv_Tuner_configure_filter(
JNIEnv *env, jobject filter, int type, int subtype, jobject settings) {
ALOGD("configure filter type=%d, subtype=%d", type, subtype);
@@ -3459,6 +3871,20 @@ static jint android_media_tv_Tuner_configure_filter(
}
}
+ AvStreamType streamType;
+ if (isAvFilterSettings(filterSettings) && getAvStreamType(env, settings, streamType)) {
+ sp<::android::hardware::tv::tuner::V1_1::IFilter> iFilterSp_1_1;
+ iFilterSp_1_1 = ::android::hardware::tv::tuner::V1_1::IFilter::castFrom(iFilterSp);
+ if (iFilterSp_1_1 != NULL) {
+ res = iFilterSp_1_1->configureAvStreamType(streamType);
+ } else {
+ ALOGW("configureAvStreamType is not supported with the current HAL implementation.");
+ }
+ if (res != Result::SUCCESS) {
+ return (jint) res;
+ }
+ }
+
MQDescriptorSync<uint8_t> filterMQDesc;
Result getQueueDescResult = Result::UNKNOWN_ERROR;
if (filterSp->mFilterMQ == NULL) {
diff --git a/media/jni/android_media_tv_Tuner.h b/media/jni/android_media_tv_Tuner.h
index 2b73f312be05..71d2983b7c51 100644
--- a/media/jni/android_media_tv_Tuner.h
+++ b/media/jni/android_media_tv_Tuner.h
@@ -20,6 +20,7 @@
#include <android/hardware/tv/tuner/1.1/IFilter.h>
#include <android/hardware/tv/tuner/1.1/IFilterCallback.h>
#include <android/hardware/tv/tuner/1.1/IFrontend.h>
+#include <android/hardware/tv/tuner/1.1/IFrontendCallback.h>
#include <android/hardware/tv/tuner/1.1/ITuner.h>
#include <android/hardware/tv/tuner/1.1/types.h>
@@ -63,7 +64,6 @@ using ::android::hardware::tv::tuner::V1_0::IDvrCallback;
using ::android::hardware::tv::tuner::V1_0::IFilter;
using ::android::hardware::tv::tuner::V1_1::IFilterCallback;
using ::android::hardware::tv::tuner::V1_0::IFrontend;
-using ::android::hardware::tv::tuner::V1_0::IFrontendCallback;
using ::android::hardware::tv::tuner::V1_0::ILnb;
using ::android::hardware::tv::tuner::V1_0::ILnbCallback;
using ::android::hardware::tv::tuner::V1_0::ITimeFilter;
@@ -73,6 +73,9 @@ using ::android::hardware::tv::tuner::V1_0::LnbId;
using ::android::hardware::tv::tuner::V1_0::PlaybackStatus;
using ::android::hardware::tv::tuner::V1_0::RecordStatus;
using ::android::hardware::tv::tuner::V1_0::Result;
+using ::android::hardware::tv::tuner::V1_1::FrontendScanMessageExt1_1;
+using ::android::hardware::tv::tuner::V1_1::FrontendScanMessageTypeExt1_1;
+using ::android::hardware::tv::tuner::V1_1::IFrontendCallback;
using MQ = MessageQueue<uint8_t, kSynchronizedReadWrite>;
@@ -191,6 +194,8 @@ struct FrontendCallback : public IFrontendCallback {
virtual Return<void> onEvent(FrontendEventType frontendEventType);
virtual Return<void> onScanMessage(
FrontendScanMessageType type, const FrontendScanMessage& message);
+ virtual Return<void> onScanMessageExt1_1(
+ FrontendScanMessageTypeExt1_1 type, const FrontendScanMessageExt1_1& messageExt);
jweak mObject;
FrontendId mId;
@@ -268,6 +273,8 @@ private:
static jobject getIsdbsFrontendCaps(JNIEnv *env, FrontendInfo::FrontendCapabilities& caps);
static jobject getIsdbtFrontendCaps(JNIEnv *env, FrontendInfo::FrontendCapabilities& caps);
static jobject getDtmbFrontendCaps(JNIEnv *env, int id);
+
+ bool isV1_1ExtendedStatusType(jint type);
};
class C2DataIdInfo : public C2Param {
diff --git a/non-updatable-api/current.txt b/non-updatable-api/current.txt
index 45d22144fe8f..4029202c591b 100644
--- a/non-updatable-api/current.txt
+++ b/non-updatable-api/current.txt
@@ -2851,6 +2851,7 @@ package android.accessibilityservice {
method public int describeContents();
method public int getDisplayId();
method public int getGestureId();
+ method @NonNull public java.util.List<android.view.MotionEvent> getMotionEvents();
method public void writeToParcel(@NonNull android.os.Parcel, int);
field @NonNull public static final android.os.Parcelable.Creator<android.accessibilityservice.AccessibilityGestureEvent> CREATOR;
}
@@ -2932,6 +2933,7 @@ package android.accessibilityservice {
field public static final int GESTURE_SWIPE_UP_AND_DOWN = 7; // 0x7
field public static final int GESTURE_SWIPE_UP_AND_LEFT = 13; // 0xd
field public static final int GESTURE_SWIPE_UP_AND_RIGHT = 14; // 0xe
+ field public static final int GESTURE_UNKNOWN = 0; // 0x0
field public static final int GLOBAL_ACTION_ACCESSIBILITY_ALL_APPS = 14; // 0xe
field public static final int GLOBAL_ACTION_ACCESSIBILITY_BUTTON = 11; // 0xb
field public static final int GLOBAL_ACTION_ACCESSIBILITY_BUTTON_CHOOSER = 12; // 0xc
@@ -3047,6 +3049,7 @@ package android.accessibilityservice {
field public static final int FLAG_REQUEST_SHORTCUT_WARNING_DIALOG_SPOKEN_FEEDBACK = 1024; // 0x400
field public static final int FLAG_REQUEST_TOUCH_EXPLORATION_MODE = 4; // 0x4
field public static final int FLAG_RETRIEVE_INTERACTIVE_WINDOWS = 64; // 0x40
+ field public static final int FLAG_SEND_MOTION_EVENTS = 16384; // 0x4000
field public static final int FLAG_SERVICE_HANDLES_DOUBLE_TAP = 2048; // 0x800
field public int eventTypes;
field public int feedbackType;
@@ -10668,12 +10671,15 @@ package android.content {
field public static final String ACTION_PACKAGE_CHANGED = "android.intent.action.PACKAGE_CHANGED";
field public static final String ACTION_PACKAGE_DATA_CLEARED = "android.intent.action.PACKAGE_DATA_CLEARED";
field public static final String ACTION_PACKAGE_FIRST_LAUNCH = "android.intent.action.PACKAGE_FIRST_LAUNCH";
+ field public static final String ACTION_PACKAGE_FULLY_LOADED = "android.intent.action.PACKAGE_FULLY_LOADED";
field public static final String ACTION_PACKAGE_FULLY_REMOVED = "android.intent.action.PACKAGE_FULLY_REMOVED";
field @Deprecated public static final String ACTION_PACKAGE_INSTALL = "android.intent.action.PACKAGE_INSTALL";
field public static final String ACTION_PACKAGE_NEEDS_VERIFICATION = "android.intent.action.PACKAGE_NEEDS_VERIFICATION";
field public static final String ACTION_PACKAGE_REMOVED = "android.intent.action.PACKAGE_REMOVED";
field public static final String ACTION_PACKAGE_REPLACED = "android.intent.action.PACKAGE_REPLACED";
field public static final String ACTION_PACKAGE_RESTARTED = "android.intent.action.PACKAGE_RESTARTED";
+ field public static final String ACTION_PACKAGE_STARTABLE = "android.intent.action.PACKAGE_STARTABLE";
+ field public static final String ACTION_PACKAGE_UNSTARTABLE = "android.intent.action.PACKAGE_UNSTARTABLE";
field public static final String ACTION_PACKAGE_VERIFIED = "android.intent.action.PACKAGE_VERIFIED";
field public static final String ACTION_PASTE = "android.intent.action.PASTE";
field public static final String ACTION_PICK = "android.intent.action.PICK";
@@ -10814,7 +10820,6 @@ package android.content {
field public static final String EXTRA_REFERRER = "android.intent.extra.REFERRER";
field public static final String EXTRA_REFERRER_NAME = "android.intent.extra.REFERRER_NAME";
field public static final String EXTRA_REMOTE_INTENT_TOKEN = "android.intent.extra.remote_intent_token";
- field public static final String EXTRA_REMOVED_BY_SYSTEM = "android.intent.extra.REMOVED_BY_SYSTEM";
field public static final String EXTRA_REPLACEMENT_EXTRAS = "android.intent.extra.REPLACEMENT_EXTRAS";
field public static final String EXTRA_REPLACING = "android.intent.extra.REPLACING";
field public static final String EXTRA_RESTRICTIONS_BUNDLE = "android.intent.extra.restrictions_bundle";
@@ -10838,7 +10843,9 @@ package android.content {
field public static final String EXTRA_TIMEZONE = "time-zone";
field public static final String EXTRA_TITLE = "android.intent.extra.TITLE";
field public static final String EXTRA_UID = "android.intent.extra.UID";
+ field public static final String EXTRA_UNSTARTABLE_REASON = "android.intent.extra.UNSTARTABLE_REASON";
field public static final String EXTRA_USER = "android.intent.extra.USER";
+ field public static final String EXTRA_USER_INITIATED = "android.intent.extra.USER_INITIATED";
field public static final int FILL_IN_ACTION = 1; // 0x1
field public static final int FILL_IN_CATEGORIES = 4; // 0x4
field public static final int FILL_IN_CLIP_DATA = 128; // 0x80
@@ -12258,7 +12265,7 @@ package android.content.pm {
field @Deprecated public static final int GET_DISABLED_UNTIL_USED_COMPONENTS = 32768; // 0x8000
field public static final int GET_GIDS = 256; // 0x100
field public static final int GET_INSTRUMENTATION = 16; // 0x10
- field public static final int GET_INTENT_FILTERS = 32; // 0x20
+ field @Deprecated public static final int GET_INTENT_FILTERS = 32; // 0x20
field public static final int GET_META_DATA = 128; // 0x80
field public static final int GET_PERMISSIONS = 4096; // 0x1000
field public static final int GET_PROVIDERS = 8; // 0x8
@@ -12297,6 +12304,9 @@ package android.content.pm {
field public static final int SYNCHRONOUS = 2; // 0x2
field @Nullable public static final java.util.List<java.security.cert.Certificate> TRUST_ALL;
field @NonNull public static final java.util.List<java.security.cert.Certificate> TRUST_NONE;
+ field public static final int UNSTARTABLE_REASON_CONNECTION_ERROR = 1; // 0x1
+ field public static final int UNSTARTABLE_REASON_INSUFFICIENT_STORAGE = 2; // 0x2
+ field public static final int UNSTARTABLE_REASON_UNKNOWN = 0; // 0x0
field public static final int VERIFICATION_ALLOW = 1; // 0x1
field public static final int VERIFICATION_REJECT = -1; // 0xffffffff
field public static final int VERSION_CODE_HIGHEST = -1; // 0xffffffff
@@ -45206,6 +45216,7 @@ package android.telephony {
}
public static final class CarrierConfigManager.Ims {
+ field public static final String KEY_IMS_SINGLE_REGISTRATION_REQUIRED_BOOL = "ims.ims_single_registration_required_bool";
field public static final String KEY_PREFIX = "ims.";
field public static final String KEY_WIFI_OFF_DEFERRING_TIME_MILLIS_INT = "ims.wifi_off_deferring_time_millis_int";
}
@@ -46210,6 +46221,7 @@ package android.telephony {
}
public class SignalStrength implements android.os.Parcelable {
+ ctor public SignalStrength(@NonNull android.telephony.SignalStrength);
method public int describeContents();
method @Deprecated public int getCdmaDbm();
method @Deprecated public int getCdmaEcio();
@@ -46717,6 +46729,9 @@ package android.telephony {
field public static final int DATA_ENABLED_REASON_USER = 0; // 0x0
field public static final int DATA_SUSPENDED = 3; // 0x3
field public static final int DATA_UNKNOWN = -1; // 0xffffffff
+ field public static final int ERI_FLASH = 2; // 0x2
+ field public static final int ERI_OFF = 1; // 0x1
+ field public static final int ERI_ON = 0; // 0x0
field public static final String EXTRA_ACTIVE_SIM_SUPPORTED_COUNT = "android.telephony.extra.ACTIVE_SIM_SUPPORTED_COUNT";
field public static final String EXTRA_CALL_VOICEMAIL_INTENT = "android.telephony.extra.CALL_VOICEMAIL_INTENT";
field public static final String EXTRA_CARRIER_ID = "android.telephony.extra.CARRIER_ID";
diff --git a/non-updatable-api/module-lib-current.txt b/non-updatable-api/module-lib-current.txt
index 9b83a294ad35..ae6ecc763aef 100644
--- a/non-updatable-api/module-lib-current.txt
+++ b/non-updatable-api/module-lib-current.txt
@@ -107,8 +107,6 @@ package android.os {
public interface Parcelable {
method public default int getStability();
- field public static final int PARCELABLE_STABILITY_LOCAL = 0; // 0x0
- field public static final int PARCELABLE_STABILITY_VINTF = 1; // 0x1
}
public class StatsServiceManager {
diff --git a/non-updatable-api/system-current.txt b/non-updatable-api/system-current.txt
index f558b486bb07..e871814ab9a6 100644
--- a/non-updatable-api/system-current.txt
+++ b/non-updatable-api/system-current.txt
@@ -225,6 +225,7 @@ package android {
field public static final String SET_WALLPAPER_COMPONENT = "android.permission.SET_WALLPAPER_COMPONENT";
field public static final String SHOW_KEYGUARD_MESSAGE = "android.permission.SHOW_KEYGUARD_MESSAGE";
field public static final String SHUTDOWN = "android.permission.SHUTDOWN";
+ field public static final String START_ACTIVITIES_FROM_BACKGROUND = "android.permission.START_ACTIVITIES_FROM_BACKGROUND";
field public static final String STATUS_BAR_SERVICE = "android.permission.STATUS_BAR_SERVICE";
field public static final String STOP_APP_SWITCHES = "android.permission.STOP_APP_SWITCHES";
field public static final String SUBSTITUTE_NOTIFICATION_APP_NAME = "android.permission.SUBSTITUTE_NOTIFICATION_APP_NAME";
@@ -594,7 +595,7 @@ package android.app {
public class BroadcastOptions {
method public static android.app.BroadcastOptions makeBasic();
- method @RequiresPermission("android.permission.START_ACTIVITIES_FROM_BACKGROUND") public void setBackgroundActivityStartsAllowed(boolean);
+ method @RequiresPermission(android.Manifest.permission.START_ACTIVITIES_FROM_BACKGROUND) public void setBackgroundActivityStartsAllowed(boolean);
method public void setDontSendToRestrictedApps(boolean);
method @RequiresPermission(android.Manifest.permission.CHANGE_DEVICE_IDLE_TEMP_WHITELIST) public void setTemporaryAppWhitelistDuration(long);
method public android.os.Bundle toBundle();
@@ -863,6 +864,7 @@ package android.app.admin {
field public static final int PROVISIONING_TRIGGER_QR_CODE = 2; // 0x2
field public static final int PROVISIONING_TRIGGER_UNSPECIFIED = 0; // 0x0
field public static final int STATE_USER_PROFILE_COMPLETE = 4; // 0x4
+ field public static final int STATE_USER_PROFILE_FINALIZED = 5; // 0x5
field public static final int STATE_USER_SETUP_COMPLETE = 2; // 0x2
field public static final int STATE_USER_SETUP_FINALIZED = 3; // 0x3
field public static final int STATE_USER_SETUP_INCOMPLETE = 1; // 0x1
@@ -1742,6 +1744,7 @@ package android.content {
field public static final String APP_PREDICTION_SERVICE = "app_prediction";
field public static final String BACKUP_SERVICE = "backup";
field public static final String BATTERY_STATS_SERVICE = "batterystats";
+ field public static final int BIND_ALLOW_BACKGROUND_ACTIVITY_STARTS = 1048576; // 0x100000
field public static final String BUGREPORT_SERVICE = "bugreport";
field public static final String CONTENT_SUGGESTIONS_SERVICE = "content_suggestions";
field public static final String CONTEXTHUB_SERVICE = "contexthub";
@@ -5148,12 +5151,45 @@ package android.media.tv.tuner.filter {
public class AvSettings extends android.media.tv.tuner.filter.Settings {
method @NonNull public static android.media.tv.tuner.filter.AvSettings.Builder builder(int, boolean);
+ method public int getAudioStreamType();
+ method public int getVideoStreamType();
method public boolean isPassthrough();
+ field public static final int AUDIO_STREAM_TYPE_AAC = 6; // 0x6
+ field public static final int AUDIO_STREAM_TYPE_AC3 = 7; // 0x7
+ field public static final int AUDIO_STREAM_TYPE_AC4 = 9; // 0x9
+ field public static final int AUDIO_STREAM_TYPE_DRA = 15; // 0xf
+ field public static final int AUDIO_STREAM_TYPE_DTS = 10; // 0xa
+ field public static final int AUDIO_STREAM_TYPE_DTS_HD = 11; // 0xb
+ field public static final int AUDIO_STREAM_TYPE_EAC3 = 8; // 0x8
+ field public static final int AUDIO_STREAM_TYPE_MP3 = 2; // 0x2
+ field public static final int AUDIO_STREAM_TYPE_MPEG1 = 3; // 0x3
+ field public static final int AUDIO_STREAM_TYPE_MPEG2 = 4; // 0x4
+ field public static final int AUDIO_STREAM_TYPE_MPEGH = 5; // 0x5
+ field public static final int AUDIO_STREAM_TYPE_OPUS = 13; // 0xd
+ field public static final int AUDIO_STREAM_TYPE_PCM = 1; // 0x1
+ field public static final int AUDIO_STREAM_TYPE_UNDEFINED = 0; // 0x0
+ field public static final int AUDIO_STREAM_TYPE_VORBIS = 14; // 0xe
+ field public static final int AUDIO_STREAM_TYPE_WMA = 12; // 0xc
+ field public static final int VIDEO_STREAM_TYPE_AV1 = 10; // 0xa
+ field public static final int VIDEO_STREAM_TYPE_AVC = 5; // 0x5
+ field public static final int VIDEO_STREAM_TYPE_AVS = 11; // 0xb
+ field public static final int VIDEO_STREAM_TYPE_AVS2 = 12; // 0xc
+ field public static final int VIDEO_STREAM_TYPE_HEVC = 6; // 0x6
+ field public static final int VIDEO_STREAM_TYPE_MPEG1 = 2; // 0x2
+ field public static final int VIDEO_STREAM_TYPE_MPEG2 = 3; // 0x3
+ field public static final int VIDEO_STREAM_TYPE_MPEG4P2 = 4; // 0x4
+ field public static final int VIDEO_STREAM_TYPE_RESERVED = 1; // 0x1
+ field public static final int VIDEO_STREAM_TYPE_UNDEFINED = 0; // 0x0
+ field public static final int VIDEO_STREAM_TYPE_VC1 = 7; // 0x7
+ field public static final int VIDEO_STREAM_TYPE_VP8 = 8; // 0x8
+ field public static final int VIDEO_STREAM_TYPE_VP9 = 9; // 0x9
}
public static class AvSettings.Builder {
method @NonNull public android.media.tv.tuner.filter.AvSettings build();
+ method @NonNull public android.media.tv.tuner.filter.AvSettings.Builder setAudioStreamType(int);
method @NonNull public android.media.tv.tuner.filter.AvSettings.Builder setPassthrough(boolean);
+ method @NonNull public android.media.tv.tuner.filter.AvSettings.Builder setVideoStreamType(int);
}
public class DownloadEvent extends android.media.tv.tuner.filter.FilterEvent {
@@ -5231,7 +5267,7 @@ package android.media.tv.tuner.filter {
method @NonNull public static android.media.tv.tuner.filter.IpFilterConfiguration.Builder builder();
method @NonNull @Size(min=4, max=16) public byte[] getDstIpAddress();
method public int getDstPort();
- method public int getIpFilterContextId();
+ method @IntRange(from=0, to=61439) public int getIpFilterContextId();
method @NonNull @Size(min=4, max=16) public byte[] getSrcIpAddress();
method public int getSrcPort();
method public int getType();
@@ -5267,6 +5303,7 @@ package android.media.tv.tuner.filter {
method public boolean isPrivateData();
method public boolean isPtsPresent();
method public boolean isSecureMemory();
+ method public void release();
}
public final class MmtpFilterConfiguration extends android.media.tv.tuner.filter.FilterConfiguration {
@@ -5773,6 +5810,7 @@ package android.media.tv.tuner.frontend {
method public int getSymbolRate();
method public int getType();
method public int getVcmMode();
+ method public boolean isDiseqcRxMessage();
field public static final int MODULATION_AUTO = 1; // 0x1
field public static final int MODULATION_MOD_128APSK = 2048; // 0x800
field public static final int MODULATION_MOD_16APSK = 256; // 0x100
@@ -5816,6 +5854,7 @@ package android.media.tv.tuner.frontend {
public static class DvbsFrontendSettings.Builder {
method @NonNull public android.media.tv.tuner.frontend.DvbsFrontendSettings build();
method @NonNull public android.media.tv.tuner.frontend.DvbsFrontendSettings.Builder setCodeRate(@Nullable android.media.tv.tuner.frontend.DvbsCodeRate);
+ method @NonNull public android.media.tv.tuner.frontend.DvbsFrontendSettings.Builder setDiseqcRxMessage(boolean);
method @IntRange(from=1) @NonNull public android.media.tv.tuner.frontend.DvbsFrontendSettings.Builder setFrequency(int);
method @NonNull public android.media.tv.tuner.frontend.DvbsFrontendSettings.Builder setInputStreamId(int);
method @NonNull public android.media.tv.tuner.frontend.DvbsFrontendSettings.Builder setModulation(int);
@@ -6017,14 +6056,21 @@ package android.media.tv.tuner.frontend {
public class FrontendStatus {
method public int getAgc();
method @NonNull public android.media.tv.tuner.frontend.FrontendStatus.Atsc3PlpTuningInfo[] getAtsc3PlpTuningInfo();
+ method public int getBandwidth();
method public int getBer();
+ method @NonNull public int[] getBers();
+ method @NonNull public int[] getCodeRates();
method public int getFreqOffset();
+ method public int getGuardInterval();
method public int getHierarchy();
method public long getInnerFec();
+ method @NonNull public int[] getInterleaving();
+ method @NonNull public int[] getIsdbtSegment();
method @NonNull public boolean[] getLayerErrors();
method public int getLnbVoltage();
method public int getMer();
method public int getModulation();
+ method @NonNull public int[] getModulationsExt();
method public int getPer();
method public int getPerBer();
method public int getPlpId();
@@ -6033,23 +6079,34 @@ package android.media.tv.tuner.frontend {
method public int getSnr();
method public int getSpectralInversion();
method public int getSymbolRate();
+ method public int getSystemId();
+ method public int getTransmissionMode();
+ method @NonNull public int[] getTsDataRate();
+ method public int getUec();
method public boolean isDemodLocked();
method public boolean isEwbs();
method public boolean isLnaOn();
method public boolean isRfLocked();
field public static final int FRONTEND_STATUS_TYPE_AGC = 14; // 0xe
field public static final int FRONTEND_STATUS_TYPE_ATSC3_PLP_INFO = 21; // 0x15
+ field public static final int FRONTEND_STATUS_TYPE_BANDWIDTH = 25; // 0x19
field public static final int FRONTEND_STATUS_TYPE_BER = 2; // 0x2
+ field public static final int FRONTEND_STATUS_TYPE_BERS = 23; // 0x17
+ field public static final int FRONTEND_STATUS_TYPE_CODERATES = 24; // 0x18
field public static final int FRONTEND_STATUS_TYPE_DEMOD_LOCK = 0; // 0x0
field public static final int FRONTEND_STATUS_TYPE_EWBS = 13; // 0xd
field public static final int FRONTEND_STATUS_TYPE_FEC = 8; // 0x8
field public static final int FRONTEND_STATUS_TYPE_FREQ_OFFSET = 18; // 0x12
+ field public static final int FRONTEND_STATUS_TYPE_GUARD_INTERVAL = 26; // 0x1a
field public static final int FRONTEND_STATUS_TYPE_HIERARCHY = 19; // 0x13
+ field public static final int FRONTEND_STATUS_TYPE_INTERLEAVINGS = 30; // 0x1e
+ field public static final int FRONTEND_STATUS_TYPE_ISDBT_SEGMENTS = 31; // 0x1f
field public static final int FRONTEND_STATUS_TYPE_LAYER_ERROR = 16; // 0x10
field public static final int FRONTEND_STATUS_TYPE_LNA = 15; // 0xf
field public static final int FRONTEND_STATUS_TYPE_LNB_VOLTAGE = 11; // 0xb
field public static final int FRONTEND_STATUS_TYPE_MER = 17; // 0x11
field public static final int FRONTEND_STATUS_TYPE_MODULATION = 9; // 0x9
+ field public static final int FRONTEND_STATUS_TYPE_MODULATIONS_EXT = 22; // 0x16
field public static final int FRONTEND_STATUS_TYPE_PER = 3; // 0x3
field public static final int FRONTEND_STATUS_TYPE_PLP_ID = 12; // 0xc
field public static final int FRONTEND_STATUS_TYPE_PRE_BER = 4; // 0x4
@@ -6059,6 +6116,10 @@ package android.media.tv.tuner.frontend {
field public static final int FRONTEND_STATUS_TYPE_SNR = 1; // 0x1
field public static final int FRONTEND_STATUS_TYPE_SPECTRAL = 10; // 0xa
field public static final int FRONTEND_STATUS_TYPE_SYMBOL_RATE = 7; // 0x7
+ field public static final int FRONTEND_STATUS_TYPE_T2_SYSTEM_ID = 29; // 0x1d
+ field public static final int FRONTEND_STATUS_TYPE_TRANSMISSION_MODE = 27; // 0x1b
+ field public static final int FRONTEND_STATUS_TYPE_TS_DATA_RATES = 32; // 0x20
+ field public static final int FRONTEND_STATUS_TYPE_UEC = 28; // 0x1c
}
public static class FrontendStatus.Atsc3PlpTuningInfo {
@@ -6222,7 +6283,9 @@ package android.media.tv.tuner.frontend {
method public void onHierarchyReported(int);
method public void onInputStreamIdsReported(@NonNull int[]);
method public void onLocked();
+ method public default void onModulationReported(int);
method public void onPlpIdsReported(@NonNull int[]);
+ method public default void onPriorityReported(boolean);
method public void onProgress(@IntRange(from=0, to=100) int);
method public void onScanStopped();
method public void onSignalTypeReported(int);
@@ -7641,6 +7704,22 @@ package android.os {
method public boolean hasSingleFileDescriptor();
}
+ public interface Parcelable {
+ field public static final int PARCELABLE_STABILITY_LOCAL = 0; // 0x0
+ field public static final int PARCELABLE_STABILITY_VINTF = 1; // 0x1
+ }
+
+ public final class ParcelableHolder implements android.os.Parcelable {
+ ctor public ParcelableHolder(int);
+ method public int describeContents();
+ method @Nullable public <T extends android.os.Parcelable> T getParcelable(@NonNull Class<T>);
+ method public int getStability();
+ method public void readFromParcel(@NonNull android.os.Parcel);
+ method public boolean setParcelable(@Nullable android.os.Parcelable);
+ method public void writeToParcel(@NonNull android.os.Parcel, int);
+ field @NonNull public static final android.os.Parcelable.Creator<android.os.ParcelableHolder> CREATOR;
+ }
+
public final class PowerManager {
method @RequiresPermission(allOf={android.Manifest.permission.READ_DREAM_STATE, android.Manifest.permission.WRITE_DREAM_STATE}) public void dream(long);
method @RequiresPermission(android.Manifest.permission.DEVICE_POWER) public boolean forceSuspend();
@@ -10529,6 +10608,7 @@ package android.telephony {
method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public int getCarrierPrivilegeStatus(int);
method @NonNull @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public java.util.List<java.lang.String> getCarrierPrivilegedPackagesForAllActiveSubscriptions();
method @Nullable @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public android.telephony.CarrierRestrictionRules getCarrierRestrictionRules();
+ method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public int getCdmaEnhancedRoamingIndicatorIconIndex();
method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public String getCdmaMdn();
method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public String getCdmaMdn(int);
method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public String getCdmaMin();
@@ -11262,6 +11342,10 @@ package android.telephony.ims {
field @NonNull public static final android.os.Parcelable.Creator<android.telephony.ims.ImsExternalCallState> CREATOR;
}
+ public class ImsManager {
+ method @NonNull public android.telephony.ims.SipDelegateManager getSipDelegateManager(int);
+ }
+
public class ImsMmTelManager implements android.telephony.ims.RegistrationManager {
method @Deprecated @NonNull @RequiresPermission(anyOf={android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE, android.Manifest.permission.READ_PRECISE_PHONE_STATE}) public static android.telephony.ims.ImsMmTelManager createForSubscriptionId(int);
method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public void getFeatureState(@NonNull java.util.concurrent.Executor, @NonNull java.util.function.Consumer<java.lang.Integer>) throws android.telephony.ims.ImsException;
@@ -11297,10 +11381,13 @@ package android.telephony.ims {
method public void disableIms(int);
method public void enableIms(int);
method public android.telephony.ims.stub.ImsConfigImplBase getConfig(int);
+ method public long getImsServiceCapabilities();
method public android.telephony.ims.stub.ImsRegistrationImplBase getRegistration(int);
+ method @Nullable public android.telephony.ims.stub.SipTransportImplBase getSipTransport(int);
method public final void onUpdateSupportedImsFeatures(android.telephony.ims.stub.ImsFeatureConfiguration) throws android.os.RemoteException;
method public android.telephony.ims.stub.ImsFeatureConfiguration querySupportedImsFeatures();
method public void readyForFeatureCreation();
+ field public static final long CAPABILITY_SIP_DELEGATE_CREATION = 2L; // 0x2L
}
public final class ImsSsData implements android.os.Parcelable {
@@ -11546,6 +11633,10 @@ package android.telephony.ims {
method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setUceSettingEnabled(boolean) throws android.telephony.ims.ImsException;
}
+ public class SipDelegateManager {
+ method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public boolean isSupported() throws android.telephony.ims.ImsException;
+ }
+
}
package android.telephony.ims.feature {
@@ -11795,6 +11886,10 @@ package android.telephony.ims.stub {
method public int updateColr(int);
}
+ public class SipTransportImplBase {
+ ctor public SipTransportImplBase(@NonNull java.util.concurrent.Executor);
+ }
+
}
package android.telephony.mbms {
diff --git a/packages/CarSystemUI/AndroidManifest.xml b/packages/CarSystemUI/AndroidManifest.xml
index c0482e1b3e04..f0cf2a9b7156 100644
--- a/packages/CarSystemUI/AndroidManifest.xml
+++ b/packages/CarSystemUI/AndroidManifest.xml
@@ -23,6 +23,8 @@
<uses-permission android:name="android.car.permission.CAR_POWER" />
<!-- This permission is required to get the trusted device list of a user. -->
<uses-permission android:name="android.car.permission.CAR_ENROLL_TRUST"/>
+ <!-- This permission is required to monitor gear state. -->
+ <uses-permission android:name="android.car.permission.CAR_POWERTRAIN" />
<!-- This permission is required to get bluetooth broadcast. -->
<uses-permission android:name="android.permission.BLUETOOTH" />
<!-- These permissions are required to implement icons based on role holders. -->
diff --git a/packages/CarSystemUI/res/layout/rear_view_camera.xml b/packages/CarSystemUI/res/layout/rear_view_camera.xml
new file mode 100644
index 000000000000..9b9898cf3f45
--- /dev/null
+++ b/packages/CarSystemUI/res/layout/rear_view_camera.xml
@@ -0,0 +1,31 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ~ Copyright (C) 2020 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License.
+ -->
+<LinearLayout
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:id="@+id/rear_view_camera_container"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:background="@android:color/transparent"
+ android:orientation="vertical">
+ <Button
+ android:id="@+id/close_button"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:background="@color/rear_view_camera_button_background"
+ android:text="@string/rear_view_camera_close_button_text"
+ android:textAppearance="?android:attr/textAppearanceLarge"/>
+</LinearLayout>
diff --git a/packages/CarSystemUI/res/layout/sysui_overlay_window.xml b/packages/CarSystemUI/res/layout/sysui_overlay_window.xml
index 2c9788955bfa..980265e84e54 100644
--- a/packages/CarSystemUI/res/layout/sysui_overlay_window.xml
+++ b/packages/CarSystemUI/res/layout/sysui_overlay_window.xml
@@ -42,4 +42,10 @@
android:layout_height="match_parent"
android:layout="@layout/car_user_switching_dialog"/>
-</FrameLayout> \ No newline at end of file
+ <!-- Should be at bottom to get the highest Z-order. -->
+ <ViewStub android:id="@+id/rear_view_camera_stub"
+ android:layout_width="@dimen/rear_view_camera_width"
+ android:layout_height="@dimen/rear_view_camera_height"
+ android:layout_gravity="center"
+ android:layout="@layout/rear_view_camera"/>
+</FrameLayout>
diff --git a/packages/CarSystemUI/res/values-af/strings.xml b/packages/CarSystemUI/res/values-af/strings.xml
index 2ab3aa44a86c..b377ec47f6c6 100644
--- a/packages/CarSystemUI/res/values-af/strings.xml
+++ b/packages/CarSystemUI/res/values-af/strings.xml
@@ -28,4 +28,6 @@
<string name="user_add_user_message_update" msgid="7061671307004867811">"Enige gebruiker kan programme vir al die ander gebruikers opdateer."</string>
<string name="car_loading_profile" msgid="4507385037552574474">"Laai tans"</string>
<string name="car_loading_profile_developer_message" msgid="1660962766911529611">"Laai tans gebruiker (van <xliff:g id="FROM_USER">%1$d</xliff:g> na <xliff:g id="TO_USER">%2$d</xliff:g>)"</string>
+ <!-- no translation found for rear_view_camera_close_button_text (8430918817320533693) -->
+ <skip />
</resources>
diff --git a/packages/CarSystemUI/res/values-am/strings.xml b/packages/CarSystemUI/res/values-am/strings.xml
index d5b580e3dd9d..4f2bba8aa1de 100644
--- a/packages/CarSystemUI/res/values-am/strings.xml
+++ b/packages/CarSystemUI/res/values-am/strings.xml
@@ -28,4 +28,6 @@
<string name="user_add_user_message_update" msgid="7061671307004867811">"ማንኛውም ተጠቃሚ መተግበሪያዎችን ለሌሎች ተጠቃሚዎች ሁሉ ማዘመን ይችላል።"</string>
<string name="car_loading_profile" msgid="4507385037552574474">"በመጫን ላይ"</string>
<string name="car_loading_profile_developer_message" msgid="1660962766911529611">"ተጠቃሚን (ከ<xliff:g id="FROM_USER">%1$d</xliff:g> ወደ <xliff:g id="TO_USER">%2$d</xliff:g>) በመጫን ላይ"</string>
+ <!-- no translation found for rear_view_camera_close_button_text (8430918817320533693) -->
+ <skip />
</resources>
diff --git a/packages/CarSystemUI/res/values-ar/strings.xml b/packages/CarSystemUI/res/values-ar/strings.xml
index 09b302d85eab..61a08a4eae49 100644
--- a/packages/CarSystemUI/res/values-ar/strings.xml
+++ b/packages/CarSystemUI/res/values-ar/strings.xml
@@ -28,4 +28,6 @@
<string name="user_add_user_message_update" msgid="7061671307004867811">"يمكن لأي مستخدم تحديث التطبيقات لجميع المستخدمين الآخرين."</string>
<string name="car_loading_profile" msgid="4507385037552574474">"جارٍ التحميل"</string>
<string name="car_loading_profile_developer_message" msgid="1660962766911529611">"جارٍ تحميل الملف الشخصي الجديد للمستخدم (من <xliff:g id="FROM_USER">%1$d</xliff:g> إلى <xliff:g id="TO_USER">%2$d</xliff:g>)"</string>
+ <!-- no translation found for rear_view_camera_close_button_text (8430918817320533693) -->
+ <skip />
</resources>
diff --git a/packages/CarSystemUI/res/values-as/strings.xml b/packages/CarSystemUI/res/values-as/strings.xml
index a8aa74d8c7a4..edc36215bcce 100644
--- a/packages/CarSystemUI/res/values-as/strings.xml
+++ b/packages/CarSystemUI/res/values-as/strings.xml
@@ -28,4 +28,6 @@
<string name="user_add_user_message_update" msgid="7061671307004867811">"যিকোনো ব্যৱহাৰকাৰীয়ে অন্য ব্যৱহাৰকাৰীৰ বাবে এপ্‌সমূহ আপডে’ট কৰিব পাৰে।"</string>
<string name="car_loading_profile" msgid="4507385037552574474">"ল’ড হৈ আছে"</string>
<string name="car_loading_profile_developer_message" msgid="1660962766911529611">"ব্যৱহাৰকাৰী ল’ড হৈ আছে (<xliff:g id="FROM_USER">%1$d</xliff:g>ৰ পৰা to <xliff:g id="TO_USER">%2$d</xliff:g>লৈ)"</string>
+ <!-- no translation found for rear_view_camera_close_button_text (8430918817320533693) -->
+ <skip />
</resources>
diff --git a/packages/CarSystemUI/res/values-az/strings.xml b/packages/CarSystemUI/res/values-az/strings.xml
index 97facc27be68..398f5c38c03e 100644
--- a/packages/CarSystemUI/res/values-az/strings.xml
+++ b/packages/CarSystemUI/res/values-az/strings.xml
@@ -28,4 +28,6 @@
<string name="user_add_user_message_update" msgid="7061671307004867811">"İstənilən istifadəçi digər bütün istifadəçilər üçün tətbiqləri güncəlləyə bilər."</string>
<string name="car_loading_profile" msgid="4507385037552574474">"Yüklənir"</string>
<string name="car_loading_profile_developer_message" msgid="1660962766911529611">"İstifadəçi yüklənir (<xliff:g id="FROM_USER">%1$d</xliff:g>-<xliff:g id="TO_USER">%2$d</xliff:g>)"</string>
+ <!-- no translation found for rear_view_camera_close_button_text (8430918817320533693) -->
+ <skip />
</resources>
diff --git a/packages/CarSystemUI/res/values-b+sr+Latn/strings.xml b/packages/CarSystemUI/res/values-b+sr+Latn/strings.xml
index ec310be7a4d8..6c1979f7a95a 100644
--- a/packages/CarSystemUI/res/values-b+sr+Latn/strings.xml
+++ b/packages/CarSystemUI/res/values-b+sr+Latn/strings.xml
@@ -28,4 +28,6 @@
<string name="user_add_user_message_update" msgid="7061671307004867811">"Svaki korisnik može da ažurira aplikacije za sve ostale korisnike."</string>
<string name="car_loading_profile" msgid="4507385037552574474">"Učitava se"</string>
<string name="car_loading_profile_developer_message" msgid="1660962766911529611">"Profil korisnika se učitava (iz<xliff:g id="FROM_USER">%1$d</xliff:g> u <xliff:g id="TO_USER">%2$d</xliff:g>)"</string>
+ <!-- no translation found for rear_view_camera_close_button_text (8430918817320533693) -->
+ <skip />
</resources>
diff --git a/packages/CarSystemUI/res/values-be/strings.xml b/packages/CarSystemUI/res/values-be/strings.xml
index 17fc58451464..4e9794855e47 100644
--- a/packages/CarSystemUI/res/values-be/strings.xml
+++ b/packages/CarSystemUI/res/values-be/strings.xml
@@ -28,4 +28,6 @@
<string name="user_add_user_message_update" msgid="7061671307004867811">"Кожны карыстальнік прылады можа абнаўляць праграмы для ўсіх іншых карыстальнікаў."</string>
<string name="car_loading_profile" msgid="4507385037552574474">"Ідзе загрузка"</string>
<string name="car_loading_profile_developer_message" msgid="1660962766911529611">"Ідзе загрузка профілю карыстальніка (ад <xliff:g id="FROM_USER">%1$d</xliff:g> да <xliff:g id="TO_USER">%2$d</xliff:g>)"</string>
+ <!-- no translation found for rear_view_camera_close_button_text (8430918817320533693) -->
+ <skip />
</resources>
diff --git a/packages/CarSystemUI/res/values-bg/strings.xml b/packages/CarSystemUI/res/values-bg/strings.xml
index ae2db2d08f25..7dfab54b8add 100644
--- a/packages/CarSystemUI/res/values-bg/strings.xml
+++ b/packages/CarSystemUI/res/values-bg/strings.xml
@@ -28,4 +28,6 @@
<string name="user_add_user_message_update" msgid="7061671307004867811">"Всеки потребител може да актуализира приложенията за всички останали потребители."</string>
<string name="car_loading_profile" msgid="4507385037552574474">"Зарежда се"</string>
<string name="car_loading_profile_developer_message" msgid="1660962766911529611">"Потребителят се зарежда (от <xliff:g id="FROM_USER">%1$d</xliff:g> до <xliff:g id="TO_USER">%2$d</xliff:g>)"</string>
+ <!-- no translation found for rear_view_camera_close_button_text (8430918817320533693) -->
+ <skip />
</resources>
diff --git a/packages/CarSystemUI/res/values-bn/strings.xml b/packages/CarSystemUI/res/values-bn/strings.xml
index 9a01fad952eb..a45e66e8c2f2 100644
--- a/packages/CarSystemUI/res/values-bn/strings.xml
+++ b/packages/CarSystemUI/res/values-bn/strings.xml
@@ -28,4 +28,6 @@
<string name="user_add_user_message_update" msgid="7061671307004867811">"যেকোনও ব্যবহারকারী বাকি সব ব্যবহারকারীর জন্য অ্যাপ আপডেট করতে পারবেন।"</string>
<string name="car_loading_profile" msgid="4507385037552574474">"লোড হচ্ছে"</string>
<string name="car_loading_profile_developer_message" msgid="1660962766911529611">"ব্যবহারকারীর প্রোফাইল লোড করা হচ্ছে (<xliff:g id="FROM_USER">%1$d</xliff:g> থেকে <xliff:g id="TO_USER">%2$d</xliff:g>-এ)"</string>
+ <!-- no translation found for rear_view_camera_close_button_text (8430918817320533693) -->
+ <skip />
</resources>
diff --git a/packages/CarSystemUI/res/values-bs/strings.xml b/packages/CarSystemUI/res/values-bs/strings.xml
index 5ef9aeba3436..119f2d7bf793 100644
--- a/packages/CarSystemUI/res/values-bs/strings.xml
+++ b/packages/CarSystemUI/res/values-bs/strings.xml
@@ -28,4 +28,6 @@
<string name="user_add_user_message_update" msgid="7061671307004867811">"Bilo koji korisnik može ažurirati aplikacije za sve druge korisnike."</string>
<string name="car_loading_profile" msgid="4507385037552574474">"Učitavanje"</string>
<string name="car_loading_profile_developer_message" msgid="1660962766911529611">"Učitavanje korisnika (od korisnika <xliff:g id="FROM_USER">%1$d</xliff:g> do korisnika <xliff:g id="TO_USER">%2$d</xliff:g>)"</string>
+ <!-- no translation found for rear_view_camera_close_button_text (8430918817320533693) -->
+ <skip />
</resources>
diff --git a/packages/CarSystemUI/res/values-ca/strings.xml b/packages/CarSystemUI/res/values-ca/strings.xml
index 083f9d05069e..b1e722e95c58 100644
--- a/packages/CarSystemUI/res/values-ca/strings.xml
+++ b/packages/CarSystemUI/res/values-ca/strings.xml
@@ -28,4 +28,6 @@
<string name="user_add_user_message_update" msgid="7061671307004867811">"Qualsevol usuari pot actualitzar les aplicacions de la resta d\'usuaris."</string>
<string name="car_loading_profile" msgid="4507385037552574474">"S\'està carregant"</string>
<string name="car_loading_profile_developer_message" msgid="1660962766911529611">"S\'està carregant l\'usuari (de <xliff:g id="FROM_USER">%1$d</xliff:g> a <xliff:g id="TO_USER">%2$d</xliff:g>)"</string>
+ <!-- no translation found for rear_view_camera_close_button_text (8430918817320533693) -->
+ <skip />
</resources>
diff --git a/packages/CarSystemUI/res/values-cs/strings.xml b/packages/CarSystemUI/res/values-cs/strings.xml
index 8071cef72650..dd4472f06aa3 100644
--- a/packages/CarSystemUI/res/values-cs/strings.xml
+++ b/packages/CarSystemUI/res/values-cs/strings.xml
@@ -28,4 +28,6 @@
<string name="user_add_user_message_update" msgid="7061671307004867811">"Každý uživatel může aktualizovat aplikace všech ostatních uživatelů."</string>
<string name="car_loading_profile" msgid="4507385037552574474">"Načítání"</string>
<string name="car_loading_profile_developer_message" msgid="1660962766911529611">"Načítání uživatele (předchozí: <xliff:g id="FROM_USER">%1$d</xliff:g>, následující: <xliff:g id="TO_USER">%2$d</xliff:g>)"</string>
+ <!-- no translation found for rear_view_camera_close_button_text (8430918817320533693) -->
+ <skip />
</resources>
diff --git a/packages/CarSystemUI/res/values-da/strings.xml b/packages/CarSystemUI/res/values-da/strings.xml
index b19cdcba5af9..6c08aa56bc7e 100644
--- a/packages/CarSystemUI/res/values-da/strings.xml
+++ b/packages/CarSystemUI/res/values-da/strings.xml
@@ -28,4 +28,6 @@
<string name="user_add_user_message_update" msgid="7061671307004867811">"Alle brugere kan opdatere apps for alle andre brugere."</string>
<string name="car_loading_profile" msgid="4507385037552574474">"Indlæser"</string>
<string name="car_loading_profile_developer_message" msgid="1660962766911529611">"Indlæser bruger (fra <xliff:g id="FROM_USER">%1$d</xliff:g> til <xliff:g id="TO_USER">%2$d</xliff:g>)"</string>
+ <!-- no translation found for rear_view_camera_close_button_text (8430918817320533693) -->
+ <skip />
</resources>
diff --git a/packages/CarSystemUI/res/values-de/strings.xml b/packages/CarSystemUI/res/values-de/strings.xml
index 99ba13e4f3f8..131dee19b0ca 100644
--- a/packages/CarSystemUI/res/values-de/strings.xml
+++ b/packages/CarSystemUI/res/values-de/strings.xml
@@ -28,4 +28,6 @@
<string name="user_add_user_message_update" msgid="7061671307004867811">"Jeder Nutzer kann Apps für alle anderen Nutzer aktualisieren."</string>
<string name="car_loading_profile" msgid="4507385037552574474">"Wird geladen"</string>
<string name="car_loading_profile_developer_message" msgid="1660962766911529611">"Nutzer wird geladen (von <xliff:g id="FROM_USER">%1$d</xliff:g> bis <xliff:g id="TO_USER">%2$d</xliff:g>)"</string>
+ <!-- no translation found for rear_view_camera_close_button_text (8430918817320533693) -->
+ <skip />
</resources>
diff --git a/packages/CarSystemUI/res/values-el/strings.xml b/packages/CarSystemUI/res/values-el/strings.xml
index e2d2cec34479..66f8d18472c9 100644
--- a/packages/CarSystemUI/res/values-el/strings.xml
+++ b/packages/CarSystemUI/res/values-el/strings.xml
@@ -28,4 +28,6 @@
<string name="user_add_user_message_update" msgid="7061671307004867811">"Οποιοσδήποτε χρήστης μπορεί να ενημερώσει τις εφαρμογές για όλους τους άλλους χρήστες."</string>
<string name="car_loading_profile" msgid="4507385037552574474">"Φόρτωση"</string>
<string name="car_loading_profile_developer_message" msgid="1660962766911529611">"Φόρτωση χρήστη (από <xliff:g id="FROM_USER">%1$d</xliff:g> έως <xliff:g id="TO_USER">%2$d</xliff:g>)"</string>
+ <!-- no translation found for rear_view_camera_close_button_text (8430918817320533693) -->
+ <skip />
</resources>
diff --git a/packages/CarSystemUI/res/values-en-rAU/strings.xml b/packages/CarSystemUI/res/values-en-rAU/strings.xml
index b8bf9906916d..b3e358fbb6ef 100644
--- a/packages/CarSystemUI/res/values-en-rAU/strings.xml
+++ b/packages/CarSystemUI/res/values-en-rAU/strings.xml
@@ -28,4 +28,6 @@
<string name="user_add_user_message_update" msgid="7061671307004867811">"Any user can update apps for all other users."</string>
<string name="car_loading_profile" msgid="4507385037552574474">"Loading"</string>
<string name="car_loading_profile_developer_message" msgid="1660962766911529611">"Loading user (from <xliff:g id="FROM_USER">%1$d</xliff:g> to <xliff:g id="TO_USER">%2$d</xliff:g>)"</string>
+ <!-- no translation found for rear_view_camera_close_button_text (8430918817320533693) -->
+ <skip />
</resources>
diff --git a/packages/CarSystemUI/res/values-en-rCA/strings.xml b/packages/CarSystemUI/res/values-en-rCA/strings.xml
index b8bf9906916d..b3e358fbb6ef 100644
--- a/packages/CarSystemUI/res/values-en-rCA/strings.xml
+++ b/packages/CarSystemUI/res/values-en-rCA/strings.xml
@@ -28,4 +28,6 @@
<string name="user_add_user_message_update" msgid="7061671307004867811">"Any user can update apps for all other users."</string>
<string name="car_loading_profile" msgid="4507385037552574474">"Loading"</string>
<string name="car_loading_profile_developer_message" msgid="1660962766911529611">"Loading user (from <xliff:g id="FROM_USER">%1$d</xliff:g> to <xliff:g id="TO_USER">%2$d</xliff:g>)"</string>
+ <!-- no translation found for rear_view_camera_close_button_text (8430918817320533693) -->
+ <skip />
</resources>
diff --git a/packages/CarSystemUI/res/values-en-rGB/strings.xml b/packages/CarSystemUI/res/values-en-rGB/strings.xml
index b8bf9906916d..b3e358fbb6ef 100644
--- a/packages/CarSystemUI/res/values-en-rGB/strings.xml
+++ b/packages/CarSystemUI/res/values-en-rGB/strings.xml
@@ -28,4 +28,6 @@
<string name="user_add_user_message_update" msgid="7061671307004867811">"Any user can update apps for all other users."</string>
<string name="car_loading_profile" msgid="4507385037552574474">"Loading"</string>
<string name="car_loading_profile_developer_message" msgid="1660962766911529611">"Loading user (from <xliff:g id="FROM_USER">%1$d</xliff:g> to <xliff:g id="TO_USER">%2$d</xliff:g>)"</string>
+ <!-- no translation found for rear_view_camera_close_button_text (8430918817320533693) -->
+ <skip />
</resources>
diff --git a/packages/CarSystemUI/res/values-en-rIN/strings.xml b/packages/CarSystemUI/res/values-en-rIN/strings.xml
index b8bf9906916d..b3e358fbb6ef 100644
--- a/packages/CarSystemUI/res/values-en-rIN/strings.xml
+++ b/packages/CarSystemUI/res/values-en-rIN/strings.xml
@@ -28,4 +28,6 @@
<string name="user_add_user_message_update" msgid="7061671307004867811">"Any user can update apps for all other users."</string>
<string name="car_loading_profile" msgid="4507385037552574474">"Loading"</string>
<string name="car_loading_profile_developer_message" msgid="1660962766911529611">"Loading user (from <xliff:g id="FROM_USER">%1$d</xliff:g> to <xliff:g id="TO_USER">%2$d</xliff:g>)"</string>
+ <!-- no translation found for rear_view_camera_close_button_text (8430918817320533693) -->
+ <skip />
</resources>
diff --git a/packages/CarSystemUI/res/values-en-rXC/strings.xml b/packages/CarSystemUI/res/values-en-rXC/strings.xml
index 1ffa5ebde689..eaf6f51d3092 100644
--- a/packages/CarSystemUI/res/values-en-rXC/strings.xml
+++ b/packages/CarSystemUI/res/values-en-rXC/strings.xml
@@ -28,4 +28,6 @@
<string name="user_add_user_message_update" msgid="7061671307004867811">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‏‏‏‏‏‏‏‏‏‏‏‏‏‏‏‏‏‏‏‎‎‎‏‎‎‎‎‎‎‎‎‎‎‎‎‏‏‎‎‎‏‎‏‎‎‎‏‏‏‎‏‎‏‏‏‎‏‎‎‏‎‏‏‏‏‏‏‏‎‏‎‎‏‏‏‎‎‎‏‏‎Any user can update apps for all other users.‎‏‎‎‏‎"</string>
<string name="car_loading_profile" msgid="4507385037552574474">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‏‏‏‏‏‏‏‏‏‏‏‏‏‏‏‏‎‏‏‏‏‏‎‏‎‎‎‏‏‎‏‎‏‏‏‎‎‏‎‏‏‎‎‏‏‏‏‎‏‏‏‏‏‎‏‎‎‏‏‏‎‏‏‎‏‏‎‎‎‎‎‎‎‎‎‏‎‏‎‎Loading‎‏‎‎‏‎"</string>
<string name="car_loading_profile_developer_message" msgid="1660962766911529611">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‏‏‏‏‏‏‏‏‏‏‏‏‏‏‏‎‏‏‎‏‏‏‎‎‎‎‏‏‎‎‏‏‏‎‏‏‎‎‏‏‎‏‎‏‏‎‎‎‎‏‏‎‏‎‏‏‏‎‏‎‎‏‎‏‏‎‎‎‏‎‏‎‎‎‏‎‏‏‎Loading user (from ‎‏‎‎‏‏‎<xliff:g id="FROM_USER">%1$d</xliff:g>‎‏‎‎‏‏‏‎ to ‎‏‎‎‏‏‎<xliff:g id="TO_USER">%2$d</xliff:g>‎‏‎‎‏‏‏‎)‎‏‎‎‏‎"</string>
+ <!-- no translation found for rear_view_camera_close_button_text (8430918817320533693) -->
+ <skip />
</resources>
diff --git a/packages/CarSystemUI/res/values-es-rUS/strings.xml b/packages/CarSystemUI/res/values-es-rUS/strings.xml
index c1c21d17a3a7..6a5f8ce43318 100644
--- a/packages/CarSystemUI/res/values-es-rUS/strings.xml
+++ b/packages/CarSystemUI/res/values-es-rUS/strings.xml
@@ -28,4 +28,6 @@
<string name="user_add_user_message_update" msgid="7061671307004867811">"Cualquier usuario podrá actualizar las apps de otras personas."</string>
<string name="car_loading_profile" msgid="4507385037552574474">"Cargando"</string>
<string name="car_loading_profile_developer_message" msgid="1660962766911529611">"Cargando usuario (de <xliff:g id="FROM_USER">%1$d</xliff:g> a <xliff:g id="TO_USER">%2$d</xliff:g>)"</string>
+ <!-- no translation found for rear_view_camera_close_button_text (8430918817320533693) -->
+ <skip />
</resources>
diff --git a/packages/CarSystemUI/res/values-es/strings.xml b/packages/CarSystemUI/res/values-es/strings.xml
index fe546051e729..c43d7e54d559 100644
--- a/packages/CarSystemUI/res/values-es/strings.xml
+++ b/packages/CarSystemUI/res/values-es/strings.xml
@@ -28,4 +28,6 @@
<string name="user_add_user_message_update" msgid="7061671307004867811">"Cualquier usuario puede actualizar las aplicaciones del resto de los usuarios."</string>
<string name="car_loading_profile" msgid="4507385037552574474">"Cargando"</string>
<string name="car_loading_profile_developer_message" msgid="1660962766911529611">"Cargando usuario (de <xliff:g id="FROM_USER">%1$d</xliff:g> a <xliff:g id="TO_USER">%2$d</xliff:g>)"</string>
+ <!-- no translation found for rear_view_camera_close_button_text (8430918817320533693) -->
+ <skip />
</resources>
diff --git a/packages/CarSystemUI/res/values-et/strings.xml b/packages/CarSystemUI/res/values-et/strings.xml
index 2fa71a975973..ad82d5fc230b 100644
--- a/packages/CarSystemUI/res/values-et/strings.xml
+++ b/packages/CarSystemUI/res/values-et/strings.xml
@@ -28,4 +28,6 @@
<string name="user_add_user_message_update" msgid="7061671307004867811">"Iga kasutaja saab rakendusi värskendada kõigi teiste kasutajate jaoks."</string>
<string name="car_loading_profile" msgid="4507385037552574474">"Laadimine"</string>
<string name="car_loading_profile_developer_message" msgid="1660962766911529611">"Kasutaja laadimine (<xliff:g id="FROM_USER">%1$d</xliff:g> &gt; <xliff:g id="TO_USER">%2$d</xliff:g>)"</string>
+ <!-- no translation found for rear_view_camera_close_button_text (8430918817320533693) -->
+ <skip />
</resources>
diff --git a/packages/CarSystemUI/res/values-eu/strings.xml b/packages/CarSystemUI/res/values-eu/strings.xml
index 36bcaae01443..5d2ca3548af2 100644
--- a/packages/CarSystemUI/res/values-eu/strings.xml
+++ b/packages/CarSystemUI/res/values-eu/strings.xml
@@ -28,4 +28,6 @@
<string name="user_add_user_message_update" msgid="7061671307004867811">"Edozein erabiltzailek egunera ditzake beste erabiltzaile guztien aplikazioak."</string>
<string name="car_loading_profile" msgid="4507385037552574474">"Kargatzen"</string>
<string name="car_loading_profile_developer_message" msgid="1660962766911529611">"Erabiltzailea kargatzen (<xliff:g id="FROM_USER">%1$d</xliff:g> izatetik<xliff:g id="TO_USER">%2$d</xliff:g> izatera igaroko da)"</string>
+ <!-- no translation found for rear_view_camera_close_button_text (8430918817320533693) -->
+ <skip />
</resources>
diff --git a/packages/CarSystemUI/res/values-fa/strings.xml b/packages/CarSystemUI/res/values-fa/strings.xml
index 3224899afb90..ef37b654bde9 100644
--- a/packages/CarSystemUI/res/values-fa/strings.xml
+++ b/packages/CarSystemUI/res/values-fa/strings.xml
@@ -28,4 +28,6 @@
<string name="user_add_user_message_update" msgid="7061671307004867811">"هر کاربری می‌تواند برنامه‌ها را برای همه کاربران دیگر به‌روزرسانی کند."</string>
<string name="car_loading_profile" msgid="4507385037552574474">"درحال بارگیری"</string>
<string name="car_loading_profile_developer_message" msgid="1660962766911529611">"بارگیری کاربر (از <xliff:g id="FROM_USER">%1$d</xliff:g> تا <xliff:g id="TO_USER">%2$d</xliff:g>)"</string>
+ <!-- no translation found for rear_view_camera_close_button_text (8430918817320533693) -->
+ <skip />
</resources>
diff --git a/packages/CarSystemUI/res/values-fi/strings.xml b/packages/CarSystemUI/res/values-fi/strings.xml
index 60689695725c..10bb0c5b782c 100644
--- a/packages/CarSystemUI/res/values-fi/strings.xml
+++ b/packages/CarSystemUI/res/values-fi/strings.xml
@@ -28,4 +28,6 @@
<string name="user_add_user_message_update" msgid="7061671307004867811">"Kaikki käyttäjät voivat päivittää muiden käyttäjien sovelluksia."</string>
<string name="car_loading_profile" msgid="4507385037552574474">"Ladataan"</string>
<string name="car_loading_profile_developer_message" msgid="1660962766911529611">"Ladataan käyttäjäprofiilia (<xliff:g id="FROM_USER">%1$d</xliff:g>–<xliff:g id="TO_USER">%2$d</xliff:g>)"</string>
+ <!-- no translation found for rear_view_camera_close_button_text (8430918817320533693) -->
+ <skip />
</resources>
diff --git a/packages/CarSystemUI/res/values-fr-rCA/strings.xml b/packages/CarSystemUI/res/values-fr-rCA/strings.xml
index 18e68c07d23d..bebd3f441410 100644
--- a/packages/CarSystemUI/res/values-fr-rCA/strings.xml
+++ b/packages/CarSystemUI/res/values-fr-rCA/strings.xml
@@ -28,4 +28,6 @@
<string name="user_add_user_message_update" msgid="7061671307004867811">"Tout utilisateur peut mettre à jour les applications pour tous les autres utilisateurs."</string>
<string name="car_loading_profile" msgid="4507385037552574474">"Chargement en cours…"</string>
<string name="car_loading_profile_developer_message" msgid="1660962766911529611">"Chargement de l\'utilisateur (de <xliff:g id="FROM_USER">%1$d</xliff:g> vers <xliff:g id="TO_USER">%2$d</xliff:g>) en cours…"</string>
+ <!-- no translation found for rear_view_camera_close_button_text (8430918817320533693) -->
+ <skip />
</resources>
diff --git a/packages/CarSystemUI/res/values-fr/strings.xml b/packages/CarSystemUI/res/values-fr/strings.xml
index 954df67d4b74..3d498d2f9ca7 100644
--- a/packages/CarSystemUI/res/values-fr/strings.xml
+++ b/packages/CarSystemUI/res/values-fr/strings.xml
@@ -28,4 +28,6 @@
<string name="user_add_user_message_update" msgid="7061671307004867811">"N\'importe quel utilisateur peut mettre à jour les applications pour tous les autres utilisateurs."</string>
<string name="car_loading_profile" msgid="4507385037552574474">"Chargement…"</string>
<string name="car_loading_profile_developer_message" msgid="1660962766911529611">"Chargement de l\'utilisateur (de <xliff:g id="FROM_USER">%1$d</xliff:g> à <xliff:g id="TO_USER">%2$d</xliff:g>)"</string>
+ <!-- no translation found for rear_view_camera_close_button_text (8430918817320533693) -->
+ <skip />
</resources>
diff --git a/packages/CarSystemUI/res/values-gl/strings.xml b/packages/CarSystemUI/res/values-gl/strings.xml
index 95bfbd30c0b8..e4586cc17a73 100644
--- a/packages/CarSystemUI/res/values-gl/strings.xml
+++ b/packages/CarSystemUI/res/values-gl/strings.xml
@@ -28,4 +28,6 @@
<string name="user_add_user_message_update" msgid="7061671307004867811">"Calquera usuario pode actualizar as aplicacións para o resto dos usuarios."</string>
<string name="car_loading_profile" msgid="4507385037552574474">"Cargando"</string>
<string name="car_loading_profile_developer_message" msgid="1660962766911529611">"Cargando usuario (do <xliff:g id="FROM_USER">%1$d</xliff:g> ao <xliff:g id="TO_USER">%2$d</xliff:g>)"</string>
+ <!-- no translation found for rear_view_camera_close_button_text (8430918817320533693) -->
+ <skip />
</resources>
diff --git a/packages/CarSystemUI/res/values-gu/strings.xml b/packages/CarSystemUI/res/values-gu/strings.xml
index dec991ce1400..ba884e410187 100644
--- a/packages/CarSystemUI/res/values-gu/strings.xml
+++ b/packages/CarSystemUI/res/values-gu/strings.xml
@@ -28,4 +28,6 @@
<string name="user_add_user_message_update" msgid="7061671307004867811">"કોઈપણ વપરાશકર્તા અન્ય બધા વપરાશકર્તાઓ માટે ઍપને અપડેટ કરી શકે છે."</string>
<string name="car_loading_profile" msgid="4507385037552574474">"લોડ કરી રહ્યાં છીએ"</string>
<string name="car_loading_profile_developer_message" msgid="1660962766911529611">"વપરાશકર્તાને લોડ કરી રહ્યાં છીએ (<xliff:g id="FROM_USER">%1$d</xliff:g>માંથી <xliff:g id="TO_USER">%2$d</xliff:g>માં)"</string>
+ <!-- no translation found for rear_view_camera_close_button_text (8430918817320533693) -->
+ <skip />
</resources>
diff --git a/packages/CarSystemUI/res/values-hi/strings.xml b/packages/CarSystemUI/res/values-hi/strings.xml
index 89b69608efbe..95454a53709f 100644
--- a/packages/CarSystemUI/res/values-hi/strings.xml
+++ b/packages/CarSystemUI/res/values-hi/strings.xml
@@ -28,4 +28,6 @@
<string name="user_add_user_message_update" msgid="7061671307004867811">"कोई भी उपयोगकर्ता, बाकी सभी उपयोगकर्ताओं के लिए ऐप्लिकेशन अपडेट कर सकता है."</string>
<string name="car_loading_profile" msgid="4507385037552574474">"लोड हो रही है"</string>
<string name="car_loading_profile_developer_message" msgid="1660962766911529611">"उपयोगकर्ता को लोड किया जा रहा है (<xliff:g id="FROM_USER">%1$d</xliff:g> से <xliff:g id="TO_USER">%2$d</xliff:g> पर)"</string>
+ <!-- no translation found for rear_view_camera_close_button_text (8430918817320533693) -->
+ <skip />
</resources>
diff --git a/packages/CarSystemUI/res/values-hr/strings.xml b/packages/CarSystemUI/res/values-hr/strings.xml
index 6baec74ddbff..f3aaf63eac18 100644
--- a/packages/CarSystemUI/res/values-hr/strings.xml
+++ b/packages/CarSystemUI/res/values-hr/strings.xml
@@ -28,4 +28,6 @@
<string name="user_add_user_message_update" msgid="7061671307004867811">"Svaki korisnik može ažurirati aplikacije za ostale korisnike."</string>
<string name="car_loading_profile" msgid="4507385037552574474">"Učitavanje"</string>
<string name="car_loading_profile_developer_message" msgid="1660962766911529611">"Učitavanje korisnika (od <xliff:g id="FROM_USER">%1$d</xliff:g> do <xliff:g id="TO_USER">%2$d</xliff:g>)"</string>
+ <!-- no translation found for rear_view_camera_close_button_text (8430918817320533693) -->
+ <skip />
</resources>
diff --git a/packages/CarSystemUI/res/values-hu/strings.xml b/packages/CarSystemUI/res/values-hu/strings.xml
index ffa512c4772a..b63ba8b8ed60 100644
--- a/packages/CarSystemUI/res/values-hu/strings.xml
+++ b/packages/CarSystemUI/res/values-hu/strings.xml
@@ -28,4 +28,6 @@
<string name="user_add_user_message_update" msgid="7061671307004867811">"Bármely felhasználó frissítheti az alkalmazásokat az összes felhasználó számára."</string>
<string name="car_loading_profile" msgid="4507385037552574474">"Betöltés"</string>
<string name="car_loading_profile_developer_message" msgid="1660962766911529611">"Felhasználó betöltése (<xliff:g id="FROM_USER">%1$d</xliff:g> → <xliff:g id="TO_USER">%2$d</xliff:g>)"</string>
+ <!-- no translation found for rear_view_camera_close_button_text (8430918817320533693) -->
+ <skip />
</resources>
diff --git a/packages/CarSystemUI/res/values-hy/strings.xml b/packages/CarSystemUI/res/values-hy/strings.xml
index ee6f74b4e5d8..e2a2c6bf459c 100644
--- a/packages/CarSystemUI/res/values-hy/strings.xml
+++ b/packages/CarSystemUI/res/values-hy/strings.xml
@@ -28,4 +28,6 @@
<string name="user_add_user_message_update" msgid="7061671307004867811">"Ցանկացած օգտատեր կարող է թարմացնել հավելվածները բոլոր մյուս հաշիվների համար։"</string>
<string name="car_loading_profile" msgid="4507385037552574474">"Բեռնում"</string>
<string name="car_loading_profile_developer_message" msgid="1660962766911529611">"Օգտատերը բեռնվում է (<xliff:g id="FROM_USER">%1$d</xliff:g> – <xliff:g id="TO_USER">%2$d</xliff:g>)"</string>
+ <!-- no translation found for rear_view_camera_close_button_text (8430918817320533693) -->
+ <skip />
</resources>
diff --git a/packages/CarSystemUI/res/values-in/strings.xml b/packages/CarSystemUI/res/values-in/strings.xml
index 901cbe759d63..0a70d261b77d 100644
--- a/packages/CarSystemUI/res/values-in/strings.xml
+++ b/packages/CarSystemUI/res/values-in/strings.xml
@@ -28,4 +28,6 @@
<string name="user_add_user_message_update" msgid="7061671307004867811">"Setiap pengguna dapat mengupdate aplikasi untuk semua pengguna lain."</string>
<string name="car_loading_profile" msgid="4507385037552574474">"Memuat"</string>
<string name="car_loading_profile_developer_message" msgid="1660962766911529611">"Memuat pengguna (dari <xliff:g id="FROM_USER">%1$d</xliff:g> menjadi <xliff:g id="TO_USER">%2$d</xliff:g>)"</string>
+ <!-- no translation found for rear_view_camera_close_button_text (8430918817320533693) -->
+ <skip />
</resources>
diff --git a/packages/CarSystemUI/res/values-is/strings.xml b/packages/CarSystemUI/res/values-is/strings.xml
index 13e71366ebd3..ea6b031c72b9 100644
--- a/packages/CarSystemUI/res/values-is/strings.xml
+++ b/packages/CarSystemUI/res/values-is/strings.xml
@@ -28,4 +28,6 @@
<string name="user_add_user_message_update" msgid="7061671307004867811">"Allir notendur geta uppfært forrit fyrir alla aðra notendur."</string>
<string name="car_loading_profile" msgid="4507385037552574474">"Hleður"</string>
<string name="car_loading_profile_developer_message" msgid="1660962766911529611">"Hleður notanda (frá <xliff:g id="FROM_USER">%1$d</xliff:g> til <xliff:g id="TO_USER">%2$d</xliff:g>)"</string>
+ <!-- no translation found for rear_view_camera_close_button_text (8430918817320533693) -->
+ <skip />
</resources>
diff --git a/packages/CarSystemUI/res/values-it/strings.xml b/packages/CarSystemUI/res/values-it/strings.xml
index f4f7ab719661..ecbcd5d9dadd 100644
--- a/packages/CarSystemUI/res/values-it/strings.xml
+++ b/packages/CarSystemUI/res/values-it/strings.xml
@@ -28,4 +28,6 @@
<string name="user_add_user_message_update" msgid="7061671307004867811">"Qualsiasi utente può aggiornare le app per tutti gli altri."</string>
<string name="car_loading_profile" msgid="4507385037552574474">"Caricamento"</string>
<string name="car_loading_profile_developer_message" msgid="1660962766911529611">"Caricamento dell\'utente (da <xliff:g id="FROM_USER">%1$d</xliff:g> a <xliff:g id="TO_USER">%2$d</xliff:g>)"</string>
+ <!-- no translation found for rear_view_camera_close_button_text (8430918817320533693) -->
+ <skip />
</resources>
diff --git a/packages/CarSystemUI/res/values-iw/strings.xml b/packages/CarSystemUI/res/values-iw/strings.xml
index a044b23709e1..fe182a3b7251 100644
--- a/packages/CarSystemUI/res/values-iw/strings.xml
+++ b/packages/CarSystemUI/res/values-iw/strings.xml
@@ -28,4 +28,6 @@
<string name="user_add_user_message_update" msgid="7061671307004867811">"כל משתמש יכול לעדכן אפליקציות לכל שאר המשתמשים."</string>
<string name="car_loading_profile" msgid="4507385037552574474">"בטעינה"</string>
<string name="car_loading_profile_developer_message" msgid="1660962766911529611">"המשתמש בטעינה (מהמשתמש <xliff:g id="FROM_USER">%1$d</xliff:g> אל <xliff:g id="TO_USER">%2$d</xliff:g>)"</string>
+ <!-- no translation found for rear_view_camera_close_button_text (8430918817320533693) -->
+ <skip />
</resources>
diff --git a/packages/CarSystemUI/res/values-ja/strings.xml b/packages/CarSystemUI/res/values-ja/strings.xml
index aae7dbff155e..14486758dcd1 100644
--- a/packages/CarSystemUI/res/values-ja/strings.xml
+++ b/packages/CarSystemUI/res/values-ja/strings.xml
@@ -28,4 +28,6 @@
<string name="user_add_user_message_update" msgid="7061671307004867811">"どのユーザーも他のすべてのユーザーに代わってアプリを更新できます。"</string>
<string name="car_loading_profile" msgid="4507385037552574474">"読み込んでいます"</string>
<string name="car_loading_profile_developer_message" msgid="1660962766911529611">"ユーザーを読み込んでいます(<xliff:g id="FROM_USER">%1$d</xliff:g>~<xliff:g id="TO_USER">%2$d</xliff:g>)"</string>
+ <!-- no translation found for rear_view_camera_close_button_text (8430918817320533693) -->
+ <skip />
</resources>
diff --git a/packages/CarSystemUI/res/values-ka/strings.xml b/packages/CarSystemUI/res/values-ka/strings.xml
index 19894d164189..0fef7e55f27e 100644
--- a/packages/CarSystemUI/res/values-ka/strings.xml
+++ b/packages/CarSystemUI/res/values-ka/strings.xml
@@ -28,4 +28,6 @@
<string name="user_add_user_message_update" msgid="7061671307004867811">"ნებისმიერ მომხმარებელს შეუძლია აპები ყველა სხვა მომხმარებლისათვის განაახლოს."</string>
<string name="car_loading_profile" msgid="4507385037552574474">"იტვირთება"</string>
<string name="car_loading_profile_developer_message" msgid="1660962766911529611">"იტვირთება მომხმარებელი (<xliff:g id="FROM_USER">%1$d</xliff:g>-დან <xliff:g id="TO_USER">%2$d</xliff:g>-მდე)"</string>
+ <!-- no translation found for rear_view_camera_close_button_text (8430918817320533693) -->
+ <skip />
</resources>
diff --git a/packages/CarSystemUI/res/values-kk/strings.xml b/packages/CarSystemUI/res/values-kk/strings.xml
index f9449be39540..a4cf78709515 100644
--- a/packages/CarSystemUI/res/values-kk/strings.xml
+++ b/packages/CarSystemUI/res/values-kk/strings.xml
@@ -28,4 +28,6 @@
<string name="user_add_user_message_update" msgid="7061671307004867811">"Кез келген пайдаланушы қолданбаларды басқа пайдаланушылар үшін жаңарта алады."</string>
<string name="car_loading_profile" msgid="4507385037552574474">"Жүктелуде"</string>
<string name="car_loading_profile_developer_message" msgid="1660962766911529611">"Пайдаланушы профилі жүктелуде (<xliff:g id="FROM_USER">%1$d</xliff:g> – <xliff:g id="TO_USER">%2$d</xliff:g>)"</string>
+ <!-- no translation found for rear_view_camera_close_button_text (8430918817320533693) -->
+ <skip />
</resources>
diff --git a/packages/CarSystemUI/res/values-km/strings.xml b/packages/CarSystemUI/res/values-km/strings.xml
index fbcab8431476..7b9a093d7f39 100644
--- a/packages/CarSystemUI/res/values-km/strings.xml
+++ b/packages/CarSystemUI/res/values-km/strings.xml
@@ -28,4 +28,6 @@
<string name="user_add_user_message_update" msgid="7061671307004867811">"អ្នកប្រើប្រាស់​ណាក៏​អាច​ដំឡើងកំណែ​កម្មវិធី​សម្រាប់​អ្នកប្រើប្រាស់ទាំងអស់​ផ្សេងទៀត​បានដែរ។"</string>
<string name="car_loading_profile" msgid="4507385037552574474">"កំពុងផ្ទុក"</string>
<string name="car_loading_profile_developer_message" msgid="1660962766911529611">"កំពុងផ្ទុក​អ្នកប្រើប្រាស់ (ពី <xliff:g id="FROM_USER">%1$d</xliff:g> ដល់ <xliff:g id="TO_USER">%2$d</xliff:g>)"</string>
+ <!-- no translation found for rear_view_camera_close_button_text (8430918817320533693) -->
+ <skip />
</resources>
diff --git a/packages/CarSystemUI/res/values-kn/strings.xml b/packages/CarSystemUI/res/values-kn/strings.xml
index 21c4cc02e207..34a83553d5c0 100644
--- a/packages/CarSystemUI/res/values-kn/strings.xml
+++ b/packages/CarSystemUI/res/values-kn/strings.xml
@@ -28,4 +28,6 @@
<string name="user_add_user_message_update" msgid="7061671307004867811">"ಯಾವುದೇ ಬಳಕೆದಾರರು ಎಲ್ಲಾ ಇತರೆ ಬಳಕೆದಾರರಿಗಾಗಿ ಆ್ಯಪ್‌ಗಳನ್ನು ಅಪ್‌ಡೇಟ್‌ ಮಾಡಬಹುದು."</string>
<string name="car_loading_profile" msgid="4507385037552574474">"ಲೋಡ್ ಆಗುತ್ತಿದೆ"</string>
<string name="car_loading_profile_developer_message" msgid="1660962766911529611">"ಬಳಕೆದಾರರನ್ನು ಲೋಡ್ ಮಾಡಲಾಗುತ್ತಿದೆ (<xliff:g id="FROM_USER">%1$d</xliff:g> ನಿಂದ <xliff:g id="TO_USER">%2$d</xliff:g> ವರೆಗೆ)"</string>
+ <!-- no translation found for rear_view_camera_close_button_text (8430918817320533693) -->
+ <skip />
</resources>
diff --git a/packages/CarSystemUI/res/values-ko/strings.xml b/packages/CarSystemUI/res/values-ko/strings.xml
index 6b670b018814..b570c5c6b81e 100644
--- a/packages/CarSystemUI/res/values-ko/strings.xml
+++ b/packages/CarSystemUI/res/values-ko/strings.xml
@@ -28,4 +28,6 @@
<string name="user_add_user_message_update" msgid="7061671307004867811">"누구나 다른 모든 사용자를 위해 앱을 업데이트할 수 있습니다."</string>
<string name="car_loading_profile" msgid="4507385037552574474">"로드 중"</string>
<string name="car_loading_profile_developer_message" msgid="1660962766911529611">"사용자 로드 중(<xliff:g id="FROM_USER">%1$d</xliff:g>님에서 <xliff:g id="TO_USER">%2$d</xliff:g>님으로)"</string>
+ <!-- no translation found for rear_view_camera_close_button_text (8430918817320533693) -->
+ <skip />
</resources>
diff --git a/packages/CarSystemUI/res/values-ky/strings.xml b/packages/CarSystemUI/res/values-ky/strings.xml
index b093363d0c23..c66b34ffb9c1 100644
--- a/packages/CarSystemUI/res/values-ky/strings.xml
+++ b/packages/CarSystemUI/res/values-ky/strings.xml
@@ -28,4 +28,6 @@
<string name="user_add_user_message_update" msgid="7061671307004867811">"Колдонмолорду бир колдонуучу калган бардык колдонуучулар үчүн да жаңырта алат."</string>
<string name="car_loading_profile" msgid="4507385037552574474">"Жүктөлүүдө"</string>
<string name="car_loading_profile_developer_message" msgid="1660962766911529611">"Колдонуучу тууралуу маалымат жүктөлүүдө (<xliff:g id="FROM_USER">%1$d</xliff:g> – <xliff:g id="TO_USER">%2$d</xliff:g>)"</string>
+ <!-- no translation found for rear_view_camera_close_button_text (8430918817320533693) -->
+ <skip />
</resources>
diff --git a/packages/CarSystemUI/res/values-lo/strings.xml b/packages/CarSystemUI/res/values-lo/strings.xml
index d2199e2a0cef..2bf19e03b82a 100644
--- a/packages/CarSystemUI/res/values-lo/strings.xml
+++ b/packages/CarSystemUI/res/values-lo/strings.xml
@@ -28,4 +28,6 @@
<string name="user_add_user_message_update" msgid="7061671307004867811">"ຜູ້ໃຊ້ຕ່າງໆສາມາດອັບເດດແອັບສຳລັບຜູ້ໃຊ້ອື່ນທັງໝົດໄດ້."</string>
<string name="car_loading_profile" msgid="4507385037552574474">"ກຳລັງໂຫຼດ"</string>
<string name="car_loading_profile_developer_message" msgid="1660962766911529611">"ກຳລັງໂຫຼດຜູ້ໃຊ້ (ຈາກ <xliff:g id="FROM_USER">%1$d</xliff:g> ໄປຍັງ <xliff:g id="TO_USER">%2$d</xliff:g>)"</string>
+ <!-- no translation found for rear_view_camera_close_button_text (8430918817320533693) -->
+ <skip />
</resources>
diff --git a/packages/CarSystemUI/res/values-lt/strings.xml b/packages/CarSystemUI/res/values-lt/strings.xml
index 26690002416e..1cae1e907193 100644
--- a/packages/CarSystemUI/res/values-lt/strings.xml
+++ b/packages/CarSystemUI/res/values-lt/strings.xml
@@ -28,4 +28,6 @@
<string name="user_add_user_message_update" msgid="7061671307004867811">"Bet kuris naudotojas gali atnaujinti visų kitų naudotojų programas."</string>
<string name="car_loading_profile" msgid="4507385037552574474">"Įkeliama"</string>
<string name="car_loading_profile_developer_message" msgid="1660962766911529611">"Įkeliamas naudotojo profilis (<xliff:g id="FROM_USER">%1$d</xliff:g> – <xliff:g id="TO_USER">%2$d</xliff:g>)"</string>
+ <!-- no translation found for rear_view_camera_close_button_text (8430918817320533693) -->
+ <skip />
</resources>
diff --git a/packages/CarSystemUI/res/values-lv/strings.xml b/packages/CarSystemUI/res/values-lv/strings.xml
index 87b4ede4383a..62b8bf8d98eb 100644
--- a/packages/CarSystemUI/res/values-lv/strings.xml
+++ b/packages/CarSystemUI/res/values-lv/strings.xml
@@ -28,4 +28,6 @@
<string name="user_add_user_message_update" msgid="7061671307004867811">"Ikviens lietotājs var atjaunināt lietotnes visu lietotāju vārdā."</string>
<string name="car_loading_profile" msgid="4507385037552574474">"Notiek ielāde…"</string>
<string name="car_loading_profile_developer_message" msgid="1660962766911529611">"Notiek lietotāja profila ielāde (<xliff:g id="FROM_USER">%1$d</xliff:g>–<xliff:g id="TO_USER">%2$d</xliff:g>)…"</string>
+ <!-- no translation found for rear_view_camera_close_button_text (8430918817320533693) -->
+ <skip />
</resources>
diff --git a/packages/CarSystemUI/res/values-mk/strings.xml b/packages/CarSystemUI/res/values-mk/strings.xml
index f8fd02cb071d..3e7ad63ae2d9 100644
--- a/packages/CarSystemUI/res/values-mk/strings.xml
+++ b/packages/CarSystemUI/res/values-mk/strings.xml
@@ -28,4 +28,6 @@
<string name="user_add_user_message_update" msgid="7061671307004867811">"Секој корисник може да ажурира апликации за сите други корисници."</string>
<string name="car_loading_profile" msgid="4507385037552574474">"Се вчитува"</string>
<string name="car_loading_profile_developer_message" msgid="1660962766911529611">"Се вчитува корисникот (од <xliff:g id="FROM_USER">%1$d</xliff:g> до <xliff:g id="TO_USER">%2$d</xliff:g>)"</string>
+ <!-- no translation found for rear_view_camera_close_button_text (8430918817320533693) -->
+ <skip />
</resources>
diff --git a/packages/CarSystemUI/res/values-ml/strings.xml b/packages/CarSystemUI/res/values-ml/strings.xml
index 343157160105..3bc7557b5484 100644
--- a/packages/CarSystemUI/res/values-ml/strings.xml
+++ b/packages/CarSystemUI/res/values-ml/strings.xml
@@ -28,4 +28,6 @@
<string name="user_add_user_message_update" msgid="7061671307004867811">"ഏതൊരു ഉപയോക്താവിനും മറ്റെല്ലാ ഉപയോക്താക്കൾക്കുമായി ആപ്പുകൾ അപ്‌ഡേറ്റ് ചെയ്യാനാവും."</string>
<string name="car_loading_profile" msgid="4507385037552574474">"ലോഡ് ചെയ്യുന്നു"</string>
<string name="car_loading_profile_developer_message" msgid="1660962766911529611">"ഉപയോക്തൃ പ്രൊഫൈൽ ലോഡ് ചെയ്യുന്നു (<xliff:g id="FROM_USER">%1$d</xliff:g> എന്നതിൽ നിന്ന് <xliff:g id="TO_USER">%2$d</xliff:g> എന്നതിലേക്ക്)"</string>
+ <!-- no translation found for rear_view_camera_close_button_text (8430918817320533693) -->
+ <skip />
</resources>
diff --git a/packages/CarSystemUI/res/values-mn/strings.xml b/packages/CarSystemUI/res/values-mn/strings.xml
index 5bd76dc7e067..45921d26172e 100644
--- a/packages/CarSystemUI/res/values-mn/strings.xml
+++ b/packages/CarSystemUI/res/values-mn/strings.xml
@@ -28,4 +28,6 @@
<string name="user_add_user_message_update" msgid="7061671307004867811">"Бусад бүх хэрэглэгчийн аппыг дурын хэрэглэгч шинэчлэх боломжтой."</string>
<string name="car_loading_profile" msgid="4507385037552574474">"Ачаалж байна"</string>
<string name="car_loading_profile_developer_message" msgid="1660962766911529611">"Хэрэглэгчийг ачаалж байна (<xliff:g id="FROM_USER">%1$d</xliff:g>-с <xliff:g id="TO_USER">%2$d</xliff:g> хүртэл)"</string>
+ <!-- no translation found for rear_view_camera_close_button_text (8430918817320533693) -->
+ <skip />
</resources>
diff --git a/packages/CarSystemUI/res/values-mr/strings.xml b/packages/CarSystemUI/res/values-mr/strings.xml
index 2366465e1a9f..fdbab4fbc4f2 100644
--- a/packages/CarSystemUI/res/values-mr/strings.xml
+++ b/packages/CarSystemUI/res/values-mr/strings.xml
@@ -28,4 +28,6 @@
<string name="user_add_user_message_update" msgid="7061671307004867811">"कोणताही वापरकर्ता इतर सर्व वापरकर्त्यांसाठी अ‍ॅप्स अपडेट करू शकतो."</string>
<string name="car_loading_profile" msgid="4507385037552574474">"लोड करत आहे"</string>
<string name="car_loading_profile_developer_message" msgid="1660962766911529611">"वापरकर्ता लोड करत आहे (<xliff:g id="FROM_USER">%1$d</xliff:g> पासून <xliff:g id="TO_USER">%2$d</xliff:g> पर्यंत)"</string>
+ <!-- no translation found for rear_view_camera_close_button_text (8430918817320533693) -->
+ <skip />
</resources>
diff --git a/packages/CarSystemUI/res/values-ms/strings.xml b/packages/CarSystemUI/res/values-ms/strings.xml
index 29ac83afc12c..1a43d9c7cdef 100644
--- a/packages/CarSystemUI/res/values-ms/strings.xml
+++ b/packages/CarSystemUI/res/values-ms/strings.xml
@@ -28,4 +28,6 @@
<string name="user_add_user_message_update" msgid="7061671307004867811">"Mana-mana pengguna boleh mengemas kini apl untuk semua pengguna lain."</string>
<string name="car_loading_profile" msgid="4507385037552574474">"Memuatkan"</string>
<string name="car_loading_profile_developer_message" msgid="1660962766911529611">"Memuatkan pengguna (daripada <xliff:g id="FROM_USER">%1$d</xliff:g> hingga <xliff:g id="TO_USER">%2$d</xliff:g>)"</string>
+ <!-- no translation found for rear_view_camera_close_button_text (8430918817320533693) -->
+ <skip />
</resources>
diff --git a/packages/CarSystemUI/res/values-my/strings.xml b/packages/CarSystemUI/res/values-my/strings.xml
index 7f240b430471..4f3922b373b5 100644
--- a/packages/CarSystemUI/res/values-my/strings.xml
+++ b/packages/CarSystemUI/res/values-my/strings.xml
@@ -28,4 +28,6 @@
<string name="user_add_user_message_update" msgid="7061671307004867811">"မည်သူမဆို အသုံးပြုသူအားလုံးအတွက် အက်ပ်များကို အပ်ဒိတ်လုပ်နိုင်သည်။"</string>
<string name="car_loading_profile" msgid="4507385037552574474">"ဖွင့်နေသည်"</string>
<string name="car_loading_profile_developer_message" msgid="1660962766911529611">"အသုံးပြုသူကို ဖွင့်နေသည် (<xliff:g id="FROM_USER">%1$d</xliff:g> မှ <xliff:g id="TO_USER">%2$d</xliff:g> သို့)"</string>
+ <!-- no translation found for rear_view_camera_close_button_text (8430918817320533693) -->
+ <skip />
</resources>
diff --git a/packages/CarSystemUI/res/values-nb/strings.xml b/packages/CarSystemUI/res/values-nb/strings.xml
index c1cfcf727859..5b6166feba0f 100644
--- a/packages/CarSystemUI/res/values-nb/strings.xml
+++ b/packages/CarSystemUI/res/values-nb/strings.xml
@@ -28,4 +28,6 @@
<string name="user_add_user_message_update" msgid="7061671307004867811">"Alle brukere kan oppdatere apper for alle andre brukere."</string>
<string name="car_loading_profile" msgid="4507385037552574474">"Laster inn"</string>
<string name="car_loading_profile_developer_message" msgid="1660962766911529611">"Laster inn brukeren (fra <xliff:g id="FROM_USER">%1$d</xliff:g> til <xliff:g id="TO_USER">%2$d</xliff:g>)"</string>
+ <!-- no translation found for rear_view_camera_close_button_text (8430918817320533693) -->
+ <skip />
</resources>
diff --git a/packages/CarSystemUI/res/values-ne/strings.xml b/packages/CarSystemUI/res/values-ne/strings.xml
index 70bcfc763cf2..e9eb4d8bdac7 100644
--- a/packages/CarSystemUI/res/values-ne/strings.xml
+++ b/packages/CarSystemUI/res/values-ne/strings.xml
@@ -28,4 +28,6 @@
<string name="user_add_user_message_update" msgid="7061671307004867811">"सबै प्रयोगकर्ताले अन्य प्रयोगकर्ताका अनुप्रयोगहरू अद्यावधिक गर्न सक्छन्।"</string>
<string name="car_loading_profile" msgid="4507385037552574474">"लोड गरिँदै"</string>
<string name="car_loading_profile_developer_message" msgid="1660962766911529611">"प्रयोगकर्तासम्बन्धी जानकारी लोड गरिँदै (<xliff:g id="FROM_USER">%1$d</xliff:g> बाट <xliff:g id="TO_USER">%2$d</xliff:g> मा)"</string>
+ <!-- no translation found for rear_view_camera_close_button_text (8430918817320533693) -->
+ <skip />
</resources>
diff --git a/packages/CarSystemUI/res/values-nl/strings.xml b/packages/CarSystemUI/res/values-nl/strings.xml
index 95a76467b078..d79f2b1d10f4 100644
--- a/packages/CarSystemUI/res/values-nl/strings.xml
+++ b/packages/CarSystemUI/res/values-nl/strings.xml
@@ -28,4 +28,6 @@
<string name="user_add_user_message_update" msgid="7061671307004867811">"Elke gebruiker kan apps updaten voor alle andere gebruikers"</string>
<string name="car_loading_profile" msgid="4507385037552574474">"Laden"</string>
<string name="car_loading_profile_developer_message" msgid="1660962766911529611">"Gebruiker laden (van <xliff:g id="FROM_USER">%1$d</xliff:g> naar <xliff:g id="TO_USER">%2$d</xliff:g>)"</string>
+ <!-- no translation found for rear_view_camera_close_button_text (8430918817320533693) -->
+ <skip />
</resources>
diff --git a/packages/CarSystemUI/res/values-or/strings.xml b/packages/CarSystemUI/res/values-or/strings.xml
index b0b59b348594..58f59e4c4dbf 100644
--- a/packages/CarSystemUI/res/values-or/strings.xml
+++ b/packages/CarSystemUI/res/values-or/strings.xml
@@ -28,4 +28,6 @@
<string name="user_add_user_message_update" msgid="7061671307004867811">"ଯେ କୌଣସି ଉପଯୋଗକର୍ତ୍ତା ଅନ୍ୟ ସମସ୍ତ ଉପଯୋଗକର୍ତ୍ତାଙ୍କ ପାଇଁ ଆପଗୁଡ଼ିକୁ ଅପଡେଟ୍ କରିପାରିବେ।"</string>
<string name="car_loading_profile" msgid="4507385037552574474">"ଲୋଡ୍ କରାଯାଉଛି"</string>
<string name="car_loading_profile_developer_message" msgid="1660962766911529611">"ଉପଯୋଗକର୍ତ୍ତାଙ୍କୁ ଲୋଡ୍ କରାଯାଉଛି (<xliff:g id="FROM_USER">%1$d</xliff:g>ଙ୍କ ଠାରୁ <xliff:g id="TO_USER">%2$d</xliff:g> ପର୍ଯ୍ୟନ୍ତ)"</string>
+ <!-- no translation found for rear_view_camera_close_button_text (8430918817320533693) -->
+ <skip />
</resources>
diff --git a/packages/CarSystemUI/res/values-pa/strings.xml b/packages/CarSystemUI/res/values-pa/strings.xml
index e7efca1894b7..e73e20a5fc85 100644
--- a/packages/CarSystemUI/res/values-pa/strings.xml
+++ b/packages/CarSystemUI/res/values-pa/strings.xml
@@ -28,4 +28,6 @@
<string name="user_add_user_message_update" msgid="7061671307004867811">"ਕੋਈ ਵੀ ਵਰਤੋਂਕਾਰ ਹੋਰ ਸਾਰੇ ਵਰਤੋਂਕਾਰਾਂ ਦੀਆਂ ਐਪਾਂ ਨੂੰ ਅੱਪਡੇਟ ਕਰ ਸਕਦਾ ਹੈ।"</string>
<string name="car_loading_profile" msgid="4507385037552574474">"ਲੋਡ ਕੀਤਾ ਜਾ ਰਿਹਾ ਹੈ"</string>
<string name="car_loading_profile_developer_message" msgid="1660962766911529611">"ਵਰਤੋਂਕਾਰ ਨੂੰ ਲੋਡ ਕੀਤਾ ਜਾ ਰਿਹਾ ਹੈ (<xliff:g id="FROM_USER">%1$d</xliff:g> ਤੋਂ <xliff:g id="TO_USER">%2$d</xliff:g> ਤੱਕ)"</string>
+ <!-- no translation found for rear_view_camera_close_button_text (8430918817320533693) -->
+ <skip />
</resources>
diff --git a/packages/CarSystemUI/res/values-pl/strings.xml b/packages/CarSystemUI/res/values-pl/strings.xml
index 37d0ef171599..dd8c1892b63e 100644
--- a/packages/CarSystemUI/res/values-pl/strings.xml
+++ b/packages/CarSystemUI/res/values-pl/strings.xml
@@ -28,4 +28,6 @@
<string name="user_add_user_message_update" msgid="7061671307004867811">"Każdy użytkownik może aktualizować aplikacje wszystkich innych użytkowników."</string>
<string name="car_loading_profile" msgid="4507385037552574474">"Ładuję"</string>
<string name="car_loading_profile_developer_message" msgid="1660962766911529611">"Ładuję użytkownika (od <xliff:g id="FROM_USER">%1$d</xliff:g> do <xliff:g id="TO_USER">%2$d</xliff:g>)"</string>
+ <!-- no translation found for rear_view_camera_close_button_text (8430918817320533693) -->
+ <skip />
</resources>
diff --git a/packages/CarSystemUI/res/values-pt-rPT/strings.xml b/packages/CarSystemUI/res/values-pt-rPT/strings.xml
index 182f5b58d1b1..c7f5ecf00707 100644
--- a/packages/CarSystemUI/res/values-pt-rPT/strings.xml
+++ b/packages/CarSystemUI/res/values-pt-rPT/strings.xml
@@ -28,4 +28,6 @@
<string name="user_add_user_message_update" msgid="7061671307004867811">"Qualquer utilizador pode atualizar apps para todos os outros utilizadores."</string>
<string name="car_loading_profile" msgid="4507385037552574474">"A carregar…"</string>
<string name="car_loading_profile_developer_message" msgid="1660962766911529611">"A carregar o utilizador (de <xliff:g id="FROM_USER">%1$d</xliff:g> para <xliff:g id="TO_USER">%2$d</xliff:g>)…"</string>
+ <!-- no translation found for rear_view_camera_close_button_text (8430918817320533693) -->
+ <skip />
</resources>
diff --git a/packages/CarSystemUI/res/values-pt/strings.xml b/packages/CarSystemUI/res/values-pt/strings.xml
index 5c8394a51599..0712fb82f7fd 100644
--- a/packages/CarSystemUI/res/values-pt/strings.xml
+++ b/packages/CarSystemUI/res/values-pt/strings.xml
@@ -28,4 +28,6 @@
<string name="user_add_user_message_update" msgid="7061671307004867811">"Qualquer usuário pode atualizar apps para os demais usuários."</string>
<string name="car_loading_profile" msgid="4507385037552574474">"Carregando"</string>
<string name="car_loading_profile_developer_message" msgid="1660962766911529611">"Carregando usuário (de <xliff:g id="FROM_USER">%1$d</xliff:g> para <xliff:g id="TO_USER">%2$d</xliff:g>)"</string>
+ <!-- no translation found for rear_view_camera_close_button_text (8430918817320533693) -->
+ <skip />
</resources>
diff --git a/packages/CarSystemUI/res/values-ro/strings.xml b/packages/CarSystemUI/res/values-ro/strings.xml
index 25ecbb6453b0..60fd4fef41c0 100644
--- a/packages/CarSystemUI/res/values-ro/strings.xml
+++ b/packages/CarSystemUI/res/values-ro/strings.xml
@@ -28,4 +28,6 @@
<string name="user_add_user_message_update" msgid="7061671307004867811">"Orice utilizator poate actualiza aplicațiile pentru toți ceilalți utilizatori."</string>
<string name="car_loading_profile" msgid="4507385037552574474">"Se încarcă"</string>
<string name="car_loading_profile_developer_message" msgid="1660962766911529611">"Se încarcă utilizatorul (de la <xliff:g id="FROM_USER">%1$d</xliff:g> la <xliff:g id="TO_USER">%2$d</xliff:g>)"</string>
+ <!-- no translation found for rear_view_camera_close_button_text (8430918817320533693) -->
+ <skip />
</resources>
diff --git a/packages/CarSystemUI/res/values-ru/strings.xml b/packages/CarSystemUI/res/values-ru/strings.xml
index e93d25d1acdc..a043d24789a9 100644
--- a/packages/CarSystemUI/res/values-ru/strings.xml
+++ b/packages/CarSystemUI/res/values-ru/strings.xml
@@ -28,4 +28,6 @@
<string name="user_add_user_message_update" msgid="7061671307004867811">"Любой пользователь устройства может обновлять приложения для всех аккаунтов."</string>
<string name="car_loading_profile" msgid="4507385037552574474">"Загрузка…"</string>
<string name="car_loading_profile_developer_message" msgid="1660962766911529611">"Загрузка профиля пользователя (с <xliff:g id="FROM_USER">%1$d</xliff:g> по <xliff:g id="TO_USER">%2$d</xliff:g>)…"</string>
+ <!-- no translation found for rear_view_camera_close_button_text (8430918817320533693) -->
+ <skip />
</resources>
diff --git a/packages/CarSystemUI/res/values-si/strings.xml b/packages/CarSystemUI/res/values-si/strings.xml
index 947cb0a53206..e14f64a7bca8 100644
--- a/packages/CarSystemUI/res/values-si/strings.xml
+++ b/packages/CarSystemUI/res/values-si/strings.xml
@@ -28,4 +28,6 @@
<string name="user_add_user_message_update" msgid="7061671307004867811">"සියලුම අනෙක් පරිශීලකයින් සඳහා ඕනෑම පරිශීලකයෙකුට යෙදුම් යාවත්කාලීන කළ හැක."</string>
<string name="car_loading_profile" msgid="4507385037552574474">"පූරණය වෙමින්"</string>
<string name="car_loading_profile_developer_message" msgid="1660962766911529611">"පරිශීලකයා පූරණය වෙමින් (<xliff:g id="FROM_USER">%1$d</xliff:g> සිට <xliff:g id="TO_USER">%2$d</xliff:g> වෙත)"</string>
+ <!-- no translation found for rear_view_camera_close_button_text (8430918817320533693) -->
+ <skip />
</resources>
diff --git a/packages/CarSystemUI/res/values-sk/strings.xml b/packages/CarSystemUI/res/values-sk/strings.xml
index ea99f0faf5e0..8f98983877d9 100644
--- a/packages/CarSystemUI/res/values-sk/strings.xml
+++ b/packages/CarSystemUI/res/values-sk/strings.xml
@@ -28,4 +28,6 @@
<string name="user_add_user_message_update" msgid="7061671307004867811">"Ktorýkoľvek používateľ môže aktualizovať aplikácie všetkých ostatných používateľov."</string>
<string name="car_loading_profile" msgid="4507385037552574474">"Načítava sa"</string>
<string name="car_loading_profile_developer_message" msgid="1660962766911529611">"Načítava sa používateľ (predchádzajúci: <xliff:g id="FROM_USER">%1$d</xliff:g>, nasledujúci: <xliff:g id="TO_USER">%2$d</xliff:g>)"</string>
+ <!-- no translation found for rear_view_camera_close_button_text (8430918817320533693) -->
+ <skip />
</resources>
diff --git a/packages/CarSystemUI/res/values-sl/strings.xml b/packages/CarSystemUI/res/values-sl/strings.xml
index 32fd50e9cb8b..6b471845b657 100644
--- a/packages/CarSystemUI/res/values-sl/strings.xml
+++ b/packages/CarSystemUI/res/values-sl/strings.xml
@@ -28,4 +28,6 @@
<string name="user_add_user_message_update" msgid="7061671307004867811">"Vsak uporabnik lahko posodobi aplikacije za vse druge uporabnike."</string>
<string name="car_loading_profile" msgid="4507385037552574474">"Nalaganje"</string>
<string name="car_loading_profile_developer_message" msgid="1660962766911529611">"Nalaganje uporabnika (od uporabnika <xliff:g id="FROM_USER">%1$d</xliff:g> do uporabnika <xliff:g id="TO_USER">%2$d</xliff:g>)"</string>
+ <!-- no translation found for rear_view_camera_close_button_text (8430918817320533693) -->
+ <skip />
</resources>
diff --git a/packages/CarSystemUI/res/values-sq/strings.xml b/packages/CarSystemUI/res/values-sq/strings.xml
index 6fdd06c7d4d6..18ea40131817 100644
--- a/packages/CarSystemUI/res/values-sq/strings.xml
+++ b/packages/CarSystemUI/res/values-sq/strings.xml
@@ -28,4 +28,6 @@
<string name="user_add_user_message_update" msgid="7061671307004867811">"Çdo përdorues mund t\'i përditësojë aplikacionet për të gjithë përdoruesit e tjerë."</string>
<string name="car_loading_profile" msgid="4507385037552574474">"Po ngarkohet"</string>
<string name="car_loading_profile_developer_message" msgid="1660962766911529611">"Përdoruesi po ngarkohet (nga <xliff:g id="FROM_USER">%1$d</xliff:g> te <xliff:g id="TO_USER">%2$d</xliff:g>)"</string>
+ <!-- no translation found for rear_view_camera_close_button_text (8430918817320533693) -->
+ <skip />
</resources>
diff --git a/packages/CarSystemUI/res/values-sr/strings.xml b/packages/CarSystemUI/res/values-sr/strings.xml
index 494aeaa0f1f9..878a1c1aa425 100644
--- a/packages/CarSystemUI/res/values-sr/strings.xml
+++ b/packages/CarSystemUI/res/values-sr/strings.xml
@@ -28,4 +28,6 @@
<string name="user_add_user_message_update" msgid="7061671307004867811">"Сваки корисник може да ажурира апликације за све остале кориснике."</string>
<string name="car_loading_profile" msgid="4507385037552574474">"Учитава се"</string>
<string name="car_loading_profile_developer_message" msgid="1660962766911529611">"Профил корисника се учитава (из<xliff:g id="FROM_USER">%1$d</xliff:g> у <xliff:g id="TO_USER">%2$d</xliff:g>)"</string>
+ <!-- no translation found for rear_view_camera_close_button_text (8430918817320533693) -->
+ <skip />
</resources>
diff --git a/packages/CarSystemUI/res/values-sv/strings.xml b/packages/CarSystemUI/res/values-sv/strings.xml
index 65481cdf2533..905dd445eeab 100644
--- a/packages/CarSystemUI/res/values-sv/strings.xml
+++ b/packages/CarSystemUI/res/values-sv/strings.xml
@@ -28,4 +28,6 @@
<string name="user_add_user_message_update" msgid="7061671307004867811">"Alla användare kan uppdatera appar för andra användare."</string>
<string name="car_loading_profile" msgid="4507385037552574474">"Läser in"</string>
<string name="car_loading_profile_developer_message" msgid="1660962766911529611">"Läser in användare (från <xliff:g id="FROM_USER">%1$d</xliff:g> till <xliff:g id="TO_USER">%2$d</xliff:g>)"</string>
+ <!-- no translation found for rear_view_camera_close_button_text (8430918817320533693) -->
+ <skip />
</resources>
diff --git a/packages/CarSystemUI/res/values-sw/strings.xml b/packages/CarSystemUI/res/values-sw/strings.xml
index a79d628e6786..3cb6098a3f1b 100644
--- a/packages/CarSystemUI/res/values-sw/strings.xml
+++ b/packages/CarSystemUI/res/values-sw/strings.xml
@@ -28,4 +28,6 @@
<string name="user_add_user_message_update" msgid="7061671307004867811">"Mtumiaji yeyote anaweza kusasisha programu za watumiaji wengine."</string>
<string name="car_loading_profile" msgid="4507385037552574474">"Inapakia"</string>
<string name="car_loading_profile_developer_message" msgid="1660962766911529611">"Inapakia wasifu wa mtumiaji (kutoka <xliff:g id="FROM_USER">%1$d</xliff:g> kuwa <xliff:g id="TO_USER">%2$d</xliff:g>)"</string>
+ <!-- no translation found for rear_view_camera_close_button_text (8430918817320533693) -->
+ <skip />
</resources>
diff --git a/packages/CarSystemUI/res/values-ta/strings.xml b/packages/CarSystemUI/res/values-ta/strings.xml
index 849b40d36ccd..de52edee1621 100644
--- a/packages/CarSystemUI/res/values-ta/strings.xml
+++ b/packages/CarSystemUI/res/values-ta/strings.xml
@@ -28,4 +28,6 @@
<string name="user_add_user_message_update" msgid="7061671307004867811">"எந்தப் பயனரும் பிற பயனர்கள் சார்பாக ஆப்ஸைப் புதுப்பிக்க முடியும்."</string>
<string name="car_loading_profile" msgid="4507385037552574474">"ஏற்றுகிறது"</string>
<string name="car_loading_profile_developer_message" msgid="1660962766911529611">"பயனர் தகவலை ஏற்றுகிறது (<xliff:g id="FROM_USER">%1$d</xliff:g>லிருந்து <xliff:g id="TO_USER">%2$d</xliff:g> வரை)"</string>
+ <!-- no translation found for rear_view_camera_close_button_text (8430918817320533693) -->
+ <skip />
</resources>
diff --git a/packages/CarSystemUI/res/values-te/strings.xml b/packages/CarSystemUI/res/values-te/strings.xml
index 83bb24a64a46..fff0845dfb6c 100644
--- a/packages/CarSystemUI/res/values-te/strings.xml
+++ b/packages/CarSystemUI/res/values-te/strings.xml
@@ -28,4 +28,6 @@
<string name="user_add_user_message_update" msgid="7061671307004867811">"ఏ యూజర్ అయినా మిగతా యూజర్‌ల కోసం యాప్‌లను అప్‌డేట్ చేయవచ్చు."</string>
<string name="car_loading_profile" msgid="4507385037552574474">"లోడ్ అవుతోంది"</string>
<string name="car_loading_profile_developer_message" msgid="1660962766911529611">"యూజర్‌ను లోడ్ చేస్తోంది (<xliff:g id="FROM_USER">%1$d</xliff:g> నుండి <xliff:g id="TO_USER">%2$d</xliff:g> వరకు)"</string>
+ <!-- no translation found for rear_view_camera_close_button_text (8430918817320533693) -->
+ <skip />
</resources>
diff --git a/packages/CarSystemUI/res/values-th/strings.xml b/packages/CarSystemUI/res/values-th/strings.xml
index fa99ac1928c1..8f3012b5b4a5 100644
--- a/packages/CarSystemUI/res/values-th/strings.xml
+++ b/packages/CarSystemUI/res/values-th/strings.xml
@@ -28,4 +28,6 @@
<string name="user_add_user_message_update" msgid="7061671307004867811">"ผู้ใช้ทุกคนจะอัปเดตแอปให้แก่ผู้ใช้คนอื่นๆ ได้"</string>
<string name="car_loading_profile" msgid="4507385037552574474">"กำลังโหลด"</string>
<string name="car_loading_profile_developer_message" msgid="1660962766911529611">"กำลังโหลดผู้ใช้ (จาก <xliff:g id="FROM_USER">%1$d</xliff:g> ถึง <xliff:g id="TO_USER">%2$d</xliff:g>)"</string>
+ <!-- no translation found for rear_view_camera_close_button_text (8430918817320533693) -->
+ <skip />
</resources>
diff --git a/packages/CarSystemUI/res/values-tl/strings.xml b/packages/CarSystemUI/res/values-tl/strings.xml
index c6f5f59acf0d..5b0e3b3cf19c 100644
--- a/packages/CarSystemUI/res/values-tl/strings.xml
+++ b/packages/CarSystemUI/res/values-tl/strings.xml
@@ -28,4 +28,6 @@
<string name="user_add_user_message_update" msgid="7061671307004867811">"Puwedeng i-update ng sinumang user ang mga app para sa lahat ng iba pang user."</string>
<string name="car_loading_profile" msgid="4507385037552574474">"Naglo-load"</string>
<string name="car_loading_profile_developer_message" msgid="1660962766911529611">"Nilo-load ang user (mula kay <xliff:g id="FROM_USER">%1$d</xliff:g> papunta kay <xliff:g id="TO_USER">%2$d</xliff:g>)"</string>
+ <!-- no translation found for rear_view_camera_close_button_text (8430918817320533693) -->
+ <skip />
</resources>
diff --git a/packages/CarSystemUI/res/values-tr/strings.xml b/packages/CarSystemUI/res/values-tr/strings.xml
index a76812769dae..81fa01c16058 100644
--- a/packages/CarSystemUI/res/values-tr/strings.xml
+++ b/packages/CarSystemUI/res/values-tr/strings.xml
@@ -28,4 +28,6 @@
<string name="user_add_user_message_update" msgid="7061671307004867811">"Herhangi bir kullanıcı, diğer tüm kullanıcılar için uygulamaları güncelleyebilir."</string>
<string name="car_loading_profile" msgid="4507385037552574474">"Yükleniyor"</string>
<string name="car_loading_profile_developer_message" msgid="1660962766911529611">"Kullanıcı yükleniyor (<xliff:g id="FROM_USER">%1$d</xliff:g> kullanıcısından <xliff:g id="TO_USER">%2$d</xliff:g> kullanıcısına)"</string>
+ <!-- no translation found for rear_view_camera_close_button_text (8430918817320533693) -->
+ <skip />
</resources>
diff --git a/packages/CarSystemUI/res/values-uk/strings.xml b/packages/CarSystemUI/res/values-uk/strings.xml
index c424d87ace6e..b7031c698815 100644
--- a/packages/CarSystemUI/res/values-uk/strings.xml
+++ b/packages/CarSystemUI/res/values-uk/strings.xml
@@ -28,4 +28,6 @@
<string name="user_add_user_message_update" msgid="7061671307004867811">"Усі користувачі можуть оновлювати додатки для решти людей."</string>
<string name="car_loading_profile" msgid="4507385037552574474">"Завантаження"</string>
<string name="car_loading_profile_developer_message" msgid="1660962766911529611">"Завантаження профілю користувача (від <xliff:g id="FROM_USER">%1$d</xliff:g> до <xliff:g id="TO_USER">%2$d</xliff:g>)"</string>
+ <!-- no translation found for rear_view_camera_close_button_text (8430918817320533693) -->
+ <skip />
</resources>
diff --git a/packages/CarSystemUI/res/values-ur/strings.xml b/packages/CarSystemUI/res/values-ur/strings.xml
index 063dcbc4ecd1..ef65c7516956 100644
--- a/packages/CarSystemUI/res/values-ur/strings.xml
+++ b/packages/CarSystemUI/res/values-ur/strings.xml
@@ -28,4 +28,6 @@
<string name="user_add_user_message_update" msgid="7061671307004867811">"کوئی بھی صارف دیگر سبھی صارفین کے لیے ایپس کو اپ ڈیٹ کر سکتا ہے۔"</string>
<string name="car_loading_profile" msgid="4507385037552574474">"لوڈ ہو رہی ہے"</string>
<string name="car_loading_profile_developer_message" msgid="1660962766911529611">"صارف کی نئی پروفائل لوڈ ہو رہی ہے (<xliff:g id="FROM_USER">%1$d</xliff:g> سے <xliff:g id="TO_USER">%2$d</xliff:g> کو)"</string>
+ <!-- no translation found for rear_view_camera_close_button_text (8430918817320533693) -->
+ <skip />
</resources>
diff --git a/packages/CarSystemUI/res/values-uz/strings.xml b/packages/CarSystemUI/res/values-uz/strings.xml
index adef2add435f..471e4591265a 100644
--- a/packages/CarSystemUI/res/values-uz/strings.xml
+++ b/packages/CarSystemUI/res/values-uz/strings.xml
@@ -28,4 +28,6 @@
<string name="user_add_user_message_update" msgid="7061671307004867811">"Qurilmaning istalgan foydalanuvchisi ilovalarni barcha hisoblar uchun yangilashi mumkin."</string>
<string name="car_loading_profile" msgid="4507385037552574474">"Yuklanmoqda"</string>
<string name="car_loading_profile_developer_message" msgid="1660962766911529611">"Foydalanuvchi profili yuklanmoqda (<xliff:g id="FROM_USER">%1$d</xliff:g> – <xliff:g id="TO_USER">%2$d</xliff:g>)"</string>
+ <!-- no translation found for rear_view_camera_close_button_text (8430918817320533693) -->
+ <skip />
</resources>
diff --git a/packages/CarSystemUI/res/values-vi/strings.xml b/packages/CarSystemUI/res/values-vi/strings.xml
index 616b48fd17b6..26bdddc750cd 100644
--- a/packages/CarSystemUI/res/values-vi/strings.xml
+++ b/packages/CarSystemUI/res/values-vi/strings.xml
@@ -28,4 +28,6 @@
<string name="user_add_user_message_update" msgid="7061671307004867811">"Bất kỳ người dùng nào cũng có thể cập nhật ứng dụng cho tất cả những người dùng khác."</string>
<string name="car_loading_profile" msgid="4507385037552574474">"Đang tải"</string>
<string name="car_loading_profile_developer_message" msgid="1660962766911529611">"Đang tải hồ sơ người dùng (từ <xliff:g id="FROM_USER">%1$d</xliff:g> sang <xliff:g id="TO_USER">%2$d</xliff:g>)"</string>
+ <!-- no translation found for rear_view_camera_close_button_text (8430918817320533693) -->
+ <skip />
</resources>
diff --git a/packages/CarSystemUI/res/values-zh-rCN/strings.xml b/packages/CarSystemUI/res/values-zh-rCN/strings.xml
index 6dc37382b25c..e7ca871337fa 100644
--- a/packages/CarSystemUI/res/values-zh-rCN/strings.xml
+++ b/packages/CarSystemUI/res/values-zh-rCN/strings.xml
@@ -28,4 +28,6 @@
<string name="user_add_user_message_update" msgid="7061671307004867811">"任何用户均可为所有其他用户更新应用。"</string>
<string name="car_loading_profile" msgid="4507385037552574474">"正在加载"</string>
<string name="car_loading_profile_developer_message" msgid="1660962766911529611">"正在加载用户(从 <xliff:g id="FROM_USER">%1$d</xliff:g> 到 <xliff:g id="TO_USER">%2$d</xliff:g>)"</string>
+ <!-- no translation found for rear_view_camera_close_button_text (8430918817320533693) -->
+ <skip />
</resources>
diff --git a/packages/CarSystemUI/res/values-zh-rHK/strings.xml b/packages/CarSystemUI/res/values-zh-rHK/strings.xml
index 00ebd3219ea3..268243fea6f7 100644
--- a/packages/CarSystemUI/res/values-zh-rHK/strings.xml
+++ b/packages/CarSystemUI/res/values-zh-rHK/strings.xml
@@ -28,4 +28,6 @@
<string name="user_add_user_message_update" msgid="7061671307004867811">"任何使用者都可以為所有其他使用者更新應用程式。"</string>
<string name="car_loading_profile" msgid="4507385037552574474">"正在載入"</string>
<string name="car_loading_profile_developer_message" msgid="1660962766911529611">"正在載入使用者 (由 <xliff:g id="FROM_USER">%1$d</xliff:g> 至 <xliff:g id="TO_USER">%2$d</xliff:g>)"</string>
+ <!-- no translation found for rear_view_camera_close_button_text (8430918817320533693) -->
+ <skip />
</resources>
diff --git a/packages/CarSystemUI/res/values-zh-rTW/strings.xml b/packages/CarSystemUI/res/values-zh-rTW/strings.xml
index 96d6a1d201be..9dc0f1a03d3a 100644
--- a/packages/CarSystemUI/res/values-zh-rTW/strings.xml
+++ b/packages/CarSystemUI/res/values-zh-rTW/strings.xml
@@ -28,4 +28,6 @@
<string name="user_add_user_message_update" msgid="7061671307004867811">"任何使用者都能為所有其他使用者更新應用程式。"</string>
<string name="car_loading_profile" msgid="4507385037552574474">"載入中"</string>
<string name="car_loading_profile_developer_message" msgid="1660962766911529611">"正在載入使用者 (從 <xliff:g id="FROM_USER">%1$d</xliff:g> 到 <xliff:g id="TO_USER">%2$d</xliff:g>)"</string>
+ <!-- no translation found for rear_view_camera_close_button_text (8430918817320533693) -->
+ <skip />
</resources>
diff --git a/packages/CarSystemUI/res/values-zu/strings.xml b/packages/CarSystemUI/res/values-zu/strings.xml
index b835f9a69bde..8845ff71c1bb 100644
--- a/packages/CarSystemUI/res/values-zu/strings.xml
+++ b/packages/CarSystemUI/res/values-zu/strings.xml
@@ -28,4 +28,6 @@
<string name="user_add_user_message_update" msgid="7061671307004867811">"Noma yimuphi umsebenzisi angabuyekeza izinhlelo zokusebenza zabanye abasebenzisi."</string>
<string name="car_loading_profile" msgid="4507385037552574474">"Iyalayisha"</string>
<string name="car_loading_profile_developer_message" msgid="1660962766911529611">"Ilayisha umsebenzisi (kusuka ku-<xliff:g id="FROM_USER">%1$d</xliff:g> kuya ku-<xliff:g id="TO_USER">%2$d</xliff:g>)"</string>
+ <!-- no translation found for rear_view_camera_close_button_text (8430918817320533693) -->
+ <skip />
</resources>
diff --git a/packages/CarSystemUI/res/values/colors.xml b/packages/CarSystemUI/res/values/colors.xml
index 0181b9a39aea..91d416623538 100644
--- a/packages/CarSystemUI/res/values/colors.xml
+++ b/packages/CarSystemUI/res/values/colors.xml
@@ -66,4 +66,6 @@
<color name="car_user_switching_dialog_background_color">@android:color/black</color>
<color name="car_user_switching_dialog_loading_text_color">@*android:color/car_body1</color>
+
+ <color name="rear_view_camera_button_background">@*android:color/car_card_dark</color>
</resources>
diff --git a/packages/CarSystemUI/res/values/config.xml b/packages/CarSystemUI/res/values/config.xml
index 949a0fac9598..8667ba1cd1a5 100644
--- a/packages/CarSystemUI/res/values/config.xml
+++ b/packages/CarSystemUI/res/values/config.xml
@@ -108,6 +108,7 @@
<item>com.android.systemui.car.keyguard.CarKeyguardViewMediator</item>
<item>com.android.systemui.car.userswitcher.FullscreenUserSwitcherViewMediator</item>
<item>com.android.systemui.car.userswitcher.UserSwitchTransitionViewMediator</item>
+ <item>com.android.systemui.car.rvc.RearViewCameraViewMediator</item>
</string-array>
<!--
@@ -150,4 +151,7 @@
<!-- How many milliseconds to wait before force hiding the UserSwitchTransitionView -->
<integer name="config_userSwitchTransitionViewShownTimeoutMs" translatable="false">5000</integer>
+
+ <!-- The Activity name for the Rear View Camera, if empty, the feature will be disabled. -->
+ <string name="config_rearViewCameraActivity" translatable="false"></string>
</resources>
diff --git a/packages/CarSystemUI/res/values/dimens.xml b/packages/CarSystemUI/res/values/dimens.xml
index 86bfa751d085..a7d8ab5f2a4c 100644
--- a/packages/CarSystemUI/res/values/dimens.xml
+++ b/packages/CarSystemUI/res/values/dimens.xml
@@ -227,4 +227,8 @@
<dimen name="car_fullscreen_user_pod_image_avatar_height">96dp</dimen>
<dimen name="car_user_switching_dialog_loading_text_margin_top">@*android:dimen/car_padding_4</dimen>
<dimen name="car_user_switching_dialog_loading_text_font_size">@*android:dimen/car_body1_size</dimen>
+
+ <!-- dimensions for rear view camera -->
+ <dimen name="rear_view_camera_width">600dp</dimen>
+ <dimen name="rear_view_camera_height">500dp</dimen>
</resources>
diff --git a/packages/CarSystemUI/res/values/strings.xml b/packages/CarSystemUI/res/values/strings.xml
index 06ae7cfd6d1b..264456588c80 100644
--- a/packages/CarSystemUI/res/values/strings.xml
+++ b/packages/CarSystemUI/res/values/strings.xml
@@ -42,4 +42,6 @@
<string name="car_loading_profile">Loading</string>
<!-- Message to inform user that the new user profile is loading with additional information on the previous and the next user. [CHAR LIMIT=100] -->
<string name="car_loading_profile_developer_message">Loading user (from <xliff:g id="from_user" example="10">%1$d</xliff:g> to <xliff:g id="to_user" example="12">%2$d</xliff:g>)</string>
+ <!-- Text for the close button in Rear View Camera [CHAR LIMIT=30] -->
+ <string name="rear_view_camera_close_button_text">Close</string>
</resources>
diff --git a/packages/CarSystemUI/samples/sample3/rro/Android.bp b/packages/CarSystemUI/samples/sample3/rro/Android.bp
new file mode 100644
index 000000000000..0eae7c271f66
--- /dev/null
+++ b/packages/CarSystemUI/samples/sample3/rro/Android.bp
@@ -0,0 +1,27 @@
+//
+// Copyright (C) 2020 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+android_app {
+ name: "CarSystemUISampleThreeRRO",
+ resource_dirs: ["res"],
+ certificate: "platform",
+ platform_apis: true,
+ manifest: "AndroidManifest.xml",
+ aaptflags: [
+ "--no-resource-deduping",
+ "--no-resource-removal",
+ ]
+} \ No newline at end of file
diff --git a/packages/CarSystemUI/samples/sample3/rro/AndroidManifest.xml b/packages/CarSystemUI/samples/sample3/rro/AndroidManifest.xml
new file mode 100644
index 000000000000..5c25056f7915
--- /dev/null
+++ b/packages/CarSystemUI/samples/sample3/rro/AndroidManifest.xml
@@ -0,0 +1,24 @@
+<!--
+ ~ Copyright (C) 2020 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License.
+ -->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="com.android.systemui.rro">
+ <overlay
+ android:targetPackage="com.android.systemui"
+ android:isStatic="false"
+ android:resourcesMap="@xml/car_sysui_overlays"
+ />
+</manifest> \ No newline at end of file
diff --git a/packages/CarSystemUI/samples/sample3/rro/res/drawable/car_ic_apps.xml b/packages/CarSystemUI/samples/sample3/rro/res/drawable/car_ic_apps.xml
new file mode 100644
index 000000000000..a8d8a2f241f6
--- /dev/null
+++ b/packages/CarSystemUI/samples/sample3/rro/res/drawable/car_ic_apps.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ~ Copyright (C) 2019 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License
+ -->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:viewportWidth="44"
+ android:viewportHeight="44"
+ android:width="44dp"
+ android:height="44dp">
+<path
+ android:pathData="M7.33333333 14.6666667L14.6666667 14.6666667L14.6666667 7.33333333L7.33333333 7.33333333L7.33333333 14.6666667ZM18.3333333 36.6666667L25.6666667 36.6666667L25.6666667 29.3333333L18.3333333 29.3333333L18.3333333 36.6666667ZM7.33333333 36.6666667L14.6666667 36.6666667L14.6666667 29.3333333L7.33333333 29.3333333L7.33333333 36.6666667ZM7.33333333 25.6666667L14.6666667 25.6666667L14.6666667 18.3333333L7.33333333 18.3333333L7.33333333 25.6666667ZM18.3333333 25.6666667L25.6666667 25.6666667L25.6666667 18.3333333L18.3333333 18.3333333L18.3333333 25.6666667ZM29.3333333 7.33333333L29.3333333 14.6666667L36.6666667 14.6666667L36.6666667 7.33333333L29.3333333 7.33333333ZM18.3333333 14.6666667L25.6666667 14.6666667L25.6666667 7.33333333L18.3333333 7.33333333L18.3333333 14.6666667ZM29.3333333 25.6666667L36.6666667 25.6666667L36.6666667 18.3333333L29.3333333 18.3333333L29.3333333 25.6666667ZM29.3333333 36.6666667L36.6666667 36.6666667L36.6666667 29.3333333L29.3333333 29.3333333L29.3333333 36.6666667Z"
+ android:fillColor="@color/car_nav_icon_fill_color" />
+</vector> \ No newline at end of file
diff --git a/packages/CarSystemUI/samples/sample3/rro/res/drawable/car_ic_home.xml b/packages/CarSystemUI/samples/sample3/rro/res/drawable/car_ic_home.xml
new file mode 100644
index 000000000000..c78f0edd5594
--- /dev/null
+++ b/packages/CarSystemUI/samples/sample3/rro/res/drawable/car_ic_home.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ~ Copyright (C) 2020 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License.
+ -->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="@dimen/system_bar_icon_drawing_size"
+ android:height="@dimen/system_bar_icon_drawing_size"
+ android:viewportWidth="24"
+ android:viewportHeight="24">
+ <path
+ android:pathData="M10,20v-6h4v6h5v-8h3L12,3 2,12h3v8z"
+ android:fillColor="@color/car_nav_icon_fill_color" />
+</vector> \ No newline at end of file
diff --git a/packages/CarSystemUI/samples/sample3/rro/res/drawable/car_ic_hvac.xml b/packages/CarSystemUI/samples/sample3/rro/res/drawable/car_ic_hvac.xml
new file mode 100644
index 000000000000..55c968eacc4d
--- /dev/null
+++ b/packages/CarSystemUI/samples/sample3/rro/res/drawable/car_ic_hvac.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (C) 2018 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="@dimen/system_bar_icon_drawing_size"
+ android:height="@dimen/system_bar_icon_drawing_size"
+ android:viewportWidth="24"
+ android:viewportHeight="24">
+ <path
+ android:pathData="M16.34,8.36l-2.29,0.82c-0.18,-0.13 -0.38,-0.25 -0.58,-0.34c0.17,-0.83 0.63,-1.58 1.36,-2.06C16.85,5.44 16.18,2 13.39,2C9,2 7.16,5.01 8.36,7.66l0.82,2.29c-0.13,0.18 -0.25,0.38 -0.34,0.58c-0.83,-0.17 -1.58,-0.63 -2.06,-1.36C5.44,7.15 2,7.82 2,10.61c0,4.4 3.01,6.24 5.66,5.03l2.29,-0.82c0.18,0.13 0.38,0.25 0.58,0.34c-0.17,0.83 -0.63,1.58 -1.36,2.06C7.15,18.56 7.82,22 10.61,22c4.4,0 6.24,-3.01 5.03,-5.66l-0.82,-2.29c0.13,-0.18 0.25,-0.38 0.34,-0.58c0.83,0.17 1.58,0.63 2.06,1.36c1.34,2.01 4.77,1.34 4.77,-1.45C22,9 18.99,7.16 16.34,8.36zM12,13.5c-0.83,0 -1.5,-0.67 -1.5,-1.5c0,-0.83 0.67,-1.5 1.5,-1.5c0.83,0 1.5,0.67 1.5,1.5C13.5,12.83 12.83,13.5 12,13.5zM10.24,5.22C10.74,4.44 11.89,4 13.39,4c0.79,0 0.71,0.86 0.34,1.11c-1.22,0.81 -2,2.06 -2.25,3.44c-0.21,0.03 -0.42,0.08 -0.62,0.15l-0.68,-1.88C10,6.42 9.86,5.81 10.24,5.22zM6.83,13.82c-0.4,0.18 -1.01,0.32 -1.61,-0.06C4.44,13.26 4,12.11 4,10.61c0,-0.79 0.86,-0.71 1.11,-0.34c0.81,1.22 2.06,2 3.44,2.25c0.03,0.21 0.08,0.42 0.15,0.62L6.83,13.82zM13.76,18.78c-0.5,0.77 -1.65,1.22 -3.15,1.22c-0.79,0 -0.71,-0.86 -0.34,-1.11c1.22,-0.81 2,-2.06 2.25,-3.44c0.21,-0.03 0.42,-0.08 0.62,-0.15l0.68,1.88C14,17.58 14.14,18.18 13.76,18.78zM18.89,13.73c-0.81,-1.22 -2.06,-2 -3.44,-2.25c-0.03,-0.21 -0.08,-0.42 -0.15,-0.62l1.88,-0.68c0.4,-0.18 1.01,-0.32 1.61,0.06c0.77,0.5 1.22,1.65 1.22,3.15C20,14.19 19.14,14.11 18.89,13.73z"
+ android:fillColor="@color/car_nav_icon_fill_color" />
+</vector>
diff --git a/packages/CarSystemUI/samples/sample3/rro/res/drawable/car_ic_music.xml b/packages/CarSystemUI/samples/sample3/rro/res/drawable/car_ic_music.xml
new file mode 100644
index 000000000000..6339ebb3ea8d
--- /dev/null
+++ b/packages/CarSystemUI/samples/sample3/rro/res/drawable/car_ic_music.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ~ Copyright (C) 2019 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License
+ -->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:viewportWidth="44"
+ android:viewportHeight="44"
+ android:width="44dp"
+ android:height="44dp">
+ <path
+ android:pathData="M22 5.5L22 24.8416667C20.9183333 24.2183333 19.6716667 23.8333333 18.3333333 23.8333333C14.2816667 23.8333333 11 27.115 11 31.1666667C11 35.2183333 14.2816667 38.5 18.3333333 38.5C22.385 38.5 25.6666667 35.2183333 25.6666667 31.1666667L25.6666667 12.8333333L33 12.8333333L33 5.5L22 5.5Z"
+ android:fillColor="@color/car_nav_icon_fill_color" />
+</vector> \ No newline at end of file
diff --git a/packages/CarSystemUI/samples/sample3/rro/res/drawable/car_ic_navigation.xml b/packages/CarSystemUI/samples/sample3/rro/res/drawable/car_ic_navigation.xml
new file mode 100644
index 000000000000..e1fabe07cdeb
--- /dev/null
+++ b/packages/CarSystemUI/samples/sample3/rro/res/drawable/car_ic_navigation.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ~ Copyright (C) 2019 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License
+ -->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:viewportWidth="44"
+ android:viewportHeight="44"
+ android:width="44dp"
+ android:height="44dp">
+ <path
+ android:pathData="M39.8016667 20.6983333L23.3016667 4.19833333C22.5866667 3.48333333 21.4316667 3.48333333 20.7166667 4.19833333L4.21666667 20.6983333C3.50166667 21.4133333 3.50166667 22.5683333 4.21666667 23.2833333L20.7166667 39.7833333C21.4316667 40.4983333 22.5866667 40.4983333 23.3016667 39.7833333L39.8016667 23.2833333C40.5166667 22.5866667 40.5166667 21.4316667 39.8016667 20.6983333ZM25.6666667 26.5833333L25.6666667 22L18.3333333 22L18.3333333 27.5L14.6666667 27.5L14.6666667 20.1666667C14.6666667 19.1583333 15.4916667 18.3333333 16.5 18.3333333L25.6666667 18.3333333L25.6666667 13.75L32.0833333 20.1666667L25.6666667 26.5833333Z"
+ android:fillColor="@color/car_nav_icon_fill_color" />
+</vector> \ No newline at end of file
diff --git a/packages/CarSystemUI/samples/sample3/rro/res/drawable/car_ic_notification.xml b/packages/CarSystemUI/samples/sample3/rro/res/drawable/car_ic_notification.xml
new file mode 100644
index 000000000000..aabf9161c11f
--- /dev/null
+++ b/packages/CarSystemUI/samples/sample3/rro/res/drawable/car_ic_notification.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ~ Copyright (C) 2019 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License
+ -->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="@dimen/system_bar_icon_drawing_size"
+ android:height="@dimen/system_bar_icon_drawing_size"
+ android:viewportWidth="44"
+ android:viewportHeight="44">
+ <path
+ android:pathData="M22 39.125C23.925 39.125 25.5 37.55 25.5 35.625L18.5 35.625C18.5 37.55 20.0575 39.125 22 39.125ZM32.5 28.625L32.5 19.875C32.5 14.5025 29.63 10.005 24.625 8.815L24.625 7.625C24.625 6.1725 23.4525 5 22 5C20.5475 5 19.375 6.1725 19.375 7.625L19.375 8.815C14.3525 10.005 11.5 14.485 11.5 19.875L11.5 28.625L8 32.125L8 33.875L36 33.875L36 32.125L32.5 28.625Z"
+ android:fillColor="@color/car_nav_icon_fill_color" />
+</vector> \ No newline at end of file
diff --git a/packages/CarSystemUI/samples/sample3/rro/res/drawable/car_ic_overview.xml b/packages/CarSystemUI/samples/sample3/rro/res/drawable/car_ic_overview.xml
new file mode 100644
index 000000000000..f185eb9afb75
--- /dev/null
+++ b/packages/CarSystemUI/samples/sample3/rro/res/drawable/car_ic_overview.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ~ Copyright (C) 2019 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License
+ -->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:viewportWidth="44"
+ android:viewportHeight="44"
+ android:width="44dp"
+ android:height="44dp">
+ <path
+ android:pathData="M36.92857 22.39286A14.53571 14.53571 0 0 1 7.857143 22.39286A14.53571 14.53571 0 0 1 36.92857 22.39286Z"
+ android:strokeColor="@color/car_nav_icon_fill_color"
+ android:strokeWidth="4" />
+</vector> \ No newline at end of file
diff --git a/packages/CarSystemUI/samples/sample3/rro/res/drawable/car_ic_phone.xml b/packages/CarSystemUI/samples/sample3/rro/res/drawable/car_ic_phone.xml
new file mode 100644
index 000000000000..50e36b5a6e3c
--- /dev/null
+++ b/packages/CarSystemUI/samples/sample3/rro/res/drawable/car_ic_phone.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ~ Copyright (C) 2019 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License
+ -->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:viewportWidth="44"
+ android:viewportHeight="44"
+ android:width="44dp"
+ android:height="44dp">
+ <path
+ android:pathData="M12.1366667 19.7816667C14.7766667 24.97 19.03 29.205 24.2183333 31.8633333L28.2516667 27.83C28.7466667 27.335 29.48 27.17 30.1216667 27.39C32.175 28.0683333 34.3933333 28.435 36.6666667 28.435C37.675 28.435 38.5 29.26 38.5 30.2683333L38.5 36.6666667C38.5 37.675 37.675 38.5 36.6666667 38.5C19.4516667 38.5 5.5 24.5483333 5.5 7.33333333C5.5 6.325 6.325 5.5 7.33333333 5.5L13.75 5.5C14.7583333 5.5 15.5833333 6.325 15.5833333 7.33333333C15.5833333 9.625 15.95 11.825 16.6283333 13.8783333C16.83 14.52 16.6833333 15.235 16.17 15.7483333L12.1366667 19.7816667Z"
+ android:fillColor="@color/car_nav_icon_fill_color" />
+</vector> \ No newline at end of file
diff --git a/packages/CarSystemUI/samples/sample3/rro/res/drawable/system_bar_background.xml b/packages/CarSystemUI/samples/sample3/rro/res/drawable/system_bar_background.xml
new file mode 100644
index 000000000000..66da21ca23f8
--- /dev/null
+++ b/packages/CarSystemUI/samples/sample3/rro/res/drawable/system_bar_background.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ~ Copyright (C) 2020 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License.
+ -->
+<shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="rectangle" >
+ <solid
+ android:color="#404040"
+ />
+</shape> \ No newline at end of file
diff --git a/packages/CarSystemUI/samples/sample3/rro/res/layout/car_left_navigation_bar.xml b/packages/CarSystemUI/samples/sample3/rro/res/layout/car_left_navigation_bar.xml
new file mode 100644
index 000000000000..3d1cd085e578
--- /dev/null
+++ b/packages/CarSystemUI/samples/sample3/rro/res/layout/car_left_navigation_bar.xml
@@ -0,0 +1,51 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+**
+** Copyright 2018, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+
+<com.android.systemui.car.navigationbar.CarNavigationBarView
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:systemui="http://schemas.android.com/apk/res-auto"
+ android:layout_height="match_parent"
+ android:layout_width="match_parent"
+ android:orientation="vertical"
+ android:background="@android:color/transparent">
+
+ <LinearLayout
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:layout_weight="1"
+ android:gravity="bottom"
+ android:orientation="vertical">
+
+ <com.android.systemui.statusbar.policy.Clock
+ android:id="@+id/clock"
+ android:textAppearance="@style/TextAppearance.StatusBar.Clock"
+ android:layout_height="wrap_content"
+ android:layout_width="match_parent"
+ android:singleLine="true"
+ android:gravity="center_horizontal"
+ android:paddingBottom="20dp"
+ />
+
+ <Space
+ android:layout_height="50dp"
+ android:layout_width="match_parent"/>
+
+ </LinearLayout>
+
+</com.android.systemui.car.navigationbar.CarNavigationBarView>
diff --git a/packages/CarSystemUI/samples/sample3/rro/res/layout/car_navigation_bar.xml b/packages/CarSystemUI/samples/sample3/rro/res/layout/car_navigation_bar.xml
new file mode 100644
index 000000000000..8314ba5600a9
--- /dev/null
+++ b/packages/CarSystemUI/samples/sample3/rro/res/layout/car_navigation_bar.xml
@@ -0,0 +1,122 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ~ Copyright (C) 2020 The Android Open Source Project.
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License.
+ -->
+
+<com.android.systemui.car.navigationbar.CarNavigationBarView
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:systemui="http://schemas.android.com/apk/res-auto"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:background="@drawable/system_bar_background"
+ android:gravity="center"
+ android:orientation="horizontal">
+
+ <RelativeLayout
+ android:id="@+id/nav_buttons"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layoutDirection="ltr">
+
+ <com.android.systemui.car.hvac.AdjustableTemperatureView
+ android:id="@+id/driver_hvac"
+ android:layout_width="wrap_content"
+ android:layout_height="match_parent"
+ android:gravity="center_vertical"
+ systemui:hvacAreaId="49"
+ systemui:hvacTempFormat="%.0f\u00B0" />
+
+ <LinearLayout
+ android:layout_width="wrap_content"
+ android:layout_height="match_parent"
+ android:layout_centerInParent="true"
+ android:layout_weight="1"
+ android:gravity="center"
+ android:layoutDirection="ltr"
+ android:paddingEnd="@dimen/system_bar_button_group_padding"
+ android:paddingStart="@dimen/system_bar_button_group_padding">
+
+ <Space
+ android:layout_width="0dp"
+ android:layout_height="match_parent"
+ android:layout_weight="1"/>
+
+ <com.android.systemui.car.navigationbar.CarNavigationButton
+ android:id="@+id/home"
+ style="@style/NavigationBarButton"
+ systemui:componentNames="com.android.car.carlauncher/.CarLauncher"
+ systemui:highlightWhenSelected="true"
+ systemui:icon="@drawable/car_ic_home"
+ systemui:intent="intent:#Intent;action=android.intent.action.MAIN;category=android.intent.category.HOME;launchFlags=0x14000000;end"/>
+
+ <com.android.systemui.car.navigationbar.CarNavigationButton
+ android:id="@+id/phone_nav"
+ style="@style/NavigationBarButton"
+ systemui:highlightWhenSelected="true"
+ systemui:icon="@drawable/car_ic_phone"
+ systemui:intent="intent:#Intent;action=android.intent.action.MAIN;category=android.intent.category.LAUNCHER;package=com.android.car.dialer;launchFlags=0x10000000;end"
+ systemui:packages="com.android.car.dialer"/>
+
+ <com.android.systemui.car.navigationbar.CarNavigationButton
+ android:id="@+id/grid_nav"
+ style="@style/NavigationBarButton"
+ systemui:componentNames="com.android.car.carlauncher/.AppGridActivity"
+ systemui:highlightWhenSelected="true"
+ systemui:icon="@drawable/car_ic_apps"
+ systemui:intent="intent:#Intent;component=com.android.car.carlauncher/.AppGridActivity;launchFlags=0x24000000;end"/>
+
+ <com.android.systemui.car.navigationbar.CarNavigationButton
+ android:id="@+id/hvac"
+ style="@style/NavigationBarButton"
+ systemui:highlightWhenSelected="true"
+ systemui:icon="@drawable/car_ic_hvac"
+ systemui:intent="intent:#Intent;action=android.car.intent.action.TOGGLE_HVAC_CONTROLS;end"
+ systemui:broadcast="true"/>
+
+ <com.android.systemui.car.navigationbar.CarNavigationButton
+ android:id="@+id/notifications"
+ style="@style/NavigationBarButton"
+ systemui:highlightWhenSelected="true"
+ systemui:icon="@drawable/car_ic_notification"
+ systemui:longIntent="intent:#Intent;component=com.android.car.bugreport/.BugReportActivity;end"/>
+
+ <Space
+ android:layout_width="0dp"
+ android:layout_height="match_parent"
+ android:layout_weight="1"/>
+ </LinearLayout>
+
+ <com.android.systemui.car.hvac.AdjustableTemperatureView
+ android:id="@+id/passenger_hvac"
+ android:layout_width="wrap_content"
+ android:layout_height="match_parent"
+ android:layout_alignParentEnd="true"
+ android:gravity="center_vertical"
+ systemui:hvacAreaId="68"
+ systemui:hvacTempFormat="%.0f\u00B0" />
+ </RelativeLayout>
+
+ <LinearLayout
+ android:id="@+id/lock_screen_nav_buttons"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_weight="1"
+ android:gravity="center"
+ android:layoutDirection="ltr"
+ android:paddingEnd="@dimen/car_keyline_1"
+ android:paddingStart="@dimen/car_keyline_1"
+ android:visibility="gone"
+ />
+</com.android.systemui.car.navigationbar.CarNavigationBarView> \ No newline at end of file
diff --git a/packages/CarSystemUI/samples/sample3/rro/res/values/attrs.xml b/packages/CarSystemUI/samples/sample3/rro/res/values/attrs.xml
new file mode 100644
index 000000000000..bc7ded20031a
--- /dev/null
+++ b/packages/CarSystemUI/samples/sample3/rro/res/values/attrs.xml
@@ -0,0 +1,43 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ~ Copyright (C) 2020 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License.
+ -->
+
+<resources>
+ <attr name="broadcast" format="boolean"/>
+ <attr name="icon" format="reference"/>
+ <attr name="intent" format="string"/>
+ <attr name="longIntent" format="string"/>
+ <attr name="componentNames" format="string" />
+ <attr name="highlightWhenSelected" format="boolean" />
+ <attr name="categories" format="string"/>
+ <attr name="packages" format="string" />
+
+ <!-- Custom attributes to configure hvac values -->
+ <declare-styleable name="AnimatedTemperatureView">
+ <attr name="hvacAreaId" format="integer"/>
+ <attr name="hvacPropertyId" format="integer"/>
+ <attr name="hvacTempFormat" format="string"/>
+ <!-- how far away the animations should center around -->
+ <attr name="hvacPivotOffset" format="dimension"/>
+ <attr name="hvacMinValue" format="float"/>
+ <attr name="hvacMaxValue" format="float"/>
+ <attr name="hvacMinText" format="string|reference"/>
+ <attr name="hvacMaxText" format="string|reference"/>
+ <attr name="android:gravity"/>
+ <attr name="android:minEms"/>
+ <attr name="android:textAppearance"/>
+ </declare-styleable>
+</resources>
diff --git a/packages/CarSystemUI/samples/sample3/rro/res/values/colors.xml b/packages/CarSystemUI/samples/sample3/rro/res/values/colors.xml
new file mode 100644
index 000000000000..f98cb96e76e8
--- /dev/null
+++ b/packages/CarSystemUI/samples/sample3/rro/res/values/colors.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ~ Copyright (C) 2020 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License.
+ -->
+<resources xmlns:android="http://schemas.android.com/apk/res/android">
+ <color name="car_nav_icon_fill_color">#8F8F8F</color>
+</resources>
diff --git a/packages/CarSystemUI/samples/sample3/rro/res/values/config.xml b/packages/CarSystemUI/samples/sample3/rro/res/values/config.xml
new file mode 100644
index 000000000000..2148e7cbfd96
--- /dev/null
+++ b/packages/CarSystemUI/samples/sample3/rro/res/values/config.xml
@@ -0,0 +1,57 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ~ Copyright (C) 2020 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License.
+ -->
+
+<resources>
+ <!-- Configure which system bars should be displayed. -->
+ <bool name="config_enableTopNavigationBar">false</bool>
+ <bool name="config_enableLeftNavigationBar">true</bool>
+ <bool name="config_enableRightNavigationBar">false</bool>
+ <bool name="config_enableBottomNavigationBar">true</bool>
+
+ <!-- Configure the type of each system bar. Each system bar must have a unique type. -->
+ <!-- STATUS_BAR = 0-->
+ <!-- NAVIGATION_BAR = 1-->
+ <!-- STATUS_BAR_EXTRA = 2-->
+ <!-- NAVIGATION_BAR_EXTRA = 3-->
+ <integer name="config_topSystemBarType">2</integer>
+ <integer name="config_leftSystemBarType">0</integer>
+ <integer name="config_rightSystemBarType">3</integer>
+ <integer name="config_bottomSystemBarType">1</integer>
+
+ <!-- Configure the relative z-order among the system bars. When two system bars overlap (e.g.
+ if both top bar and left bar are enabled, it creates an overlapping space in the upper left
+ corner), the system bar with the higher z-order takes the overlapping space and padding is
+ applied to the other bar.-->
+ <!-- NOTE: If two overlapping system bars have the same z-order, SystemBarConfigs will throw a
+ RuntimeException, since their placing order cannot be determined. Bars that do not overlap
+ are allowed to have the same z-order. -->
+ <!-- NOTE: If the z-order of a bar is 10 or above, it will also appear on top of HUN's. -->
+ <integer name="config_topSystemBarZOrder">0</integer>
+ <integer name="config_leftSystemBarZOrder">10</integer>
+ <integer name="config_rightSystemBarZOrder">0</integer>
+ <integer name="config_bottomSystemBarZOrder">15</integer>
+
+ <!-- Whether heads-up notifications should be shown on the bottom. If false, heads-up
+ notifications will be shown pushed to the top of their parent container. If true, they will
+ be shown pushed to the bottom of their parent container. If true, then should override
+ config_headsUpNotificationAnimationHelper to use a different AnimationHelper, such as
+ com.android.car.notification.headsup.animationhelper.
+ CarHeadsUpNotificationBottomAnimationHelper. -->
+ <bool name="config_showHeadsUpNotificationOnBottom">false</bool>
+
+ <string name="config_notificationPanelViewMediator" translatable="false">com.android.systemui.car.notification.BottomNotificationPanelViewMediator</string>
+</resources> \ No newline at end of file
diff --git a/packages/CarSystemUI/samples/sample3/rro/res/values/dimens.xml b/packages/CarSystemUI/samples/sample3/rro/res/values/dimens.xml
new file mode 100644
index 000000000000..c89f94938582
--- /dev/null
+++ b/packages/CarSystemUI/samples/sample3/rro/res/values/dimens.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ~ Copyright (C) 2018 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License
+ -->
+<resources>
+ <dimen name="car_left_navigation_bar_width">280dp</dimen>
+ <dimen name="car_keyline_1">24dp</dimen>
+ <dimen name="system_bar_button_group_padding">64dp</dimen>
+ <dimen name="system_bar_icon_drawing_size">44dp</dimen>
+</resources>
diff --git a/packages/CarSystemUI/samples/sample3/rro/res/values/styles.xml b/packages/CarSystemUI/samples/sample3/rro/res/values/styles.xml
new file mode 100644
index 000000000000..bad36917d2cf
--- /dev/null
+++ b/packages/CarSystemUI/samples/sample3/rro/res/values/styles.xml
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ~ Copyright (C) 2020 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License.
+ -->
+<resources xmlns:android="http://schemas.android.com/apk/res/android">
+ <style name="TextAppearance.StatusBar.Clock"
+ parent="@*android:style/TextAppearance.StatusBar.Icon">
+ <item name="android:textSize">40sp</item>
+ <item name="android:fontFamily">sans-serif-regular</item>
+ <item name="android:textColor">#FFFFFF</item>
+ </style>
+
+ <style name="NavigationBarButton">
+ <item name="android:layout_height">96dp</item>
+ <item name="android:layout_width">96dp</item>
+ <item name="android:background">?android:attr/selectableItemBackground</item>
+ </style>
+</resources> \ No newline at end of file
diff --git a/packages/CarSystemUI/samples/sample3/rro/res/xml/car_sysui_overlays.xml b/packages/CarSystemUI/samples/sample3/rro/res/xml/car_sysui_overlays.xml
new file mode 100644
index 000000000000..f08d9684f2d5
--- /dev/null
+++ b/packages/CarSystemUI/samples/sample3/rro/res/xml/car_sysui_overlays.xml
@@ -0,0 +1,75 @@
+
+<!--
+ ~ 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.
+ -->
+
+<overlay>
+ <item target="layout/car_navigation_bar" value="@layout/car_navigation_bar"/>
+ <item target="layout/car_left_navigation_bar" value="@layout/car_left_navigation_bar"/>
+
+ <item target="bool/config_enableTopNavigationBar" value="@bool/config_enableTopNavigationBar"/>
+ <item target="bool/config_enableLeftNavigationBar" value="@bool/config_enableLeftNavigationBar"/>
+ <item target="bool/config_enableRightNavigationBar" value="@bool/config_enableRightNavigationBar"/>
+ <item target="bool/config_enableBottomNavigationBar" value="@bool/config_enableBottomNavigationBar"/>
+ <item target="bool/config_showHeadsUpNotificationOnBottom" value="@bool/config_showHeadsUpNotificationOnBottom"/>
+
+ <item target="attr/icon" value="@attr/icon"/>
+ <item target="attr/intent" value="@attr/intent"/>
+ <item target="attr/longIntent" value="@attr/longIntent"/>
+ <item target="attr/componentNames" value="@attr/componentNames"/>
+ <item target="attr/highlightWhenSelected" value="@attr/highlightWhenSelected"/>
+ <item target="attr/categories" value="@attr/categories"/>
+ <item target="attr/packages" value="@attr/packages"/>
+ <item target="attr/hvacAreaId" value="@attr/hvacAreaId"/>
+ <item target="attr/hvacPropertyId" value="@attr/hvacPropertyId"/>
+ <item target="attr/hvacTempFormat" value="@attr/hvacTempFormat"/>
+ <item target="attr/hvacPivotOffset" value="@attr/hvacPivotOffset"/>
+ <item target="attr/hvacMinValue" value="@attr/hvacMinValue"/>
+ <item target="attr/hvacMaxValue" value="@attr/hvacMaxValue"/>
+ <item target="attr/hvacMinText" value="@attr/hvacMinText"/>
+ <item target="attr/hvacMaxText" value="@attr/hvacMaxText"/>
+ <!-- start the intent as a broad cast instead of an activity if true-->
+ <item target="attr/broadcast" value="@attr/broadcast"/>
+
+ <item target="color/car_nav_icon_fill_color" value="@color/car_nav_icon_fill_color" />
+
+ <item target="drawable/car_ic_overview" value="@drawable/car_ic_overview" />
+ <item target="drawable/car_ic_home" value="@drawable/car_ic_home" />
+ <item target="drawable/car_ic_hvac" value="@drawable/car_ic_hvac" />
+ <item target="drawable/car_ic_apps" value="@drawable/car_ic_apps" />
+ <item target="drawable/car_ic_music" value="@drawable/car_ic_music" />
+ <item target="drawable/car_ic_notification" value="@drawable/car_ic_notification" />
+ <item target="drawable/car_ic_phone" value="@drawable/car_ic_phone" />
+ <item target="drawable/car_ic_navigation" value="@drawable/car_ic_navigation" />
+
+ <item target="dimen/car_left_navigation_bar_width" value="@dimen/car_left_navigation_bar_width" />
+ <item target="dimen/car_keyline_1" value="@dimen/car_keyline_1" />
+ <item target="dimen/system_bar_button_group_padding" value="@dimen/system_bar_button_group_padding" />
+ <item target="dimen/system_bar_icon_drawing_size" value="@dimen/system_bar_icon_drawing_size" />
+
+ <item target="integer/config_topSystemBarType" value="@integer/config_topSystemBarType"/>
+ <item target="integer/config_leftSystemBarType" value="@integer/config_leftSystemBarType"/>
+ <item target="integer/config_rightSystemBarType" value="@integer/config_rightSystemBarType"/>
+ <item target="integer/config_bottomSystemBarType" value="@integer/config_bottomSystemBarType"/>
+
+ <item target="integer/config_topSystemBarZOrder" value="@integer/config_topSystemBarZOrder"/>
+ <item target="integer/config_leftSystemBarZOrder" value="@integer/config_leftSystemBarZOrder"/>
+ <item target="integer/config_rightSystemBarZOrder" value="@integer/config_rightSystemBarZOrder"/>
+ <item target="integer/config_bottomSystemBarZOrder" value="@integer/config_bottomSystemBarZOrder"/>
+
+ <item target="string/config_notificationPanelViewMediator" value="@string/config_notificationPanelViewMediator"/>
+
+ <item target="style/NavigationBarButton" value="@style/NavigationBarButton"/>
+</overlay> \ No newline at end of file
diff --git a/packages/CarSystemUI/src/com/android/systemui/CarGlobalRootComponent.java b/packages/CarSystemUI/src/com/android/systemui/CarGlobalRootComponent.java
index b17ad0febb90..b056dcf8fd2b 100644
--- a/packages/CarSystemUI/src/com/android/systemui/CarGlobalRootComponent.java
+++ b/packages/CarSystemUI/src/com/android/systemui/CarGlobalRootComponent.java
@@ -19,6 +19,7 @@ package com.android.systemui;
import com.android.systemui.dagger.GlobalModule;
import com.android.systemui.dagger.GlobalRootComponent;
import com.android.systemui.dagger.WMModule;
+import com.android.systemui.wmshell.CarWMComponent;
import javax.inject.Singleton;
@@ -41,6 +42,12 @@ public interface CarGlobalRootComponent extends GlobalRootComponent {
CarGlobalRootComponent build();
}
+ /**
+ * Builder for a WMComponent.
+ */
+ @Override
+ CarWMComponent.Builder getWMComponentBuilder();
+
@Override
CarSysUIComponent.Builder getSysUIComponent();
}
diff --git a/packages/CarSystemUI/src/com/android/systemui/CarSystemUIModule.java b/packages/CarSystemUI/src/com/android/systemui/CarSystemUIModule.java
index 51fda965dcd0..1d35bbb84464 100644
--- a/packages/CarSystemUI/src/com/android/systemui/CarSystemUIModule.java
+++ b/packages/CarSystemUI/src/com/android/systemui/CarSystemUIModule.java
@@ -64,7 +64,6 @@ import com.android.systemui.statusbar.policy.ConfigurationController;
import com.android.systemui.statusbar.policy.DeviceProvisionedController;
import com.android.systemui.statusbar.policy.HeadsUpManager;
import com.android.systemui.volume.VolumeDialogComponent;
-import com.android.systemui.wmshell.CarWMShellModule;
import javax.inject.Named;
@@ -74,8 +73,7 @@ import dagger.Provides;
@Module(
includes = {
- QSModule.class,
- CarWMShellModule.class
+ QSModule.class
})
abstract class CarSystemUIModule {
diff --git a/packages/CarSystemUI/src/com/android/systemui/car/rvc/RearViewCameraViewController.java b/packages/CarSystemUI/src/com/android/systemui/car/rvc/RearViewCameraViewController.java
new file mode 100644
index 000000000000..d63463309ec5
--- /dev/null
+++ b/packages/CarSystemUI/src/com/android/systemui/car/rvc/RearViewCameraViewController.java
@@ -0,0 +1,141 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.car.rvc;
+
+import android.app.ActivityView;
+import android.app.ActivityView.StateCallback;
+import android.content.ComponentName;
+import android.content.Intent;
+import android.content.res.Resources;
+import android.util.Slog;
+import android.view.ViewGroup;
+import android.widget.LinearLayout.LayoutParams;
+
+import com.android.internal.annotations.VisibleForTesting;
+import com.android.systemui.R;
+import com.android.systemui.car.window.OverlayViewController;
+import com.android.systemui.car.window.OverlayViewGlobalStateController;
+import com.android.systemui.dagger.SysUISingleton;
+import com.android.systemui.dagger.qualifiers.Main;
+
+import javax.inject.Inject;
+
+/** View controller for the rear view camera. */
+@SysUISingleton
+public class RearViewCameraViewController extends OverlayViewController {
+ private static final String TAG = "RearViewCameraView";
+ private static final boolean DBG = false;
+
+ private final ComponentName mRearViewCameraActivity;
+ private ViewGroup mRvcView;
+ private final LayoutParams mRvcViewLayoutParams = new LayoutParams(
+ LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT, /* weight= */ 1.0f);
+ @VisibleForTesting
+ ActivityView mActivityView;
+ @VisibleForTesting
+ final StateCallback mActivityViewCallback = new StateCallback() {
+ @Override
+ public void onActivityViewReady(ActivityView view) {
+ Intent intent = new Intent(Intent.ACTION_MAIN)
+ .setComponent(mRearViewCameraActivity)
+ .addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
+ .addFlags(Intent.FLAG_ACTIVITY_NEW_DOCUMENT)
+ .addFlags(Intent.FLAG_ACTIVITY_MULTIPLE_TASK);
+ // TODO(b/170899079): Migrate this to FixedActivityService.
+ view.startActivity(intent);
+ }
+
+ @Override
+ public void onActivityViewDestroyed(ActivityView view) {}
+ };
+
+ @Inject
+ public RearViewCameraViewController(
+ @Main Resources resources,
+ OverlayViewGlobalStateController overlayViewGlobalStateController) {
+ super(R.id.rear_view_camera_stub, overlayViewGlobalStateController);
+ String rearViewCameraActivityName = resources.getString(
+ R.string.config_rearViewCameraActivity);
+ if (!rearViewCameraActivityName.isEmpty()) {
+ mRearViewCameraActivity = ComponentName.unflattenFromString(rearViewCameraActivityName);
+ if (DBG) Slog.d(TAG, "mRearViewCameraActivity=" + mRearViewCameraActivity);
+ } else {
+ mRearViewCameraActivity = null;
+ Slog.e(TAG, "RearViewCameraViewController is disabled, since no Activity is defined");
+ }
+ }
+
+ @Override
+ protected void onFinishInflate() {
+ mRvcView = (ViewGroup) getLayout().findViewById(R.id.rear_view_camera_container);
+ getLayout().findViewById(R.id.close_button).setOnClickListener(v -> {
+ stop();
+ });
+ }
+
+ @Override
+ protected void hideInternal() {
+ super.hideInternal();
+ if (DBG) Slog.d(TAG, "hideInternal: mActivityView=" + mActivityView);
+ if (mActivityView == null) return;
+ mRvcView.removeView(mActivityView);
+ // Release ActivityView since the Activity on ActivityView (with showWhenLocked flag) keeps
+ // running even if ActivityView is hidden.
+ mActivityView.release();
+ mActivityView = null;
+ }
+
+ @Override
+ protected void showInternal() {
+ super.showInternal();
+ if (DBG) Slog.d(TAG, "showInternal: mActivityView=" + mActivityView);
+ if (mActivityView != null) return;
+ mActivityView = new ActivityView(mRvcView.getContext());
+ mActivityView.setCallback(mActivityViewCallback);
+ mActivityView.setLayoutParams(mRvcViewLayoutParams);
+ mRvcView.addView(mActivityView, /* index= */ 0);
+ }
+
+ boolean isShown() {
+ return mActivityView != null;
+ }
+
+ boolean isEnabled() {
+ return mRearViewCameraActivity != null;
+ }
+
+ @Override
+ protected boolean shouldShowHUN() {
+ return false;
+ }
+
+ @Override
+ protected boolean shouldShowWhenOccluded() {
+ // Returns true to show it on top of Keylock.
+ return true;
+ }
+
+ @Override
+ protected boolean shouldShowNavigationBarInsets() {
+ return true;
+ }
+
+ @Override
+ protected boolean shouldShowStatusBarInsets() {
+ return true;
+ }
+}
diff --git a/packages/CarSystemUI/src/com/android/systemui/car/rvc/RearViewCameraViewMediator.java b/packages/CarSystemUI/src/com/android/systemui/car/rvc/RearViewCameraViewMediator.java
new file mode 100644
index 000000000000..c575c423b256
--- /dev/null
+++ b/packages/CarSystemUI/src/com/android/systemui/car/rvc/RearViewCameraViewMediator.java
@@ -0,0 +1,121 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.car.rvc;
+
+import android.car.Car;
+import android.car.VehicleGear;
+import android.car.VehiclePropertyIds;
+import android.car.hardware.CarPropertyValue;
+import android.car.hardware.property.CarPropertyManager;
+import android.car.hardware.property.CarPropertyManager.CarPropertyEventCallback;
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.os.UserHandle;
+import android.util.Slog;
+
+import com.android.systemui.broadcast.BroadcastDispatcher;
+import com.android.systemui.car.CarServiceProvider;
+import com.android.systemui.car.window.OverlayViewMediator;
+import com.android.systemui.dagger.SysUISingleton;
+
+import javax.inject.Inject;
+
+/**
+ * View mediator for the rear view camera (RVC), which monitors the gear changes and shows
+ * the RVC when the gear position is R and otherwise it hides the RVC.
+ */
+@SysUISingleton
+public class RearViewCameraViewMediator implements OverlayViewMediator {
+ private static final String TAG = "RearViewCameraView";
+ private static final boolean DBG = false;
+
+ private final RearViewCameraViewController mRearViewCameraViewController;
+ private final CarServiceProvider mCarServiceProvider;
+ private final BroadcastDispatcher mBroadcastDispatcher;
+
+ private CarPropertyManager mCarPropertyManager;
+ // TODO(b/170792252): Replace the following with the callback from CarEvsManager if it's ready.
+ private final CarPropertyEventCallback mPropertyEventCallback = new CarPropertyEventCallback() {
+ @Override
+ public void onChangeEvent(CarPropertyValue value) {
+ if (DBG) Slog.d(TAG, "onChangeEvent value=" + value);
+ if (value.getPropertyId() != VehiclePropertyIds.GEAR_SELECTION) {
+ Slog.w(TAG, "Got the event for non-registered property: " + value.getPropertyId());
+ return;
+ }
+ if ((Integer) value.getValue() == VehicleGear.GEAR_REVERSE) {
+ mRearViewCameraViewController.start();
+ } else {
+ mRearViewCameraViewController.stop();
+ }
+ }
+ @Override
+ public void onErrorEvent(int propId, int zone) {
+ Slog.e(TAG, "onErrorEvent propId=" + propId + ", zone=" + zone);
+ }
+ };
+
+ private final BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() {
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ if (DBG) Slog.d(TAG, "onReceive: " + intent);
+ if (Intent.ACTION_CLOSE_SYSTEM_DIALOGS.equals(intent.getAction())
+ && mRearViewCameraViewController.isShown()) {
+ mRearViewCameraViewController.stop();
+ }
+ }
+ };
+
+ @Inject
+ public RearViewCameraViewMediator(
+ RearViewCameraViewController rearViewCameraViewController,
+ CarServiceProvider carServiceProvider,
+ BroadcastDispatcher broadcastDispatcher) {
+ if (DBG) Slog.d(TAG, "RearViewCameraViewMediator:init");
+ mRearViewCameraViewController = rearViewCameraViewController;
+ mCarServiceProvider = carServiceProvider;
+ mBroadcastDispatcher = broadcastDispatcher;
+ }
+
+ @Override
+ public void registerListeners() {
+ if (DBG) Slog.d(TAG, "RearViewCameraViewMediator:registerListeners");
+ if (!mRearViewCameraViewController.isEnabled()) {
+ Slog.i(TAG, "RearViewCameraViewController isn't enabled");
+ return;
+ }
+
+ mCarServiceProvider.addListener(car -> {
+ mCarPropertyManager = (CarPropertyManager) car.getCarManager(Car.PROPERTY_SERVICE);
+ if (mCarPropertyManager == null) {
+ Slog.e(TAG, "Unable to get CarPropertyManager");
+ return;
+ }
+ if (DBG) Slog.d(TAG, "Registering mPropertyEventCallback.");
+ mCarPropertyManager.registerCallback(mPropertyEventCallback,
+ VehiclePropertyIds.GEAR_SELECTION, CarPropertyManager.SENSOR_RATE_UI);
+ });
+ mBroadcastDispatcher.registerReceiver(mBroadcastReceiver,
+ new IntentFilter(Intent.ACTION_CLOSE_SYSTEM_DIALOGS), /* executor= */ null,
+ UserHandle.ALL);
+ }
+
+ @Override
+ public void setupOverlayContentViewControllers() {}
+}
diff --git a/packages/CarSystemUI/src/com/android/systemui/car/window/OverlayWindowModule.java b/packages/CarSystemUI/src/com/android/systemui/car/window/OverlayWindowModule.java
index 5a16efa3dd9b..fcbb0b807e74 100644
--- a/packages/CarSystemUI/src/com/android/systemui/car/window/OverlayWindowModule.java
+++ b/packages/CarSystemUI/src/com/android/systemui/car/window/OverlayWindowModule.java
@@ -20,6 +20,7 @@ import com.android.systemui.car.keyguard.CarKeyguardViewMediator;
import com.android.systemui.car.notification.BottomNotificationPanelViewMediator;
import com.android.systemui.car.notification.NotificationPanelViewMediator;
import com.android.systemui.car.notification.TopNotificationPanelViewMediator;
+import com.android.systemui.car.rvc.RearViewCameraViewMediator;
import com.android.systemui.car.userswitcher.FullscreenUserSwitcherViewMediator;
import com.android.systemui.car.userswitcher.UserSwitchTransitionViewMediator;
@@ -75,4 +76,11 @@ public abstract class OverlayWindowModule {
@ClassKey(UserSwitchTransitionViewMediator.class)
public abstract OverlayViewMediator bindUserSwitchTransitionViewMediator(
UserSwitchTransitionViewMediator userSwitchTransitionViewMediator);
+
+ /** Injects RearViewCameraViewMediator. */
+ @Binds
+ @IntoMap
+ @ClassKey(RearViewCameraViewMediator.class)
+ public abstract OverlayViewMediator bindRearViewCameraViewMediator(
+ RearViewCameraViewMediator overlayViewsMediator);
}
diff --git a/packages/CarSystemUI/src/com/android/systemui/wmshell/CarWMComponent.java b/packages/CarSystemUI/src/com/android/systemui/wmshell/CarWMComponent.java
new file mode 100644
index 000000000000..c6a7fd2f822d
--- /dev/null
+++ b/packages/CarSystemUI/src/com/android/systemui/wmshell/CarWMComponent.java
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.wmshell;
+
+import com.android.systemui.dagger.WMComponent;
+import com.android.systemui.dagger.WMSingleton;
+
+import dagger.Subcomponent;
+
+
+/**
+ * Dagger Subcomponent for WindowManager.
+ */
+@WMSingleton
+@Subcomponent(modules = {CarWMShellModule.class})
+public interface CarWMComponent extends WMComponent {
+
+ /**
+ * Builder for a SysUIComponent.
+ */
+ @Subcomponent.Builder
+ interface Builder extends WMComponent.Builder {
+ CarWMComponent build();
+ }
+}
diff --git a/packages/CarSystemUI/src/com/android/systemui/wmshell/CarWMShellModule.java b/packages/CarSystemUI/src/com/android/systemui/wmshell/CarWMShellModule.java
index 3bfe41045b44..27aabffd5090 100644
--- a/packages/CarSystemUI/src/com/android/systemui/wmshell/CarWMShellModule.java
+++ b/packages/CarSystemUI/src/com/android/systemui/wmshell/CarWMShellModule.java
@@ -20,7 +20,7 @@ import android.content.Context;
import android.os.Handler;
import android.view.IWindowManager;
-import com.android.systemui.dagger.SysUISingleton;
+import com.android.systemui.dagger.WMSingleton;
import com.android.systemui.dagger.qualifiers.Main;
import com.android.systemui.wm.DisplaySystemBarsController;
import com.android.wm.shell.common.DisplayController;
@@ -35,7 +35,7 @@ import dagger.Provides;
/** Provides dependencies from {@link com.android.wm.shell} for CarSystemUI. */
@Module(includes = WMShellBaseModule.class)
public abstract class CarWMShellModule {
- @SysUISingleton
+ @WMSingleton
@Provides
static DisplayImeController provideDisplayImeController(Context context,
IWindowManager wmService, DisplayController displayController,
diff --git a/packages/CarSystemUI/tests/src/com/android/systemui/car/rvc/RearViewCameraViewControllerTest.java b/packages/CarSystemUI/tests/src/com/android/systemui/car/rvc/RearViewCameraViewControllerTest.java
new file mode 100644
index 000000000000..a6160ecf1c62
--- /dev/null
+++ b/packages/CarSystemUI/tests/src/com/android/systemui/car/rvc/RearViewCameraViewControllerTest.java
@@ -0,0 +1,117 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.car.rvc;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.mockito.Mockito.verify;
+
+import android.app.ActivityView;
+import android.content.ComponentName;
+import android.content.Intent;
+import android.testing.TestableLooper;
+import android.view.LayoutInflater;
+import android.view.ViewGroup;
+
+import androidx.test.filters.SmallTest;
+
+import com.android.systemui.R;
+import com.android.systemui.SysuiTestCase;
+import com.android.systemui.car.CarSystemUiTest;
+import com.android.systemui.car.window.OverlayViewGlobalStateController;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.ArgumentCaptor;
+import org.mockito.Captor;
+import org.mockito.Mock;
+import org.mockito.junit.MockitoJUnitRunner;
+
+@CarSystemUiTest
+@RunWith(MockitoJUnitRunner.class)
+@TestableLooper.RunWithLooper
+@SmallTest
+public class RearViewCameraViewControllerTest extends SysuiTestCase {
+ private static final String TEST_ACTIVITY_NAME = "testPackage/testActivity";
+ private RearViewCameraViewController mRearViewCameraViewController;
+
+ @Mock
+ private OverlayViewGlobalStateController mOverlayViewGlobalStateController;
+ @Mock
+ private ActivityView mMockActivityView;
+ @Captor
+ private ArgumentCaptor<Intent> mIntentCaptor;
+
+ private void setUpRearViewCameraViewController(String testActivityName) {
+ mContext.getOrCreateTestableResources().addOverride(
+ R.string.config_rearViewCameraActivity, testActivityName);
+ mRearViewCameraViewController = new RearViewCameraViewController(
+ mContext.getOrCreateTestableResources().getResources(),
+ mOverlayViewGlobalStateController);
+ mRearViewCameraViewController.inflate((ViewGroup) LayoutInflater.from(mContext).inflate(
+ R.layout.sysui_overlay_window, /* root= */ null));
+ }
+
+ @Test
+ public void testEmptyResourceDisablesController() {
+ setUpRearViewCameraViewController("");
+
+ assertThat(mRearViewCameraViewController.isEnabled()).isFalse();
+ }
+
+ @Test
+ public void testNonEmptyResourceEnablesController() {
+ setUpRearViewCameraViewController(TEST_ACTIVITY_NAME);
+
+ assertThat(mRearViewCameraViewController.isEnabled()).isTrue();
+ }
+
+ @Test
+ public void testShowInternal() {
+ setUpRearViewCameraViewController(TEST_ACTIVITY_NAME);
+ assertThat(mRearViewCameraViewController.isShown()).isFalse();
+ assertThat(mRearViewCameraViewController.mActivityView).isNull();
+
+ mRearViewCameraViewController.showInternal();
+
+ assertThat(mRearViewCameraViewController.isShown()).isTrue();
+ assertThat(mRearViewCameraViewController.mActivityView).isNotNull();
+ }
+
+ @Test
+ public void testHideInternal() {
+ setUpRearViewCameraViewController(TEST_ACTIVITY_NAME);
+ assertThat(mRearViewCameraViewController.isShown()).isFalse();
+ mRearViewCameraViewController.showInternal();
+ assertThat(mRearViewCameraViewController.isShown()).isTrue();
+
+ mRearViewCameraViewController.hideInternal();
+
+ assertThat(mRearViewCameraViewController.isShown()).isFalse();
+ assertThat(mRearViewCameraViewController.mActivityView).isNull();
+ }
+
+ @Test
+ public void testOnActivityViewReady_fireIntent() {
+ setUpRearViewCameraViewController(TEST_ACTIVITY_NAME);
+ mRearViewCameraViewController.mActivityViewCallback.onActivityViewReady(mMockActivityView);
+
+ verify(mMockActivityView).startActivity(mIntentCaptor.capture());
+ ComponentName expectedComponent = ComponentName.unflattenFromString(TEST_ACTIVITY_NAME);
+ assertThat(mIntentCaptor.getValue().getComponent()).isEqualTo(expectedComponent);
+ }
+}
diff --git a/packages/CarSystemUI/tests/src/com/android/systemui/car/rvc/RearViewCameraViewMediatorTest.java b/packages/CarSystemUI/tests/src/com/android/systemui/car/rvc/RearViewCameraViewMediatorTest.java
new file mode 100644
index 000000000000..5be8f91ff430
--- /dev/null
+++ b/packages/CarSystemUI/tests/src/com/android/systemui/car/rvc/RearViewCameraViewMediatorTest.java
@@ -0,0 +1,169 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.car.rvc;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyFloat;
+import static org.mockito.ArgumentMatchers.anyInt;
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.doAnswer;
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import android.car.Car;
+import android.car.VehicleAreaType;
+import android.car.VehicleGear;
+import android.car.VehiclePropertyIds;
+import android.car.hardware.CarPropertyValue;
+import android.car.hardware.property.CarPropertyManager;
+import android.car.hardware.property.CarPropertyManager.CarPropertyEventCallback;
+import android.content.BroadcastReceiver;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.testing.TestableLooper;
+import android.util.Log;
+
+import androidx.test.filters.SmallTest;
+
+import com.android.systemui.SysuiTestCase;
+import com.android.systemui.broadcast.BroadcastDispatcher;
+import com.android.systemui.car.CarServiceProvider;
+import com.android.systemui.car.CarServiceProvider.CarServiceOnConnectedListener;
+import com.android.systemui.car.CarSystemUiTest;
+
+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.junit.MockitoJUnitRunner;
+
+@CarSystemUiTest
+@RunWith(MockitoJUnitRunner.class)
+@TestableLooper.RunWithLooper
+@SmallTest
+public class RearViewCameraViewMediatorTest extends SysuiTestCase {
+ private static final String TAG = RearViewCameraViewMediatorTest.class.getSimpleName();
+
+ private RearViewCameraViewMediator mRearViewCameraViewMediator;
+
+ @Mock
+ private CarServiceProvider mCarServiceProvider;
+ @Mock
+ private Car mCar;
+ @Mock
+ private CarPropertyManager mCarPropertyManager;
+ @Captor
+ private ArgumentCaptor<CarPropertyEventCallback> mCarPropertyEventCallbackCaptor;
+
+ @Mock
+ private BroadcastDispatcher mBroadcastDispatcher;
+ @Captor
+ private ArgumentCaptor<BroadcastReceiver> mBroadcastReceiverCaptor;
+ @Captor
+ private ArgumentCaptor<IntentFilter> mIntentFilterCaptor;
+
+ @Mock
+ private RearViewCameraViewController mRearViewCameraViewController;
+
+ @Before
+ public void setUp() throws Exception {
+ mRearViewCameraViewMediator = new RearViewCameraViewMediator(
+ mRearViewCameraViewController, mCarServiceProvider, mBroadcastDispatcher);
+ }
+
+ public void setUpListener() {
+ doAnswer(invocation -> {
+ CarServiceOnConnectedListener listener = invocation.getArgument(0);
+ listener.onConnected(mCar);
+ return null;
+ }).when(mCarServiceProvider).addListener(any(CarServiceOnConnectedListener.class));
+ when(mCar.getCarManager(Car.PROPERTY_SERVICE)).thenReturn(mCarPropertyManager);
+ when(mRearViewCameraViewController.isEnabled()).thenReturn(true);
+
+ mRearViewCameraViewMediator.registerListeners();
+
+ verify(mCarPropertyManager).registerCallback(mCarPropertyEventCallbackCaptor.capture(),
+ eq(VehiclePropertyIds.GEAR_SELECTION), anyFloat());
+ verify(mBroadcastDispatcher).registerReceiver(mBroadcastReceiverCaptor.capture(),
+ mIntentFilterCaptor.capture(), any(), any());
+ assertThat(mIntentFilterCaptor.getValue().getAction(0)).isEqualTo(
+ Intent.ACTION_CLOSE_SYSTEM_DIALOGS);
+ }
+
+ @Test
+ public void testDoesnNotRegisterListenersWhenRearViewCameraViewControllerIsDisabled() {
+ when(mRearViewCameraViewController.isEnabled()).thenReturn(false);
+
+ mRearViewCameraViewMediator.registerListeners();
+
+ verify(mCarPropertyManager, never()).registerCallback(any(), anyInt(), anyFloat());
+ verify(mBroadcastDispatcher, never()).registerReceiver(any(), any(), any());
+ }
+
+ @Test
+ public void testGearReverseStartsRearViewCamera() {
+ setUpListener();
+
+ CarPropertyValue<Integer> gearReverse = new CarPropertyValue(
+ VehiclePropertyIds.GEAR_SELECTION, VehicleAreaType.VEHICLE_AREA_TYPE_GLOBAL,
+ VehicleGear.GEAR_REVERSE);
+ mCarPropertyEventCallbackCaptor.getValue().onChangeEvent(gearReverse);
+
+ verify(mRearViewCameraViewController, times(1)).start();
+ }
+
+ @Test
+ public void testGearNonReverseStopsRearViewCamera() {
+ setUpListener();
+
+ int[] nonReverseVehicleGears = new int[]{
+ VehicleGear.GEAR_NEUTRAL, VehicleGear.GEAR_PARK, VehicleGear.GEAR_DRIVE,
+ VehicleGear.GEAR_FIRST
+ };
+ for (int i = 0; i < nonReverseVehicleGears.length; ++i) {
+ Log.i(TAG, "testGearNonReverseStopsRearViewCamera: gear=" + nonReverseVehicleGears[i]);
+ CarPropertyValue<Integer> propertyGear = new CarPropertyValue(
+ VehiclePropertyIds.GEAR_SELECTION, VehicleAreaType.VEHICLE_AREA_TYPE_GLOBAL,
+ nonReverseVehicleGears[i]);
+ mCarPropertyEventCallbackCaptor.getValue().onChangeEvent(propertyGear);
+
+ verify(mRearViewCameraViewController, times(i + 1)).stop();
+ }
+ }
+
+ @Test
+ public void testBroadcastIntentStopsRearViewCamera() {
+ setUpListener();
+ when(mRearViewCameraViewController.isShown()).thenReturn(true);
+
+ Intent randomIntent = new Intent(Intent.ACTION_MAIN);
+ mBroadcastReceiverCaptor.getValue().onReceive(mContext, randomIntent);
+
+ verify(mRearViewCameraViewController, never()).stop();
+
+ Intent actionCloseSystemDialogs = new Intent(Intent.ACTION_CLOSE_SYSTEM_DIALOGS);
+ mBroadcastReceiverCaptor.getValue().onReceive(mContext, actionCloseSystemDialogs);
+
+ verify(mRearViewCameraViewController, times(1)).stop();
+ }
+}
diff --git a/packages/PackageInstaller/src/com/android/packageinstaller/UninstallerActivity.java b/packages/PackageInstaller/src/com/android/packageinstaller/UninstallerActivity.java
index be778e92787e..2674eaf4b76c 100755
--- a/packages/PackageInstaller/src/com/android/packageinstaller/UninstallerActivity.java
+++ b/packages/PackageInstaller/src/com/android/packageinstaller/UninstallerActivity.java
@@ -339,8 +339,9 @@ public class UninstallerActivity extends Activity {
broadcastIntent.putExtra(UninstallFinish.EXTRA_APP_LABEL, label);
broadcastIntent.putExtra(UninstallFinish.EXTRA_UNINSTALL_ID, uninstallId);
- PendingIntent pendingIntent = PendingIntent.getBroadcast(this, uninstallId,
- broadcastIntent, PendingIntent.FLAG_UPDATE_CURRENT);
+ PendingIntent pendingIntent =
+ PendingIntent.getBroadcast(this, uninstallId, broadcastIntent,
+ PendingIntent.FLAG_MUTABLE | PendingIntent.FLAG_UPDATE_CURRENT);
NotificationManager notificationManager = getSystemService(NotificationManager.class);
NotificationChannel uninstallingChannel = new NotificationChannel(UNINSTALLING_CHANNEL,
diff --git a/packages/PrintSpooler/res/values-mr/strings.xml b/packages/PrintSpooler/res/values-mr/strings.xml
index 4d7e919ad125..81194399c00e 100644
--- a/packages/PrintSpooler/res/values-mr/strings.xml
+++ b/packages/PrintSpooler/res/values-mr/strings.xml
@@ -63,7 +63,7 @@
<string name="printer_info_desc" msgid="7181988788991581654">"या प्रिंटर विषयी अधिक माहिती"</string>
<string name="notification_channel_progress" msgid="872788690775721436">"प्रिंट कार्ये चालवणे"</string>
<string name="notification_channel_failure" msgid="9042250774797916414">"अयशस्वी प्रिंट कार्ये"</string>
- <string name="could_not_create_file" msgid="3425025039427448443">"फाईल तयार करणेे शक्य झाले नाही"</string>
+ <string name="could_not_create_file" msgid="3425025039427448443">"फाइल तयार करणेे शक्य झाले नाही"</string>
<string name="print_services_disabled_toast" msgid="9089060734685174685">"काही प्रिंट सेवा अक्षम केल्या आहेत"</string>
<string name="print_searching_for_printers" msgid="6550424555079932867">"प्रिंटर शोधत आहे"</string>
<string name="print_no_print_services" msgid="8561247706423327966">"कोणत्याही प्रिंट सेवा सक्षम केलेल्या नाहीत"</string>
diff --git a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java
index f1fb527245a1..94de48595b0d 100644
--- a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java
+++ b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java
@@ -749,25 +749,25 @@ class SettingsProtoDumpUtil {
Settings.Global.GPU_DEBUG_LAYERS,
GlobalSettingsProto.Gpu.DEBUG_LAYERS);
dumpSetting(s, p,
- Settings.Global.GLOBAL_SETTINGS_ANGLE_DEBUG_PACKAGE,
+ Settings.Global.ANGLE_DEBUG_PACKAGE,
GlobalSettingsProto.Gpu.ANGLE_DEBUG_PACKAGE);
dumpSetting(s, p,
- Settings.Global.GLOBAL_SETTINGS_ANGLE_GL_DRIVER_ALL_ANGLE,
+ Settings.Global.ANGLE_GL_DRIVER_ALL_ANGLE,
GlobalSettingsProto.Gpu.ANGLE_GL_DRIVER_ALL_ANGLE);
dumpSetting(s, p,
- Settings.Global.GLOBAL_SETTINGS_ANGLE_GL_DRIVER_SELECTION_PKGS,
+ Settings.Global.ANGLE_GL_DRIVER_SELECTION_PKGS,
GlobalSettingsProto.Gpu.ANGLE_GL_DRIVER_SELECTION_PKGS);
dumpSetting(s, p,
- Settings.Global.GLOBAL_SETTINGS_ANGLE_GL_DRIVER_SELECTION_VALUES,
+ Settings.Global.ANGLE_GL_DRIVER_SELECTION_VALUES,
GlobalSettingsProto.Gpu.ANGLE_GL_DRIVER_SELECTION_VALUES);
dumpSetting(s, p,
- Settings.Global.GLOBAL_SETTINGS_ANGLE_ALLOWLIST,
+ Settings.Global.ANGLE_ALLOWLIST,
GlobalSettingsProto.Gpu.ANGLE_ALLOWLIST);
dumpSetting(s, p,
Settings.Global.ANGLE_EGL_FEATURES,
GlobalSettingsProto.Gpu.ANGLE_EGL_FEATURES);
dumpSetting(s, p,
- Settings.Global.GLOBAL_SETTINGS_SHOW_ANGLE_IN_USE_DIALOG_BOX,
+ Settings.Global.SHOW_ANGLE_IN_USE_DIALOG_BOX,
GlobalSettingsProto.Gpu.SHOW_ANGLE_IN_USE_DIALOG);
dumpSetting(s, p,
Settings.Global.GPU_DEBUG_LAYER_APP,
@@ -1494,9 +1494,6 @@ class SettingsProtoDumpUtil {
Settings.Global.WEBVIEW_DATA_REDUCTION_PROXY_KEY,
GlobalSettingsProto.Webview.DATA_REDUCTION_PROXY_KEY);
dumpSetting(s, p,
- Settings.Global.WEBVIEW_FALLBACK_LOGIC_ENABLED,
- GlobalSettingsProto.Webview.FALLBACK_LOGIC_ENABLED);
- dumpSetting(s, p,
Settings.Global.WEBVIEW_PROVIDER,
GlobalSettingsProto.Webview.PROVIDER);
dumpSetting(s, p,
diff --git a/packages/SettingsProvider/test/src/android/provider/SettingsBackupTest.java b/packages/SettingsProvider/test/src/android/provider/SettingsBackupTest.java
index 9b0df9625df7..10d2eab167e7 100644
--- a/packages/SettingsProvider/test/src/android/provider/SettingsBackupTest.java
+++ b/packages/SettingsProvider/test/src/android/provider/SettingsBackupTest.java
@@ -408,6 +408,7 @@ public class SettingsBackupTest {
Settings.Global.PDP_WATCHDOG_MAX_PDP_RESET_FAIL_COUNT,
Settings.Global.PDP_WATCHDOG_POLL_INTERVAL_MS,
Settings.Global.PDP_WATCHDOG_TRIGGER_PACKET_COUNT,
+ Settings.Global.PEOPLE_SPACE_CONVERSATION_TYPE,
Settings.Global.POLICY_CONTROL,
Settings.Global.POWER_BUTTON_SUPPRESSION_DELAY_AFTER_GESTURE_WAKE,
Settings.Global.POWER_MANAGER_CONSTANTS,
@@ -502,11 +503,11 @@ public class SettingsBackupTest {
Settings.Global.GPU_DEBUG_APP,
Settings.Global.GPU_DEBUG_LAYERS,
Settings.Global.GPU_DEBUG_LAYERS_GLES,
- Settings.Global.GLOBAL_SETTINGS_ANGLE_DEBUG_PACKAGE,
- Settings.Global.GLOBAL_SETTINGS_ANGLE_GL_DRIVER_ALL_ANGLE,
- Settings.Global.GLOBAL_SETTINGS_ANGLE_GL_DRIVER_SELECTION_PKGS,
- Settings.Global.GLOBAL_SETTINGS_ANGLE_GL_DRIVER_SELECTION_VALUES,
- Settings.Global.GLOBAL_SETTINGS_ANGLE_ALLOWLIST,
+ Settings.Global.ANGLE_DEBUG_PACKAGE,
+ Settings.Global.ANGLE_GL_DRIVER_ALL_ANGLE,
+ Settings.Global.ANGLE_GL_DRIVER_SELECTION_PKGS,
+ Settings.Global.ANGLE_GL_DRIVER_SELECTION_VALUES,
+ Settings.Global.ANGLE_ALLOWLIST,
Settings.Global.ANGLE_EGL_FEATURES,
Settings.Global.UPDATABLE_DRIVER_ALL_APPS,
Settings.Global.UPDATABLE_DRIVER_PRODUCTION_OPT_IN_APPS,
@@ -516,7 +517,7 @@ public class SettingsBackupTest {
Settings.Global.UPDATABLE_DRIVER_PRODUCTION_DENYLIST,
Settings.Global.UPDATABLE_DRIVER_PRODUCTION_ALLOWLIST,
Settings.Global.UPDATABLE_DRIVER_SPHAL_LIBRARIES,
- Settings.Global.GLOBAL_SETTINGS_SHOW_ANGLE_IN_USE_DIALOG_BOX,
+ Settings.Global.SHOW_ANGLE_IN_USE_DIALOG_BOX,
Settings.Global.GPU_DEBUG_LAYER_APP,
Settings.Global.ENABLE_GNSS_RAW_MEAS_FULL_TRACKING,
Settings.Global.INSTALL_CARRIER_APP_NOTIFICATION_PERSISTENT,
@@ -525,7 +526,6 @@ public class SettingsBackupTest {
Settings.Global.NETWORK_ACCESS_TIMEOUT_MS,
Settings.Global.WARNING_TEMPERATURE,
Settings.Global.WEBVIEW_DATA_REDUCTION_PROXY_KEY,
- Settings.Global.WEBVIEW_FALLBACK_LOGIC_ENABLED,
Settings.Global.WEBVIEW_MULTIPROCESS,
Settings.Global.WEBVIEW_PROVIDER,
Settings.Global.WFC_IMS_ENABLED,
diff --git a/packages/Shell/res/values-mr/strings.xml b/packages/Shell/res/values-mr/strings.xml
index 9595e28eb6e2..a957184cdf6a 100644
--- a/packages/Shell/res/values-mr/strings.xml
+++ b/packages/Shell/res/values-mr/strings.xml
@@ -31,8 +31,8 @@
<string name="bugreport_confirm" msgid="5917407234515812495">"बग रीपोर्टांमध्ये तुम्ही संवेदनशील (अ‍ॅप-वापर आणि स्थान डेटा यासारखा) डेटा म्हणून विचार करता त्या डेटाच्या समावेशासह सिस्टीमच्या विविध लॉग फायलींमधील डेटा असतो. ज्या लोकांवर आणि अ‍ॅपवर तुमचा विश्वास आहे केवळ त्यांच्यासह हा बग रीपोर्ट शेअर करा."</string>
<string name="bugreport_confirm_dont_repeat" msgid="6179945398364357318">"पुन्हा दर्शवू नका"</string>
<string name="bugreport_storage_title" msgid="5332488144740527109">"बग रीपोर्ट"</string>
- <string name="bugreport_unreadable_text" msgid="586517851044535486">"बग रीपोर्ट फाईल वाचणे शक्य झाले नाही"</string>
- <string name="bugreport_add_details_to_zip_failed" msgid="1302931926486712371">"झिप फाईल मध्ये बग रीपोर्ट तपशील जोडणे शक्य झाले नाही"</string>
+ <string name="bugreport_unreadable_text" msgid="586517851044535486">"बग रीपोर्ट फाइल वाचणे शक्य झाले नाही"</string>
+ <string name="bugreport_add_details_to_zip_failed" msgid="1302931926486712371">"झिप फाइल मध्ये बग रीपोर्ट तपशील जोडणे शक्य झाले नाही"</string>
<string name="bugreport_unnamed" msgid="2800582406842092709">"अनामित"</string>
<string name="bugreport_info_action" msgid="2158204228510576227">"तपशील"</string>
<string name="bugreport_screenshot_action" msgid="8677781721940614995">"स्क्रीनशॉट"</string>
diff --git a/packages/Shell/src/com/android/shell/BugreportProgressService.java b/packages/Shell/src/com/android/shell/BugreportProgressService.java
index 0eac4add7b09..02751e27874d 100644
--- a/packages/Shell/src/com/android/shell/BugreportProgressService.java
+++ b/packages/Shell/src/com/android/shell/BugreportProgressService.java
@@ -737,18 +737,20 @@ public class BugreportProgressService extends Service {
final Intent infoIntent = new Intent(mContext, BugreportProgressService.class);
infoIntent.setAction(INTENT_BUGREPORT_INFO_LAUNCH);
infoIntent.putExtra(EXTRA_ID, info.id);
+ // Simple notification action button clicks are immutable
final PendingIntent infoPendingIntent =
PendingIntent.getService(mContext, info.id, infoIntent,
- PendingIntent.FLAG_UPDATE_CURRENT);
+ PendingIntent.FLAG_UPDATE_CURRENT | PendingIntent.FLAG_IMMUTABLE);
final Action infoAction = new Action.Builder(null,
mContext.getString(R.string.bugreport_info_action),
infoPendingIntent).build();
final Intent screenshotIntent = new Intent(mContext, BugreportProgressService.class);
screenshotIntent.setAction(INTENT_BUGREPORT_SCREENSHOT);
screenshotIntent.putExtra(EXTRA_ID, info.id);
+ // Simple notification action button clicks are immutable
PendingIntent screenshotPendingIntent = mTakingScreenshot ? null : PendingIntent
.getService(mContext, info.id, screenshotIntent,
- PendingIntent.FLAG_UPDATE_CURRENT);
+ PendingIntent.FLAG_UPDATE_CURRENT | PendingIntent.FLAG_IMMUTABLE);
final Action screenshotAction = new Action.Builder(null,
mContext.getString(R.string.bugreport_screenshot_action),
screenshotPendingIntent).build();
diff --git a/packages/SystemUI/Android.bp b/packages/SystemUI/Android.bp
index a9a5671d5b03..80a6257fd7a9 100644
--- a/packages/SystemUI/Android.bp
+++ b/packages/SystemUI/Android.bp
@@ -139,7 +139,9 @@ android_library {
"SystemUI-tags",
"SystemUI-proto",
"metrics-helper-lib",
- "androidx.test.rules", "hamcrest-library",
+ "hamcrest-library",
+ "androidx.test.rules",
+ "androidx.test.uiautomator",
"mockito-target-extended-minus-junit4",
"testables",
"truth-prebuilt",
diff --git a/packages/SystemUI/AndroidManifest.xml b/packages/SystemUI/AndroidManifest.xml
index bf9b809e5684..407104504132 100644
--- a/packages/SystemUI/AndroidManifest.xml
+++ b/packages/SystemUI/AndroidManifest.xml
@@ -573,12 +573,37 @@
</activity>
<!-- People Space UI Screen -->
- <activity
- android:name=".people.PeopleSpaceActivity"
+ <activity android:name=".people.PeopleSpaceActivity"
+ android:label="People"
+ android:icon="@drawable/ic_music_note"
android:exported="true"
- android:theme="@android:style/Theme.Material.NoActionBar">
+ android:enabled="false"
+ android:theme="@android:style/Theme.Material.NoActionBar"
+ android:launchMode="singleInstance">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN"/>
+ <category android:name="android.intent.category.LAUNCHER"/>
+ </intent-filter>
</activity>
+ <!-- People Space Widget -->
+ <receiver
+ android:name=".people.widget.PeopleSpaceWidgetProvider"
+ android:label="People Space"
+ android:enabled="true"
+ android:exported="true">
+ <intent-filter>
+ <action android:name="android.appwidget.action.APPWIDGET_UPDATE" />
+ </intent-filter>
+ <meta-data android:name="android.appwidget.provider"
+ android:resource="@xml/people_space_widget_info" />
+ </receiver>
+
+ <!-- Widget service -->
+ <service android:name=".people.widget.PeopleSpaceWidgetService"
+ android:permission="android.permission.BIND_REMOTEVIEWS"
+ android:exported="false" />
+
<!-- a gallery of delicious treats -->
<service
android:name=".DessertCaseDream"
diff --git a/packages/SystemUI/res-keyguard/font/clock.xml b/packages/SystemUI/res-keyguard/font/clock.xml
new file mode 100644
index 000000000000..008b32223ec6
--- /dev/null
+++ b/packages/SystemUI/res-keyguard/font/clock.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+**
+** Copyright 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.
+*/
+-->
+
+<!--
+** AOD/LockScreen Clock font.
+** Should include all numeric glyphs in all supported locales.
+** Recommended: font with variable width to support AOD => LS animations
+-->
+<font-family xmlns:android="http://schemas.android.com/apk/res/android">
+ <!-- TODO (b/171376810): switch this font with a variable width clock font for AOSP -->
+ <font android:typeface="monospace" android:font="@*android:string/config_headlineFontFamily" />
+</font-family> \ No newline at end of file
diff --git a/packages/SystemUI/res-keyguard/layout/keyguard_clock_switch.xml b/packages/SystemUI/res-keyguard/layout/keyguard_clock_switch.xml
index bf2963cd0b7f..f22c729744d3 100644
--- a/packages/SystemUI/res-keyguard/layout/keyguard_clock_switch.xml
+++ b/packages/SystemUI/res-keyguard/layout/keyguard_clock_switch.xml
@@ -61,6 +61,28 @@
android:visibility="invisible"
/>
</FrameLayout>
+ <FrameLayout
+ android:id="@+id/new_lockscreen_clock_view"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_alignParentEnd="true"
+ android:layout_alignParentTop="true"
+ android:visibility="gone">
+ <com.android.keyguard.GradientTextClock
+ android:id="@+id/gradient_clock_view"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:textSize="100dp"
+ android:letterSpacing="0.02"
+ android:lineSpacingMultiplier=".8"
+ android:includeFontPadding="false"
+ android:fontFamily="@font/clock"
+ android:typeface="monospace"
+ android:format12Hour="hh\nmm"
+ android:format24Hour="HH\nmm"
+ android:elegantTextHeight="false"
+ />
+ </FrameLayout>
<include layout="@layout/keyguard_status_area"
android:id="@+id/keyguard_status_area"
android:layout_width="match_parent"
diff --git a/packages/SystemUI/res/drawable/ic_check_box.xml b/packages/SystemUI/res/drawable/ic_check_box.xml
new file mode 100644
index 000000000000..a8d1a652b35b
--- /dev/null
+++ b/packages/SystemUI/res/drawable/ic_check_box.xml
@@ -0,0 +1,26 @@
+<!--
+ 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
+ -->
+
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+ <item
+ android:id="@+id/checked"
+ android:state_checked="true"
+ android:drawable="@drawable/ic_check_box_blue_24dp" />
+ <item
+ android:id="@+id/unchecked"
+ android:state_checked="false"
+ android:drawable="@drawable/ic_check_box_outline_24dp" />
+</selector>
diff --git a/packages/SystemUI/res/drawable/ic_check_box_blue_24dp.xml b/packages/SystemUI/res/drawable/ic_check_box_blue_24dp.xml
new file mode 100644
index 000000000000..43cae6983981
--- /dev/null
+++ b/packages/SystemUI/res/drawable/ic_check_box_blue_24dp.xml
@@ -0,0 +1,26 @@
+<!--
+ 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
+ -->
+
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="24dp"
+ android:height="24dp"
+ android:viewportWidth="24"
+ android:viewportHeight="24">
+ <path
+ android:pathData="M19,3L5,3c-1.11,0 -2,0.9 -2,2v14c0,1.1 0.89,2 2,2h14c1.11,0 2,-0.9 2,-2L21,5c0,-1.1 -0.89,-2 -2,-2zM10,17l-5,-5 1.41,-1.41L10,14.17l7.59,-7.59L19,8l-9,9z"
+ android:fillColor="#4285F4"/>
+</vector>
+
diff --git a/packages/SystemUI/res/drawable/ic_check_box_outline_24dp.xml b/packages/SystemUI/res/drawable/ic_check_box_outline_24dp.xml
new file mode 100644
index 000000000000..f6f453af2a26
--- /dev/null
+++ b/packages/SystemUI/res/drawable/ic_check_box_outline_24dp.xml
@@ -0,0 +1,26 @@
+<!--
+ 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
+ -->
+
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="24dp"
+ android:height="24dp"
+ android:viewportWidth="24"
+ android:viewportHeight="24">
+ <path
+ android:pathData="M19,5v14H5V5h14m0,-2H5c-1.1,0 -2,0.9 -2,2v14c0,1.1 0.9,2 2,2h14c1.1,0 2,-0.9 2,-2V5c0,-1.1 -0.9,-2 -2,-2z"
+ android:fillColor="#757575"/>
+</vector>
+
diff --git a/packages/SystemUI/res/drawable/ic_speaker_group_black_24dp.xml b/packages/SystemUI/res/drawable/ic_speaker_group_black_24dp.xml
new file mode 100644
index 000000000000..ae0d56217fd9
--- /dev/null
+++ b/packages/SystemUI/res/drawable/ic_speaker_group_black_24dp.xml
@@ -0,0 +1,31 @@
+<!--
+ 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
+ -->
+
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="24dp"
+ android:height="24dp"
+ android:viewportWidth="24"
+ android:viewportHeight="24">
+ <path
+ android:pathData="M18.2,1L9.8,1C8.81,1 8,1.81 8,2.8v14.4c0,0.99 0.81,1.79 1.8,1.79l8.4,0.01c0.99,0 1.8,-0.81 1.8,-1.8L20,2.8c0,-0.99 -0.81,-1.8 -1.8,-1.8zM14,3c1.1,0 2,0.89 2,2s-0.9,2 -2,2 -2,-0.89 -2,-2 0.9,-2 2,-2zM14,16.5c-2.21,0 -4,-1.79 -4,-4s1.79,-4 4,-4 4,1.79 4,4 -1.79,4 -4,4z"
+ android:fillColor="#000000"/>
+ <path
+ android:pathData="M14,12.5m-2.5,0a2.5,2.5 0,1 1,5 0a2.5,2.5 0,1 1,-5 0"
+ android:fillColor="#000000"/>
+ <path
+ android:pathData="M6,5H4v16c0,1.1 0.89,2 2,2h10v-2H6V5z"
+ android:fillColor="#000000"/>
+</vector>
diff --git a/packages/SystemUI/res/layout/global_screenshot.xml b/packages/SystemUI/res/layout/global_screenshot.xml
index ef7325ea8f38..e0333eb82d51 100644
--- a/packages/SystemUI/res/layout/global_screenshot.xml
+++ b/packages/SystemUI/res/layout/global_screenshot.xml
@@ -14,7 +14,7 @@
~ See the License for the specific language governing permissions and
~ limitations under the License.
-->
-<FrameLayout
+<com.android.systemui.screenshot.ScreenshotView
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/global_screenshot_frame"
android:layout_width="match_parent"
@@ -62,4 +62,4 @@
android:layout_margin="@dimen/screenshot_dismiss_button_margin"
android:src="@drawable/screenshot_cancel"/>
</FrameLayout>
-</FrameLayout>
+</com.android.systemui.screenshot.ScreenshotView>
diff --git a/packages/SystemUI/res/layout/media_output_list_item.xml b/packages/SystemUI/res/layout/media_output_list_item.xml
index ac8b7b5812bd..c98c3a0beb65 100644
--- a/packages/SystemUI/res/layout/media_output_list_item.xml
+++ b/packages/SystemUI/res/layout/media_output_list_item.xml
@@ -15,97 +15,124 @@
~ limitations under the License.
-->
-<FrameLayout
- android:id="@+id/device_container"
+<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
+ android:id="@+id/device_container"
android:layout_width="match_parent"
- android:layout_height="64dp">
-
+ android:layout_height="wrap_content"
+ android:orientation="vertical">
<FrameLayout
- android:layout_width="36dp"
- android:layout_height="36dp"
- android:layout_gravity="center_vertical"
- android:layout_marginStart="16dp">
- <ImageView
- android:id="@+id/title_icon"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_gravity="center"/>
- </FrameLayout>
+ android:layout_width="match_parent"
+ android:layout_height="64dp">
- <TextView
- android:id="@+id/title"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_gravity="center_vertical"
- android:layout_marginStart="68dp"
- android:ellipsize="end"
- android:maxLines="1"
- android:textColor="?android:attr/textColorPrimary"
- android:textSize="14sp"/>
+ <FrameLayout
+ android:layout_width="36dp"
+ android:layout_height="36dp"
+ android:layout_gravity="center_vertical"
+ android:layout_marginStart="16dp">
+ <ImageView
+ android:id="@+id/title_icon"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_gravity="center"/>
+ </FrameLayout>
- <RelativeLayout
- android:id="@+id/two_line_layout"
- android:layout_width="wrap_content"
- android:layout_height="48dp"
- android:layout_marginStart="52dp"
- android:layout_marginEnd="69dp"
- android:layout_marginTop="10dp">
<TextView
- android:id="@+id/two_line_title"
+ android:id="@+id/title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
- android:layout_marginStart="16dp"
- android:layout_marginEnd="15dp"
+ android:layout_gravity="center_vertical"
+ android:layout_marginStart="68dp"
android:ellipsize="end"
android:maxLines="1"
android:textColor="?android:attr/textColorPrimary"
android:textSize="14sp"/>
- <TextView
- android:id="@+id/subtitle"
+
+ <RelativeLayout
+ android:id="@+id/two_line_layout"
android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_marginStart="16dp"
- android:layout_marginEnd="15dp"
- android:layout_marginBottom="7dp"
- android:layout_alignParentBottom="true"
- android:ellipsize="end"
- android:maxLines="1"
- android:textColor="?android:attr/textColorSecondary"
- android:textSize="12sp"
- android:fontFamily="roboto-regular"
+ android:layout_height="48dp"
+ android:layout_marginStart="52dp"
+ android:layout_marginEnd="69dp"
+ android:layout_marginTop="10dp">
+ <TextView
+ android:id="@+id/two_line_title"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_marginStart="16dp"
+ android:layout_marginEnd="15dp"
+ android:ellipsize="end"
+ android:maxLines="1"
+ android:textColor="?android:attr/textColorPrimary"
+ android:textSize="14sp"/>
+ <TextView
+ android:id="@+id/subtitle"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_marginStart="16dp"
+ android:layout_marginEnd="15dp"
+ android:layout_marginBottom="7dp"
+ android:layout_alignParentBottom="true"
+ android:ellipsize="end"
+ android:maxLines="1"
+ android:textColor="?android:attr/textColorSecondary"
+ android:textSize="12sp"
+ android:fontFamily="roboto-regular"
+ android:visibility="gone"/>
+ <SeekBar
+ android:id="@+id/volume_seekbar"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_alignParentBottom="true"/>
+ </RelativeLayout>
+
+ <ProgressBar
+ android:id="@+id/volume_indeterminate_progress"
+ style="@*android:style/Widget.Material.ProgressBar.Horizontal"
+ android:layout_width="258dp"
+ android:layout_height="18dp"
+ android:layout_marginStart="68dp"
+ android:layout_marginTop="40dp"
+ android:indeterminate="true"
+ android:indeterminateOnly="true"
android:visibility="gone"/>
- <SeekBar
- android:id="@+id/volume_seekbar"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:layout_alignParentBottom="true"/>
- </RelativeLayout>
- <ProgressBar
- android:id="@+id/volume_indeterminate_progress"
- style="@*android:style/Widget.Material.ProgressBar.Horizontal"
- android:layout_width="258dp"
- android:layout_height="18dp"
- android:layout_marginStart="68dp"
- android:layout_marginTop="40dp"
- android:indeterminate="true"
- android:indeterminateOnly="true"
- android:visibility="gone"/>
+ <View
+ android:id="@+id/end_divider"
+ android:layout_width="1dp"
+ android:layout_height="36dp"
+ android:layout_marginEnd="68dp"
+ android:layout_gravity="right|center_vertical"
+ android:background="?android:attr/listDivider"
+ android:visibility="gone"/>
+
+ <ImageView
+ android:id="@+id/add_icon"
+ android:layout_width="24dp"
+ android:layout_height="24dp"
+ android:layout_gravity="right|center_vertical"
+ android:layout_marginEnd="24dp"
+ android:src="@drawable/ic_add"
+ android:tint="?android:attr/colorAccent"
+ android:visibility="gone"/>
+
+ <CheckBox
+ android:id="@+id/check_box"
+ android:layout_width="24dp"
+ android:layout_height="24dp"
+ android:layout_gravity="right|center_vertical"
+ android:layout_marginEnd="24dp"
+ android:button="@drawable/ic_check_box"
+ android:visibility="gone"/>
+ </FrameLayout>
<View
- android:layout_width="1dp"
- android:layout_height="36dp"
- android:layout_marginEnd="68dp"
- android:layout_gravity="right|center_vertical"
+ android:id="@+id/bottom_divider"
+ android:layout_width="match_parent"
+ android:layout_height="1dp"
+ android:layout_marginTop="12dp"
+ android:layout_marginBottom="12dp"
+ android:layout_gravity="bottom"
android:background="?android:attr/listDivider"
android:visibility="gone"/>
-
- <ImageView
- android:id="@+id/end_icon"
- android:layout_width="24dp"
- android:layout_height="24dp"
- android:layout_gravity="right|center_vertical"
- android:layout_marginEnd="24dp"
- android:visibility="gone"/>
-</FrameLayout> \ No newline at end of file
+</LinearLayout> \ No newline at end of file
diff --git a/packages/SystemUI/res/layout/people_space_widget.xml b/packages/SystemUI/res/layout/people_space_widget.xml
new file mode 100644
index 000000000000..60200993e3bf
--- /dev/null
+++ b/packages/SystemUI/res/layout/people_space_widget.xml
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ~ Copyright (C) 2020 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License.
+ -->
+<ListView
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:id="@+id/widget_list_view"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:background="@android:color/holo_blue_light"
+ android:clipChildren="false"
+ android:clipToPadding="false"
+ android:padding="5dp"
+ android:divider="@null"
+ android:dividerHeight="0dp"/> \ No newline at end of file
diff --git a/packages/SystemUI/res/layout/people_space_widget_item.xml b/packages/SystemUI/res/layout/people_space_widget_item.xml
new file mode 100644
index 000000000000..a40bfffaabd7
--- /dev/null
+++ b/packages/SystemUI/res/layout/people_space_widget_item.xml
@@ -0,0 +1,59 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ~ Copyright (C) 2020 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License.
+ -->
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:id="@+id/item"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:orientation="vertical">
+ <LinearLayout
+ android:background="@drawable/people_space_tile_view_card"
+ android:orientation="vertical"
+ android:padding="6dp"
+ android:layout_marginBottom="6dp"
+ android:elevation="4dp"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:gravity="start">
+ <ImageView
+ android:id="@+id/package_icon"
+ android:layout_width="30dp"
+ android:layout_height="30dp"
+ android:layout_gravity="end" />
+ <ImageView
+ android:id="@+id/person_icon"
+ android:layout_width="30dp"
+ android:layout_height="30dp"
+ android:layout_gravity="start" />
+ <TextView
+ android:id="@+id/name"
+ android:textAppearance="@*android:style/TextAppearance.DeviceDefault.ListItem"
+ android:textSize="18sp"
+ android:textColor="?android:attr/textColorPrimary"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_gravity="start" />
+ <TextView
+ android:id="@+id/status"
+ android:textAppearance="@*android:style/TextAppearance.DeviceDefault.ListItem"
+ android:paddingVertical="2dp"
+ android:textSize="14sp"
+ android:textColor="?android:attr/textColorSecondary"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_gravity="start" />
+ </LinearLayout>
+</LinearLayout>
diff --git a/packages/SystemUI/res/layout/qs_footer_impl.xml b/packages/SystemUI/res/layout/qs_footer_impl.xml
index 436188a83d4f..0822947e8b16 100644
--- a/packages/SystemUI/res/layout/qs_footer_impl.xml
+++ b/packages/SystemUI/res/layout/qs_footer_impl.xml
@@ -16,7 +16,7 @@
-->
<!-- Extends FrameLayout -->
-<com.android.systemui.qs.QSFooterImpl
+<com.android.systemui.qs.QSFooterView
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/qs_footer"
android:layout_width="match_parent"
@@ -130,4 +130,4 @@
</com.android.systemui.statusbar.AlphaOptimizedFrameLayout>
</com.android.keyguard.AlphaOptimizedLinearLayout>
</LinearLayout>
-</com.android.systemui.qs.QSFooterImpl>
+</com.android.systemui.qs.QSFooterView>
diff --git a/packages/SystemUI/res/values-af/strings.xml b/packages/SystemUI/res/values-af/strings.xml
index e4d751ab100d..220a77318ce6 100644
--- a/packages/SystemUI/res/values-af/strings.xml
+++ b/packages/SystemUI/res/values-af/strings.xml
@@ -86,8 +86,7 @@
<string name="screenshot_failed_to_save_unknown_text" msgid="1506621600548684129">"Probeer weer skermkiekie neem"</string>
<string name="screenshot_failed_to_save_text" msgid="8344173457344027501">"Kan weens beperkte bergingspasie nie skermkiekie stoor nie"</string>
<string name="screenshot_failed_to_capture_text" msgid="7818288545874407451">"Die program of jou organisasie laat nie toe dat skermkiekies geneem word nie"</string>
- <!-- no translation found for screenshot_edit (3510496440489019191) -->
- <skip />
+ <string name="screenshot_edit" msgid="3510496440489019191">"Wysig skermkiekie"</string>
<string name="screenshot_dismiss_ui_description" msgid="934736855340147968">"Maak skermkiekie toe"</string>
<string name="screenshot_preview_description" msgid="7606510140714080474">"Skermkiekievoorskou"</string>
<string name="screenrecord_name" msgid="2596401223859996572">"Skermopnemer"</string>
@@ -1065,8 +1064,7 @@
<string name="controls_seeding_in_progress" msgid="3033855341410264148">"Laai tans aanbevelings"</string>
<string name="controls_media_title" msgid="1746947284862928133">"Media"</string>
<string name="controls_media_close_session" msgid="3957093425905475065">"Versteek die huidige sessie."</string>
- <!-- no translation found for controls_media_active_session (1984383994625845642) -->
- <skip />
+ <string name="controls_media_active_session" msgid="1984383994625845642">"Huidige sessie kan nie versteek word nie."</string>
<string name="controls_media_dismiss_button" msgid="9081375542265132213">"Maak toe"</string>
<string name="controls_media_resume" msgid="1933520684481586053">"Hervat"</string>
<string name="controls_media_settings_button" msgid="5815790345117172504">"Instellings"</string>
diff --git a/packages/SystemUI/res/values-am/strings.xml b/packages/SystemUI/res/values-am/strings.xml
index 8c22e8f17552..b2a7c16c8ad0 100644
--- a/packages/SystemUI/res/values-am/strings.xml
+++ b/packages/SystemUI/res/values-am/strings.xml
@@ -86,8 +86,7 @@
<string name="screenshot_failed_to_save_unknown_text" msgid="1506621600548684129">"ቅጽበታዊ ገጽ ዕይታን እንደገና ማንሳት ይሞክሩ"</string>
<string name="screenshot_failed_to_save_text" msgid="8344173457344027501">"ባለው ውሱን የማከማቻ ቦታ ምክንያት ቅጽበታዊ ገጽ ዕይታን ማስቀመጥ አይችልም"</string>
<string name="screenshot_failed_to_capture_text" msgid="7818288545874407451">"ቅጽበታዊ ገጽ እይታዎችን ማንሳት በመተግበሪያው ወይም በእርስዎ ድርጅት አይፈቀድም"</string>
- <!-- no translation found for screenshot_edit (3510496440489019191) -->
- <skip />
+ <string name="screenshot_edit" msgid="3510496440489019191">"ቅጽበታዊ ገጽ ዕይታን አርትዕ ያድርጉ"</string>
<string name="screenshot_dismiss_ui_description" msgid="934736855340147968">"ቅጽበታዊ ገጽ እይታን አሰናብት"</string>
<string name="screenshot_preview_description" msgid="7606510140714080474">"የቅጽበታዊ ገጽ ዕይታ ቅድመ-ዕይታ"</string>
<string name="screenrecord_name" msgid="2596401223859996572">"የማያ መቅጃ"</string>
@@ -1065,8 +1064,7 @@
<string name="controls_seeding_in_progress" msgid="3033855341410264148">"ምክሮችን በመጫን ላይ"</string>
<string name="controls_media_title" msgid="1746947284862928133">"ሚዲያ"</string>
<string name="controls_media_close_session" msgid="3957093425905475065">"የአሁኑን ክፍለ-ጊዜ ደብቅ።"</string>
- <!-- no translation found for controls_media_active_session (1984383994625845642) -->
- <skip />
+ <string name="controls_media_active_session" msgid="1984383994625845642">"የአሁኑ ክፍለ ጊዜ መደበቅ አይችልም።"</string>
<string name="controls_media_dismiss_button" msgid="9081375542265132213">"አሰናብት"</string>
<string name="controls_media_resume" msgid="1933520684481586053">"ከቆመበት ቀጥል"</string>
<string name="controls_media_settings_button" msgid="5815790345117172504">"ቅንብሮች"</string>
diff --git a/packages/SystemUI/res/values-ar/strings.xml b/packages/SystemUI/res/values-ar/strings.xml
index 2c74a2789b36..2cced237e948 100644
--- a/packages/SystemUI/res/values-ar/strings.xml
+++ b/packages/SystemUI/res/values-ar/strings.xml
@@ -86,8 +86,7 @@
<string name="screenshot_failed_to_save_unknown_text" msgid="1506621600548684129">"جرّب أخذ لقطة الشاشة مرة أخرى"</string>
<string name="screenshot_failed_to_save_text" msgid="8344173457344027501">"يتعذر حفظ لقطة الشاشة لأن مساحة التخزين المتاحة محدودة."</string>
<string name="screenshot_failed_to_capture_text" msgid="7818288545874407451">"يحظر التطبيق أو تحظر مؤسستك التقاط لقطات شاشة"</string>
- <!-- no translation found for screenshot_edit (3510496440489019191) -->
- <skip />
+ <string name="screenshot_edit" msgid="3510496440489019191">"تعديل لقطة الشاشة"</string>
<string name="screenshot_dismiss_ui_description" msgid="934736855340147968">"إغلاق لقطة الشاشة"</string>
<string name="screenshot_preview_description" msgid="7606510140714080474">"معاينة لقطة الشاشة"</string>
<string name="screenrecord_name" msgid="2596401223859996572">"مسجّل الشاشة"</string>
@@ -1089,8 +1088,7 @@
<string name="controls_seeding_in_progress" msgid="3033855341410264148">"جارٍ تحميل الاقتراحات"</string>
<string name="controls_media_title" msgid="1746947284862928133">"الوسائط"</string>
<string name="controls_media_close_session" msgid="3957093425905475065">"إخفاء الجلسة الحالية"</string>
- <!-- no translation found for controls_media_active_session (1984383994625845642) -->
- <skip />
+ <string name="controls_media_active_session" msgid="1984383994625845642">"لا يمكن إخفاء الجلسة الحالية."</string>
<string name="controls_media_dismiss_button" msgid="9081375542265132213">"إغلاق"</string>
<string name="controls_media_resume" msgid="1933520684481586053">"استئناف التشغيل"</string>
<string name="controls_media_settings_button" msgid="5815790345117172504">"الإعدادات"</string>
diff --git a/packages/SystemUI/res/values-as/strings.xml b/packages/SystemUI/res/values-as/strings.xml
index 94cd1a7d7084..4c43e4ebed8f 100644
--- a/packages/SystemUI/res/values-as/strings.xml
+++ b/packages/SystemUI/res/values-as/strings.xml
@@ -86,8 +86,7 @@
<string name="screenshot_failed_to_save_unknown_text" msgid="1506621600548684129">"স্ক্ৰীণশ্বট আকৌ ল\'বলৈ চেষ্টা কৰক"</string>
<string name="screenshot_failed_to_save_text" msgid="8344173457344027501">"সঞ্চয়াগাৰত সীমিত খালী ঠাই থকাৰ বাবে স্ক্ৰীণশ্বট ছেভ কৰিব পৰা নগ\'ল"</string>
<string name="screenshot_failed_to_capture_text" msgid="7818288545874407451">"এপটোৱে বা আপোনাৰ প্ৰতিষ্ঠানে স্ক্ৰীণশ্বট ল\'বলৈ অনুমতি নিদিয়ে"</string>
- <!-- no translation found for screenshot_edit (3510496440489019191) -->
- <skip />
+ <string name="screenshot_edit" msgid="3510496440489019191">"স্ক্ৰীনশ্বট সম্পাদনা কৰক"</string>
<string name="screenshot_dismiss_ui_description" msgid="934736855340147968">"স্ক্ৰীনশ্বট অগ্ৰাহ্য কৰক"</string>
<string name="screenshot_preview_description" msgid="7606510140714080474">"স্ক্ৰীনশ্বটৰ পূৰ্বদৰ্শন"</string>
<string name="screenrecord_name" msgid="2596401223859996572">"স্ক্ৰীন ৰেকৰ্ডাৰ"</string>
@@ -1065,8 +1064,7 @@
<string name="controls_seeding_in_progress" msgid="3033855341410264148">"চুপাৰিছসমূহ ল’ড কৰি থকা হৈছে"</string>
<string name="controls_media_title" msgid="1746947284862928133">"মিডিয়া"</string>
<string name="controls_media_close_session" msgid="3957093425905475065">"বৰ্তমানৰ ছেশ্বনটো লুকুৱাওক।"</string>
- <!-- no translation found for controls_media_active_session (1984383994625845642) -->
- <skip />
+ <string name="controls_media_active_session" msgid="1984383994625845642">"বৰ্তমান ছেশ্বনটো লুকুৱাব নোৱাৰি।"</string>
<string name="controls_media_dismiss_button" msgid="9081375542265132213">"অগ্ৰাহ্য কৰক"</string>
<string name="controls_media_resume" msgid="1933520684481586053">"পুনৰ আৰম্ভ কৰক"</string>
<string name="controls_media_settings_button" msgid="5815790345117172504">"ছেটিংসমূহ"</string>
diff --git a/packages/SystemUI/res/values-az/strings.xml b/packages/SystemUI/res/values-az/strings.xml
index 43aca9a26e11..4cefd8426ed4 100644
--- a/packages/SystemUI/res/values-az/strings.xml
+++ b/packages/SystemUI/res/values-az/strings.xml
@@ -86,8 +86,7 @@
<string name="screenshot_failed_to_save_unknown_text" msgid="1506621600548684129">"Skrinşotu yenidən çəkin"</string>
<string name="screenshot_failed_to_save_text" msgid="8344173457344027501">"Yaddaş ehtiyatının az olması səbəbindən skrinşotu yadda saxlamaq olmur"</string>
<string name="screenshot_failed_to_capture_text" msgid="7818288545874407451">"Skrinşot çəkməyə tətbiq və ya təşkilat tərəfindən icazə verilmir"</string>
- <!-- no translation found for screenshot_edit (3510496440489019191) -->
- <skip />
+ <string name="screenshot_edit" msgid="3510496440489019191">"Skrinşota düzəliş edin"</string>
<string name="screenshot_dismiss_ui_description" msgid="934736855340147968">"Ekran şəklini ötürün"</string>
<string name="screenshot_preview_description" msgid="7606510140714080474">"Ekran şəklinə önbaxış"</string>
<string name="screenrecord_name" msgid="2596401223859996572">"Ekran Yazıcısı"</string>
@@ -1065,8 +1064,7 @@
<string name="controls_seeding_in_progress" msgid="3033855341410264148">"Tövsiyələr yüklənir"</string>
<string name="controls_media_title" msgid="1746947284862928133">"Media"</string>
<string name="controls_media_close_session" msgid="3957093425905475065">"Cari sessiyanı gizlədin."</string>
- <!-- no translation found for controls_media_active_session (1984383994625845642) -->
- <skip />
+ <string name="controls_media_active_session" msgid="1984383994625845642">"Cari sessiyanı gizlətmək olmur."</string>
<string name="controls_media_dismiss_button" msgid="9081375542265132213">"İmtina edin"</string>
<string name="controls_media_resume" msgid="1933520684481586053">"Davam edin"</string>
<string name="controls_media_settings_button" msgid="5815790345117172504">"Ayarlar"</string>
diff --git a/packages/SystemUI/res/values-b+sr+Latn/strings.xml b/packages/SystemUI/res/values-b+sr+Latn/strings.xml
index 3777dfe66ac6..2bc6c90cefd3 100644
--- a/packages/SystemUI/res/values-b+sr+Latn/strings.xml
+++ b/packages/SystemUI/res/values-b+sr+Latn/strings.xml
@@ -86,8 +86,7 @@
<string name="screenshot_failed_to_save_unknown_text" msgid="1506621600548684129">"Probajte da ponovo napravite snimak ekrana"</string>
<string name="screenshot_failed_to_save_text" msgid="8344173457344027501">"Čuvanje snimka ekrana nije uspelo zbog ograničenog memorijskog prostora"</string>
<string name="screenshot_failed_to_capture_text" msgid="7818288545874407451">"Aplikacija ili organizacija ne dozvoljavaju pravljenje snimaka ekrana"</string>
- <!-- no translation found for screenshot_edit (3510496440489019191) -->
- <skip />
+ <string name="screenshot_edit" msgid="3510496440489019191">"Izmenite snimak ekrana"</string>
<string name="screenshot_dismiss_ui_description" msgid="934736855340147968">"Odbacite snimak ekrana"</string>
<string name="screenshot_preview_description" msgid="7606510140714080474">"Pregled snimka ekrana"</string>
<string name="screenrecord_name" msgid="2596401223859996572">"Snimač ekrana"</string>
@@ -1071,8 +1070,7 @@
<string name="controls_seeding_in_progress" msgid="3033855341410264148">"Učitavaju se preporuke"</string>
<string name="controls_media_title" msgid="1746947284862928133">"Mediji"</string>
<string name="controls_media_close_session" msgid="3957093425905475065">"Sakrijte aktuelnu sesiju."</string>
- <!-- no translation found for controls_media_active_session (1984383994625845642) -->
- <skip />
+ <string name="controls_media_active_session" msgid="1984383994625845642">"Aktuelna sesija ne može da se sakrije."</string>
<string name="controls_media_dismiss_button" msgid="9081375542265132213">"Odbaci"</string>
<string name="controls_media_resume" msgid="1933520684481586053">"Nastavi"</string>
<string name="controls_media_settings_button" msgid="5815790345117172504">"Podešavanja"</string>
diff --git a/packages/SystemUI/res/values-be/strings.xml b/packages/SystemUI/res/values-be/strings.xml
index 8a5d42aeb122..6396cbeb1299 100644
--- a/packages/SystemUI/res/values-be/strings.xml
+++ b/packages/SystemUI/res/values-be/strings.xml
@@ -86,8 +86,7 @@
<string name="screenshot_failed_to_save_unknown_text" msgid="1506621600548684129">"Паспрабуйце зрабіць здымак экрана яшчэ раз"</string>
<string name="screenshot_failed_to_save_text" msgid="8344173457344027501">"Немагчыма захаваць здымак экрана, бо мала месца ў сховішчы"</string>
<string name="screenshot_failed_to_capture_text" msgid="7818288545874407451">"Рабіць здымкі экрана не дазваляе праграма ці ваша арганізацыя"</string>
- <!-- no translation found for screenshot_edit (3510496440489019191) -->
- <skip />
+ <string name="screenshot_edit" msgid="3510496440489019191">"Змяніць здымак экрана"</string>
<string name="screenshot_dismiss_ui_description" msgid="934736855340147968">"Адхіліць здымак экрана"</string>
<string name="screenshot_preview_description" msgid="7606510140714080474">"Перадпрагляд здымка экрана"</string>
<string name="screenrecord_name" msgid="2596401223859996572">"Запіс экрана"</string>
@@ -1077,8 +1076,7 @@
<string name="controls_seeding_in_progress" msgid="3033855341410264148">"Загружаюцца рэкамендацыі"</string>
<string name="controls_media_title" msgid="1746947284862928133">"Мультымедыя"</string>
<string name="controls_media_close_session" msgid="3957093425905475065">"Схаваць цяперашні сеанс."</string>
- <!-- no translation found for controls_media_active_session (1984383994625845642) -->
- <skip />
+ <string name="controls_media_active_session" msgid="1984383994625845642">"Гэты сеанс не можа быць схаваны."</string>
<string name="controls_media_dismiss_button" msgid="9081375542265132213">"Адхіліць"</string>
<string name="controls_media_resume" msgid="1933520684481586053">"Узнавіць"</string>
<string name="controls_media_settings_button" msgid="5815790345117172504">"Налады"</string>
diff --git a/packages/SystemUI/res/values-bn/strings.xml b/packages/SystemUI/res/values-bn/strings.xml
index 6cdc128bdb32..c4c6a0c3e2d9 100644
--- a/packages/SystemUI/res/values-bn/strings.xml
+++ b/packages/SystemUI/res/values-bn/strings.xml
@@ -86,8 +86,7 @@
<string name="screenshot_failed_to_save_unknown_text" msgid="1506621600548684129">"আবার স্ক্রিনশট নেওয়ার চেষ্টা করুন"</string>
<string name="screenshot_failed_to_save_text" msgid="8344173457344027501">"বেশি জায়গা নেই তাই স্ক্রিনশটটি সেভ করা যাবে না৷"</string>
<string name="screenshot_failed_to_capture_text" msgid="7818288545874407451">"এই অ্যাপ বা আপনার প্রতিষ্ঠান স্ক্রিনশট নেওয়ার অনুমতি দেয়নি"</string>
- <!-- no translation found for screenshot_edit (3510496440489019191) -->
- <skip />
+ <string name="screenshot_edit" msgid="3510496440489019191">"স্ক্রিনশট এডিট করুন"</string>
<string name="screenshot_dismiss_ui_description" msgid="934736855340147968">"স্ক্রিনশট বাতিল করুন"</string>
<string name="screenshot_preview_description" msgid="7606510140714080474">"স্ক্রিনশটের প্রিভিউ"</string>
<string name="screenrecord_name" msgid="2596401223859996572">"স্ক্রিন রেকর্ডার"</string>
@@ -1065,8 +1064,7 @@
<string name="controls_seeding_in_progress" msgid="3033855341410264148">"সাজেশন লোড করা হচ্ছে"</string>
<string name="controls_media_title" msgid="1746947284862928133">"মিডিয়া"</string>
<string name="controls_media_close_session" msgid="3957093425905475065">"বর্তমান সেশন লুকান।"</string>
- <!-- no translation found for controls_media_active_session (1984383994625845642) -->
- <skip />
+ <string name="controls_media_active_session" msgid="1984383994625845642">"বর্তমান সেশন লুকানো যাবে না।"</string>
<string name="controls_media_dismiss_button" msgid="9081375542265132213">"খারিজ করুন"</string>
<string name="controls_media_resume" msgid="1933520684481586053">"আবার চালু করুন"</string>
<string name="controls_media_settings_button" msgid="5815790345117172504">"সেটিংস"</string>
diff --git a/packages/SystemUI/res/values-bs/strings.xml b/packages/SystemUI/res/values-bs/strings.xml
index 8f622c8510ea..4ce5496f2186 100644
--- a/packages/SystemUI/res/values-bs/strings.xml
+++ b/packages/SystemUI/res/values-bs/strings.xml
@@ -86,8 +86,7 @@
<string name="screenshot_failed_to_save_unknown_text" msgid="1506621600548684129">"Pokušajte ponovo snimiti ekran"</string>
<string name="screenshot_failed_to_save_text" msgid="8344173457344027501">"Snimak ekrana se ne može sačuvati zbog manjka prostora za pohranu"</string>
<string name="screenshot_failed_to_capture_text" msgid="7818288545874407451">"Ova aplikacija ili vaša organizacija ne dozvoljavaju snimanje ekrana"</string>
- <!-- no translation found for screenshot_edit (3510496440489019191) -->
- <skip />
+ <string name="screenshot_edit" msgid="3510496440489019191">"Uredite snimak ekrana"</string>
<string name="screenshot_dismiss_ui_description" msgid="934736855340147968">"Odbacite snimak ekrana"</string>
<string name="screenshot_preview_description" msgid="7606510140714080474">"Pregled snimka ekrana"</string>
<string name="screenrecord_name" msgid="2596401223859996572">"Snimač ekrana"</string>
@@ -1071,8 +1070,7 @@
<string name="controls_seeding_in_progress" msgid="3033855341410264148">"Učitavanje preporuka"</string>
<string name="controls_media_title" msgid="1746947284862928133">"Mediji"</string>
<string name="controls_media_close_session" msgid="3957093425905475065">"Sakrijte trenutnu sesiju."</string>
- <!-- no translation found for controls_media_active_session (1984383994625845642) -->
- <skip />
+ <string name="controls_media_active_session" msgid="1984383994625845642">"Nije moguće sakriti trenutnu sesiju."</string>
<string name="controls_media_dismiss_button" msgid="9081375542265132213">"Odbaci"</string>
<string name="controls_media_resume" msgid="1933520684481586053">"Nastavi"</string>
<string name="controls_media_settings_button" msgid="5815790345117172504">"Postavke"</string>
diff --git a/packages/SystemUI/res/values-ca/strings.xml b/packages/SystemUI/res/values-ca/strings.xml
index ea7f36ae4b16..2b6dfd577616 100644
--- a/packages/SystemUI/res/values-ca/strings.xml
+++ b/packages/SystemUI/res/values-ca/strings.xml
@@ -86,8 +86,7 @@
<string name="screenshot_failed_to_save_unknown_text" msgid="1506621600548684129">"Prova de tornar a fer una captura de pantalla"</string>
<string name="screenshot_failed_to_save_text" msgid="8344173457344027501">"La captura de pantalla no es pot desar perquè no hi ha prou espai d\'emmagatzematge"</string>
<string name="screenshot_failed_to_capture_text" msgid="7818288545874407451">"L\'aplicació o la teva organització no permeten fer captures de pantalla"</string>
- <!-- no translation found for screenshot_edit (3510496440489019191) -->
- <skip />
+ <string name="screenshot_edit" msgid="3510496440489019191">"Edita la captura de pantalla"</string>
<string name="screenshot_dismiss_ui_description" msgid="934736855340147968">"Ignora la captura de pantalla"</string>
<string name="screenshot_preview_description" msgid="7606510140714080474">"Previsualització de la captura de pantalla"</string>
<string name="screenrecord_name" msgid="2596401223859996572">"Gravació de pantalla"</string>
@@ -1065,8 +1064,7 @@
<string name="controls_seeding_in_progress" msgid="3033855341410264148">"Carregant les recomanacions"</string>
<string name="controls_media_title" msgid="1746947284862928133">"Multimèdia"</string>
<string name="controls_media_close_session" msgid="3957093425905475065">"Amaga la sessió actual."</string>
- <!-- no translation found for controls_media_active_session (1984383994625845642) -->
- <skip />
+ <string name="controls_media_active_session" msgid="1984383994625845642">"La sessió actual no es pot amagar."</string>
<string name="controls_media_dismiss_button" msgid="9081375542265132213">"Ignora"</string>
<string name="controls_media_resume" msgid="1933520684481586053">"Reprèn"</string>
<string name="controls_media_settings_button" msgid="5815790345117172504">"Configuració"</string>
diff --git a/packages/SystemUI/res/values-cs/strings.xml b/packages/SystemUI/res/values-cs/strings.xml
index d3e3dbf0e749..f00c279b6b58 100644
--- a/packages/SystemUI/res/values-cs/strings.xml
+++ b/packages/SystemUI/res/values-cs/strings.xml
@@ -86,8 +86,7 @@
<string name="screenshot_failed_to_save_unknown_text" msgid="1506621600548684129">"Zkuste snímek pořídit znovu"</string>
<string name="screenshot_failed_to_save_text" msgid="8344173457344027501">"Snímek obrazovky kvůli nedostatku místa v úložišti nelze uložit"</string>
<string name="screenshot_failed_to_capture_text" msgid="7818288545874407451">"Aplikace nebo organizace zakazuje pořizování snímků obrazovky"</string>
- <!-- no translation found for screenshot_edit (3510496440489019191) -->
- <skip />
+ <string name="screenshot_edit" msgid="3510496440489019191">"Upravit snímek obrazovky"</string>
<string name="screenshot_dismiss_ui_description" msgid="934736855340147968">"Zavřít snímek obrazovky"</string>
<string name="screenshot_preview_description" msgid="7606510140714080474">"Náhled snímku obrazovky"</string>
<string name="screenrecord_name" msgid="2596401223859996572">"Rekordér obrazovky"</string>
@@ -1077,8 +1076,7 @@
<string name="controls_seeding_in_progress" msgid="3033855341410264148">"Načítání doporučení"</string>
<string name="controls_media_title" msgid="1746947284862928133">"Média"</string>
<string name="controls_media_close_session" msgid="3957093425905475065">"Skrýt aktuální relaci."</string>
- <!-- no translation found for controls_media_active_session (1984383994625845642) -->
- <skip />
+ <string name="controls_media_active_session" msgid="1984383994625845642">"Aktuální relaci nelze skrýt."</string>
<string name="controls_media_dismiss_button" msgid="9081375542265132213">"Zavřít"</string>
<string name="controls_media_resume" msgid="1933520684481586053">"Pokračovat"</string>
<string name="controls_media_settings_button" msgid="5815790345117172504">"Nastavení"</string>
diff --git a/packages/SystemUI/res/values-da/strings.xml b/packages/SystemUI/res/values-da/strings.xml
index 82e8fd1295db..9d365c33fa39 100644
--- a/packages/SystemUI/res/values-da/strings.xml
+++ b/packages/SystemUI/res/values-da/strings.xml
@@ -86,8 +86,7 @@
<string name="screenshot_failed_to_save_unknown_text" msgid="1506621600548684129">"Prøv at tage et screenshot igen"</string>
<string name="screenshot_failed_to_save_text" msgid="8344173457344027501">"Screenshottet kan ikke gemmes, fordi der er begrænset lagerplads"</string>
<string name="screenshot_failed_to_capture_text" msgid="7818288545874407451">"Appen eller din organisation tillader ikke, at du tager screenshots"</string>
- <!-- no translation found for screenshot_edit (3510496440489019191) -->
- <skip />
+ <string name="screenshot_edit" msgid="3510496440489019191">"Rediger dit screenshot"</string>
<string name="screenshot_dismiss_ui_description" msgid="934736855340147968">"Luk screenshot"</string>
<string name="screenshot_preview_description" msgid="7606510140714080474">"Forhåndsvisning af screenshot"</string>
<string name="screenrecord_name" msgid="2596401223859996572">"Skærmoptagelse"</string>
@@ -1065,8 +1064,7 @@
<string name="controls_seeding_in_progress" msgid="3033855341410264148">"Indlæser anbefalinger"</string>
<string name="controls_media_title" msgid="1746947284862928133">"Medie"</string>
<string name="controls_media_close_session" msgid="3957093425905475065">"Skjul den aktuelle session."</string>
- <!-- no translation found for controls_media_active_session (1984383994625845642) -->
- <skip />
+ <string name="controls_media_active_session" msgid="1984383994625845642">"Den nuværende session kan ikke skjules."</string>
<string name="controls_media_dismiss_button" msgid="9081375542265132213">"Luk"</string>
<string name="controls_media_resume" msgid="1933520684481586053">"Genoptag"</string>
<string name="controls_media_settings_button" msgid="5815790345117172504">"Indstillinger"</string>
diff --git a/packages/SystemUI/res/values-de/strings.xml b/packages/SystemUI/res/values-de/strings.xml
index 0e3f309ce5d4..55e7d17c84d2 100644
--- a/packages/SystemUI/res/values-de/strings.xml
+++ b/packages/SystemUI/res/values-de/strings.xml
@@ -86,8 +86,7 @@
<string name="screenshot_failed_to_save_unknown_text" msgid="1506621600548684129">"Versuche noch einmal, den Screenshot zu erstellen"</string>
<string name="screenshot_failed_to_save_text" msgid="8344173457344027501">"Speichern des Screenshots aufgrund von zu wenig Speicher nicht möglich"</string>
<string name="screenshot_failed_to_capture_text" msgid="7818288545874407451">"Die App oder deine Organisation lässt das Erstellen von Screenshots nicht zu"</string>
- <!-- no translation found for screenshot_edit (3510496440489019191) -->
- <skip />
+ <string name="screenshot_edit" msgid="3510496440489019191">"Screenshot bearbeiten"</string>
<string name="screenshot_dismiss_ui_description" msgid="934736855340147968">"Screenshot schließen"</string>
<string name="screenshot_preview_description" msgid="7606510140714080474">"Screenshotvorschau"</string>
<string name="screenrecord_name" msgid="2596401223859996572">"Bildschirmaufzeichnung"</string>
@@ -1065,8 +1064,7 @@
<string name="controls_seeding_in_progress" msgid="3033855341410264148">"Empfehlungen werden geladen"</string>
<string name="controls_media_title" msgid="1746947284862928133">"Medien"</string>
<string name="controls_media_close_session" msgid="3957093425905475065">"Du kannst die aktuelle Sitzung ausblenden."</string>
- <!-- no translation found for controls_media_active_session (1984383994625845642) -->
- <skip />
+ <string name="controls_media_active_session" msgid="1984383994625845642">"Aktuelle Sitzung kann nicht verborgen werden."</string>
<string name="controls_media_dismiss_button" msgid="9081375542265132213">"Ablehnen"</string>
<string name="controls_media_resume" msgid="1933520684481586053">"Fortsetzen"</string>
<string name="controls_media_settings_button" msgid="5815790345117172504">"Einstellungen"</string>
diff --git a/packages/SystemUI/res/values-el/strings.xml b/packages/SystemUI/res/values-el/strings.xml
index 645ff081dd72..3bb15ffff775 100644
--- a/packages/SystemUI/res/values-el/strings.xml
+++ b/packages/SystemUI/res/values-el/strings.xml
@@ -86,8 +86,7 @@
<string name="screenshot_failed_to_save_unknown_text" msgid="1506621600548684129">"Δοκιμάστε να κάνετε ξανά λήψη του στιγμιότυπου οθόνης"</string>
<string name="screenshot_failed_to_save_text" msgid="8344173457344027501">"Αδύνατη η αποθήκευση του στιγμιότυπου οθόνης λόγω περιορισμένου αποθηκευτικού χώρου"</string>
<string name="screenshot_failed_to_capture_text" msgid="7818288545874407451">"Η λήψη στιγμιότυπων οθόνης δεν επιτρέπεται από την εφαρμογή ή τον οργανισμό σας"</string>
- <!-- no translation found for screenshot_edit (3510496440489019191) -->
- <skip />
+ <string name="screenshot_edit" msgid="3510496440489019191">"Επεξεργασία στιγμιότυπου οθόνης"</string>
<string name="screenshot_dismiss_ui_description" msgid="934736855340147968">"Παράβλεψη στιγμιότυπου οθόνης"</string>
<string name="screenshot_preview_description" msgid="7606510140714080474">"Προεπισκόπηση στιγμιότυπου οθόνης"</string>
<string name="screenrecord_name" msgid="2596401223859996572">"Εγγραφή οθόνης"</string>
@@ -1065,8 +1064,7 @@
<string name="controls_seeding_in_progress" msgid="3033855341410264148">"Φόρτωση προτάσεων"</string>
<string name="controls_media_title" msgid="1746947284862928133">"Μέσα"</string>
<string name="controls_media_close_session" msgid="3957093425905475065">"Απόκρυψη της τρέχουσας περιόδου λειτουργίας."</string>
- <!-- no translation found for controls_media_active_session (1984383994625845642) -->
- <skip />
+ <string name="controls_media_active_session" msgid="1984383994625845642">"Δεν είναι δυνατή η απόκρυψη της τρέχουσας περιόδου λειτουργίας."</string>
<string name="controls_media_dismiss_button" msgid="9081375542265132213">"Παράβλεψη"</string>
<string name="controls_media_resume" msgid="1933520684481586053">"Συνέχιση"</string>
<string name="controls_media_settings_button" msgid="5815790345117172504">"Ρυθμίσεις"</string>
diff --git a/packages/SystemUI/res/values-es-rUS/strings.xml b/packages/SystemUI/res/values-es-rUS/strings.xml
index 2b5e96f03f96..d30a39529051 100644
--- a/packages/SystemUI/res/values-es-rUS/strings.xml
+++ b/packages/SystemUI/res/values-es-rUS/strings.xml
@@ -86,8 +86,7 @@
<string name="screenshot_failed_to_save_unknown_text" msgid="1506621600548684129">"Vuelve a hacer una captura de pantalla"</string>
<string name="screenshot_failed_to_save_text" msgid="8344173457344027501">"No se puede guardar la captura de pantalla debido a que no hay suficiente espacio de almacenamiento"</string>
<string name="screenshot_failed_to_capture_text" msgid="7818288545874407451">"La app o tu organización no permiten las capturas de pantalla"</string>
- <!-- no translation found for screenshot_edit (3510496440489019191) -->
- <skip />
+ <string name="screenshot_edit" msgid="3510496440489019191">"Editar captura de pantalla"</string>
<string name="screenshot_dismiss_ui_description" msgid="934736855340147968">"Descartar captura de pantalla"</string>
<string name="screenshot_preview_description" msgid="7606510140714080474">"Vista previa de la captura de pantalla"</string>
<string name="screenrecord_name" msgid="2596401223859996572">"Grabadora de pantalla"</string>
@@ -1065,8 +1064,7 @@
<string name="controls_seeding_in_progress" msgid="3033855341410264148">"Cargando recomendaciones"</string>
<string name="controls_media_title" msgid="1746947284862928133">"Contenido multimedia"</string>
<string name="controls_media_close_session" msgid="3957093425905475065">"Oculta la sesión actual."</string>
- <!-- no translation found for controls_media_active_session (1984383994625845642) -->
- <skip />
+ <string name="controls_media_active_session" msgid="1984383994625845642">"No se puede ocultar la sesión actual."</string>
<string name="controls_media_dismiss_button" msgid="9081375542265132213">"Descartar"</string>
<string name="controls_media_resume" msgid="1933520684481586053">"Reanudar"</string>
<string name="controls_media_settings_button" msgid="5815790345117172504">"Configuración"</string>
diff --git a/packages/SystemUI/res/values-es/strings.xml b/packages/SystemUI/res/values-es/strings.xml
index b0377fd899e1..875c310eb133 100644
--- a/packages/SystemUI/res/values-es/strings.xml
+++ b/packages/SystemUI/res/values-es/strings.xml
@@ -86,8 +86,7 @@
<string name="screenshot_failed_to_save_unknown_text" msgid="1506621600548684129">"Vuelve a intentar hacer la captura de pantalla"</string>
<string name="screenshot_failed_to_save_text" msgid="8344173457344027501">"No se puede guardar la captura de pantalla porque no hay espacio de almacenamiento suficiente"</string>
<string name="screenshot_failed_to_capture_text" msgid="7818288545874407451">"La aplicación o tu organización no permiten realizar capturas de pantalla"</string>
- <!-- no translation found for screenshot_edit (3510496440489019191) -->
- <skip />
+ <string name="screenshot_edit" msgid="3510496440489019191">"Editar captura de pantalla"</string>
<string name="screenshot_dismiss_ui_description" msgid="934736855340147968">"Cerrar captura de pantalla"</string>
<string name="screenshot_preview_description" msgid="7606510140714080474">"Vista previa de captura de pantalla"</string>
<string name="screenrecord_name" msgid="2596401223859996572">"Grabación de pantalla"</string>
@@ -1065,8 +1064,7 @@
<string name="controls_seeding_in_progress" msgid="3033855341410264148">"Cargando recomendaciones"</string>
<string name="controls_media_title" msgid="1746947284862928133">"Multimedia"</string>
<string name="controls_media_close_session" msgid="3957093425905475065">"Ocultar la sesión."</string>
- <!-- no translation found for controls_media_active_session (1984383994625845642) -->
- <skip />
+ <string name="controls_media_active_session" msgid="1984383994625845642">"La sesión no se puede ocultar."</string>
<string name="controls_media_dismiss_button" msgid="9081375542265132213">"Cerrar"</string>
<string name="controls_media_resume" msgid="1933520684481586053">"Reanudar"</string>
<string name="controls_media_settings_button" msgid="5815790345117172504">"Ajustes"</string>
diff --git a/packages/SystemUI/res/values-et/strings.xml b/packages/SystemUI/res/values-et/strings.xml
index a22e12bfa11d..f9940a30fcaa 100644
--- a/packages/SystemUI/res/values-et/strings.xml
+++ b/packages/SystemUI/res/values-et/strings.xml
@@ -86,8 +86,7 @@
<string name="screenshot_failed_to_save_unknown_text" msgid="1506621600548684129">"Proovige ekraanipilt uuesti jäädvustada"</string>
<string name="screenshot_failed_to_save_text" msgid="8344173457344027501">"Piiratud salvestusruumi tõttu ei saa ekraanipilti salvestada"</string>
<string name="screenshot_failed_to_capture_text" msgid="7818288545874407451">"Rakendus või teie organisatsioon ei luba ekraanipilte jäädvustada"</string>
- <!-- no translation found for screenshot_edit (3510496440489019191) -->
- <skip />
+ <string name="screenshot_edit" msgid="3510496440489019191">"Ekraanipildi muutmine"</string>
<string name="screenshot_dismiss_ui_description" msgid="934736855340147968">"Sule ekraanipilt"</string>
<string name="screenshot_preview_description" msgid="7606510140714080474">"Ekraanipildi eelvaade"</string>
<string name="screenrecord_name" msgid="2596401223859996572">"Ekraanisalvesti"</string>
@@ -1065,8 +1064,7 @@
<string name="controls_seeding_in_progress" msgid="3033855341410264148">"Soovituste laadimine"</string>
<string name="controls_media_title" msgid="1746947284862928133">"Meedia"</string>
<string name="controls_media_close_session" msgid="3957093425905475065">"Peidetakse praegune seanss."</string>
- <!-- no translation found for controls_media_active_session (1984383994625845642) -->
- <skip />
+ <string name="controls_media_active_session" msgid="1984383994625845642">"Praegust seanssi ei saa peita."</string>
<string name="controls_media_dismiss_button" msgid="9081375542265132213">"Loobu"</string>
<string name="controls_media_resume" msgid="1933520684481586053">"Jätka"</string>
<string name="controls_media_settings_button" msgid="5815790345117172504">"Seaded"</string>
diff --git a/packages/SystemUI/res/values-eu/strings.xml b/packages/SystemUI/res/values-eu/strings.xml
index f6ca69796d76..cb86a16122c0 100644
--- a/packages/SystemUI/res/values-eu/strings.xml
+++ b/packages/SystemUI/res/values-eu/strings.xml
@@ -86,8 +86,7 @@
<string name="screenshot_failed_to_save_unknown_text" msgid="1506621600548684129">"Saiatu berriro pantaila-argazkia ateratzen"</string>
<string name="screenshot_failed_to_save_text" msgid="8344173457344027501">"Ezin da gorde pantaila-argazkia ez delako gelditzen tokirik"</string>
<string name="screenshot_failed_to_capture_text" msgid="7818288545874407451">"Aplikazioak edo erakundeak ez du onartzen pantaila-argazkiak ateratzea"</string>
- <!-- no translation found for screenshot_edit (3510496440489019191) -->
- <skip />
+ <string name="screenshot_edit" msgid="3510496440489019191">"Editatu pantaila-argazkia"</string>
<string name="screenshot_dismiss_ui_description" msgid="934736855340147968">"Baztertu pantaila-argazkia"</string>
<string name="screenshot_preview_description" msgid="7606510140714080474">"Pantaila-argazkiaren aurrebista"</string>
<string name="screenrecord_name" msgid="2596401223859996572">"Pantaila-grabagailua"</string>
@@ -1065,8 +1064,7 @@
<string name="controls_seeding_in_progress" msgid="3033855341410264148">"Gomendioak kargatzen"</string>
<string name="controls_media_title" msgid="1746947284862928133">"Multimedia-edukia"</string>
<string name="controls_media_close_session" msgid="3957093425905475065">"Ezkutatu uneko saioa."</string>
- <!-- no translation found for controls_media_active_session (1984383994625845642) -->
- <skip />
+ <string name="controls_media_active_session" msgid="1984383994625845642">"Ezin da ezkutatu uneko saioa."</string>
<string name="controls_media_dismiss_button" msgid="9081375542265132213">"Baztertu"</string>
<string name="controls_media_resume" msgid="1933520684481586053">"Berrekin"</string>
<string name="controls_media_settings_button" msgid="5815790345117172504">"Ezarpenak"</string>
diff --git a/packages/SystemUI/res/values-fa/strings.xml b/packages/SystemUI/res/values-fa/strings.xml
index 4c913f68ff4d..fe38ea09888a 100644
--- a/packages/SystemUI/res/values-fa/strings.xml
+++ b/packages/SystemUI/res/values-fa/strings.xml
@@ -86,8 +86,7 @@
<string name="screenshot_failed_to_save_unknown_text" msgid="1506621600548684129">"دوباره نماگرفت بگیرید"</string>
<string name="screenshot_failed_to_save_text" msgid="8344173457344027501">"به دلیل محدود بودن فضای ذخیره‌سازی نمی‌توان نماگرفت را ذخیره کرد"</string>
<string name="screenshot_failed_to_capture_text" msgid="7818288545874407451">"برنامه یا سازمان شما اجازه نمی‌دهند نماگرفت بگیرید."</string>
- <!-- no translation found for screenshot_edit (3510496440489019191) -->
- <skip />
+ <string name="screenshot_edit" msgid="3510496440489019191">"ویرایش نماگرفت"</string>
<string name="screenshot_dismiss_ui_description" msgid="934736855340147968">"رد کردن نماگرفت"</string>
<string name="screenshot_preview_description" msgid="7606510140714080474">"پیش‌نمایش نماگرفت"</string>
<string name="screenrecord_name" msgid="2596401223859996572">"ضبط‌کننده صفحه‌نمایش"</string>
@@ -1065,8 +1064,7 @@
<string name="controls_seeding_in_progress" msgid="3033855341410264148">"درحال بار کردن توصیه‌ها"</string>
<string name="controls_media_title" msgid="1746947284862928133">"رسانه"</string>
<string name="controls_media_close_session" msgid="3957093425905475065">"جلسه فعلی پنهان شود."</string>
- <!-- no translation found for controls_media_active_session (1984383994625845642) -->
- <skip />
+ <string name="controls_media_active_session" msgid="1984383994625845642">"نمی‌توان جلسه فعلی را پنهان کرد."</string>
<string name="controls_media_dismiss_button" msgid="9081375542265132213">"رد کردن"</string>
<string name="controls_media_resume" msgid="1933520684481586053">"ازسرگیری"</string>
<string name="controls_media_settings_button" msgid="5815790345117172504">"تنظیمات"</string>
diff --git a/packages/SystemUI/res/values-fi/strings.xml b/packages/SystemUI/res/values-fi/strings.xml
index 0ab407adf99b..11c7e19be208 100644
--- a/packages/SystemUI/res/values-fi/strings.xml
+++ b/packages/SystemUI/res/values-fi/strings.xml
@@ -86,8 +86,7 @@
<string name="screenshot_failed_to_save_unknown_text" msgid="1506621600548684129">"Yritä ottaa kuvakaappaus uudelleen."</string>
<string name="screenshot_failed_to_save_text" msgid="8344173457344027501">"Kuvakaappauksen tallennus epäonnistui, sillä tallennustilaa ei ole riittävästi"</string>
<string name="screenshot_failed_to_capture_text" msgid="7818288545874407451">"Sovellus tai organisaatio ei salli kuvakaappauksien tallentamista."</string>
- <!-- no translation found for screenshot_edit (3510496440489019191) -->
- <skip />
+ <string name="screenshot_edit" msgid="3510496440489019191">"Muokkaa kuvakaappausta"</string>
<string name="screenshot_dismiss_ui_description" msgid="934736855340147968">"Hylkää kuvakaappaus"</string>
<string name="screenshot_preview_description" msgid="7606510140714080474">"Kuvakaappauksen esikatselu"</string>
<string name="screenrecord_name" msgid="2596401223859996572">"Näytön tallentaja"</string>
@@ -1065,8 +1064,7 @@
<string name="controls_seeding_in_progress" msgid="3033855341410264148">"Ladataan suosituksia"</string>
<string name="controls_media_title" msgid="1746947284862928133">"Media"</string>
<string name="controls_media_close_session" msgid="3957093425905475065">"Piilota nykyinen käyttökerta."</string>
- <!-- no translation found for controls_media_active_session (1984383994625845642) -->
- <skip />
+ <string name="controls_media_active_session" msgid="1984383994625845642">"Nykyistä käyttökertaa ei voi piilottaa."</string>
<string name="controls_media_dismiss_button" msgid="9081375542265132213">"Ohita"</string>
<string name="controls_media_resume" msgid="1933520684481586053">"Jatka"</string>
<string name="controls_media_settings_button" msgid="5815790345117172504">"Asetukset"</string>
diff --git a/packages/SystemUI/res/values-fr-rCA/strings.xml b/packages/SystemUI/res/values-fr-rCA/strings.xml
index 1b7a308f31ca..b8ea6ac31c77 100644
--- a/packages/SystemUI/res/values-fr-rCA/strings.xml
+++ b/packages/SystemUI/res/values-fr-rCA/strings.xml
@@ -86,8 +86,7 @@
<string name="screenshot_failed_to_save_unknown_text" msgid="1506621600548684129">"Essayez de faire une autre capture d\'écran"</string>
<string name="screenshot_failed_to_save_text" msgid="8344173457344027501">"Impossible d\'enregistrer la capture d\'écran, car l\'espace de stockage est limité"</string>
<string name="screenshot_failed_to_capture_text" msgid="7818288545874407451">"L\'application ou votre organisation n\'autorise pas les saisies d\'écran"</string>
- <!-- no translation found for screenshot_edit (3510496440489019191) -->
- <skip />
+ <string name="screenshot_edit" msgid="3510496440489019191">"Modifier la capture d\'écran"</string>
<string name="screenshot_dismiss_ui_description" msgid="934736855340147968">"Fermer la capture d\'écran"</string>
<string name="screenshot_preview_description" msgid="7606510140714080474">"Aperçu de la capture d\'écran"</string>
<string name="screenrecord_name" msgid="2596401223859996572">"Enregistreur d\'écran"</string>
@@ -1065,8 +1064,7 @@
<string name="controls_seeding_in_progress" msgid="3033855341410264148">"Chargement des recommandations…"</string>
<string name="controls_media_title" msgid="1746947284862928133">"Commandes multimédias"</string>
<string name="controls_media_close_session" msgid="3957093425905475065">"Masquer la session en cours."</string>
- <!-- no translation found for controls_media_active_session (1984383994625845642) -->
- <skip />
+ <string name="controls_media_active_session" msgid="1984383994625845642">"La session actuelle ne peut pas être masquée."</string>
<string name="controls_media_dismiss_button" msgid="9081375542265132213">"Fermer"</string>
<string name="controls_media_resume" msgid="1933520684481586053">"Reprendre"</string>
<string name="controls_media_settings_button" msgid="5815790345117172504">"Paramètres"</string>
diff --git a/packages/SystemUI/res/values-fr/strings.xml b/packages/SystemUI/res/values-fr/strings.xml
index 74a68618fb5d..289ce40d2ce7 100644
--- a/packages/SystemUI/res/values-fr/strings.xml
+++ b/packages/SystemUI/res/values-fr/strings.xml
@@ -86,8 +86,7 @@
<string name="screenshot_failed_to_save_unknown_text" msgid="1506621600548684129">"Essayez de nouveau de faire une capture d\'écran"</string>
<string name="screenshot_failed_to_save_text" msgid="8344173457344027501">"Impossible d\'enregistrer la capture d\'écran, car l\'espace de stockage est limité"</string>
<string name="screenshot_failed_to_capture_text" msgid="7818288545874407451">"Les captures d\'écran ne sont pas autorisées par l\'application ni par votre organisation"</string>
- <!-- no translation found for screenshot_edit (3510496440489019191) -->
- <skip />
+ <string name="screenshot_edit" msgid="3510496440489019191">"Modifier la capture d\'écran"</string>
<string name="screenshot_dismiss_ui_description" msgid="934736855340147968">"Fermer la capture d\'écran"</string>
<string name="screenshot_preview_description" msgid="7606510140714080474">"Aperçu de la capture d\'écran"</string>
<string name="screenrecord_name" msgid="2596401223859996572">"Enregistreur d\'écran"</string>
@@ -1065,8 +1064,7 @@
<string name="controls_seeding_in_progress" msgid="3033855341410264148">"Chargement des recommandations"</string>
<string name="controls_media_title" msgid="1746947284862928133">"Multimédia"</string>
<string name="controls_media_close_session" msgid="3957093425905475065">"Masquer la session en cours."</string>
- <!-- no translation found for controls_media_active_session (1984383994625845642) -->
- <skip />
+ <string name="controls_media_active_session" msgid="1984383994625845642">"Impossible de masquer la session actuelle."</string>
<string name="controls_media_dismiss_button" msgid="9081375542265132213">"Fermer"</string>
<string name="controls_media_resume" msgid="1933520684481586053">"Reprendre"</string>
<string name="controls_media_settings_button" msgid="5815790345117172504">"Paramètres"</string>
diff --git a/packages/SystemUI/res/values-gl/strings.xml b/packages/SystemUI/res/values-gl/strings.xml
index 26cf07a0dca0..e3d3755d4f68 100644
--- a/packages/SystemUI/res/values-gl/strings.xml
+++ b/packages/SystemUI/res/values-gl/strings.xml
@@ -86,8 +86,7 @@
<string name="screenshot_failed_to_save_unknown_text" msgid="1506621600548684129">"Volve tentar crear unha captura de pantalla"</string>
<string name="screenshot_failed_to_save_text" msgid="8344173457344027501">"Non se puido gardar a captura de pantalla porque o espazo de almacenamento é limitado"</string>
<string name="screenshot_failed_to_capture_text" msgid="7818288545874407451">"A aplicación ou a túa organización non permite realizar capturas de pantalla"</string>
- <!-- no translation found for screenshot_edit (3510496440489019191) -->
- <skip />
+ <string name="screenshot_edit" msgid="3510496440489019191">"Edita a captura de pantalla"</string>
<string name="screenshot_dismiss_ui_description" msgid="934736855340147968">"Ignora a captura de pantalla"</string>
<string name="screenshot_preview_description" msgid="7606510140714080474">"Vista previa da captura de pantalla"</string>
<string name="screenrecord_name" msgid="2596401223859996572">"Gravadora da pantalla"</string>
@@ -1065,8 +1064,7 @@
<string name="controls_seeding_in_progress" msgid="3033855341410264148">"Cargando recomendacións"</string>
<string name="controls_media_title" msgid="1746947284862928133">"Contido multimedia"</string>
<string name="controls_media_close_session" msgid="3957093425905475065">"Oculta a sesión actual."</string>
- <!-- no translation found for controls_media_active_session (1984383994625845642) -->
- <skip />
+ <string name="controls_media_active_session" msgid="1984383994625845642">"Non se pode ocultar a sesión actual."</string>
<string name="controls_media_dismiss_button" msgid="9081375542265132213">"Ignorar"</string>
<string name="controls_media_resume" msgid="1933520684481586053">"Retomar"</string>
<string name="controls_media_settings_button" msgid="5815790345117172504">"Configuración"</string>
diff --git a/packages/SystemUI/res/values-gu/strings.xml b/packages/SystemUI/res/values-gu/strings.xml
index acaa4420cb56..02c72dbbc7a6 100644
--- a/packages/SystemUI/res/values-gu/strings.xml
+++ b/packages/SystemUI/res/values-gu/strings.xml
@@ -86,8 +86,7 @@
<string name="screenshot_failed_to_save_unknown_text" msgid="1506621600548684129">"ફરીથી સ્ક્રીનશૉટ લેવાનો પ્રયાસ કરો"</string>
<string name="screenshot_failed_to_save_text" msgid="8344173457344027501">"મર્યાદિત સ્ટોરેજ સ્પેસને કારણે સ્ક્રીનશૉટ સાચવી શકાતો નથી"</string>
<string name="screenshot_failed_to_capture_text" msgid="7818288545874407451">"ઍપ્લિકેશન કે તમારી સંસ્થા દ્વારા સ્ક્રીનશૉટ લેવાની મંજૂરી નથી"</string>
- <!-- no translation found for screenshot_edit (3510496440489019191) -->
- <skip />
+ <string name="screenshot_edit" msgid="3510496440489019191">"સ્ક્રીનશૉટમાં ફેરફાર કરો"</string>
<string name="screenshot_dismiss_ui_description" msgid="934736855340147968">"સ્ક્રીનશૉટ છોડી દો"</string>
<string name="screenshot_preview_description" msgid="7606510140714080474">"સ્ક્રીનશૉટનો પ્રીવ્યૂ"</string>
<string name="screenrecord_name" msgid="2596401223859996572">"સ્ક્રીન રેકૉર્ડર"</string>
@@ -1065,8 +1064,7 @@
<string name="controls_seeding_in_progress" msgid="3033855341410264148">"સુઝાવ લોડ કરી રહ્યાં છીએ"</string>
<string name="controls_media_title" msgid="1746947284862928133">"મીડિયા"</string>
<string name="controls_media_close_session" msgid="3957093425905475065">"હાલનું સત્ર છુપાવો."</string>
- <!-- no translation found for controls_media_active_session (1984383994625845642) -->
- <skip />
+ <string name="controls_media_active_session" msgid="1984383994625845642">"વર્તમાન સત્ર છુપાવી શકાતું નથી."</string>
<string name="controls_media_dismiss_button" msgid="9081375542265132213">"છોડી દો"</string>
<string name="controls_media_resume" msgid="1933520684481586053">"ફરી શરૂ કરો"</string>
<string name="controls_media_settings_button" msgid="5815790345117172504">"સેટિંગ"</string>
diff --git a/packages/SystemUI/res/values-hi/strings.xml b/packages/SystemUI/res/values-hi/strings.xml
index d211dce96944..3f497e750b77 100644
--- a/packages/SystemUI/res/values-hi/strings.xml
+++ b/packages/SystemUI/res/values-hi/strings.xml
@@ -86,8 +86,7 @@
<string name="screenshot_failed_to_save_unknown_text" msgid="1506621600548684129">"स्क्रीनशॉट दोबारा लेने की कोशिश करें"</string>
<string name="screenshot_failed_to_save_text" msgid="8344173457344027501">"मेमोरी कम होने की वजह से स्क्रीनशॉट सेव नहीं किया जा सका"</string>
<string name="screenshot_failed_to_capture_text" msgid="7818288545874407451">"ऐप्लिकेशन या आपका संगठन स्क्रीनशॉट लेने की अनुमति नहीं देता"</string>
- <!-- no translation found for screenshot_edit (3510496440489019191) -->
- <skip />
+ <string name="screenshot_edit" msgid="3510496440489019191">"स्क्रीनशॉट में बदलाव करें"</string>
<string name="screenshot_dismiss_ui_description" msgid="934736855340147968">"स्क्रीनशॉट खारिज करें"</string>
<string name="screenshot_preview_description" msgid="7606510140714080474">"स्क्रीनशॉट की झलक"</string>
<string name="screenrecord_name" msgid="2596401223859996572">"स्क्रीन रिकॉर्डर"</string>
@@ -1067,8 +1066,7 @@
<string name="controls_seeding_in_progress" msgid="3033855341410264148">"सुझाव लोड हो रहे हैं"</string>
<string name="controls_media_title" msgid="1746947284862928133">"मीडिया"</string>
<string name="controls_media_close_session" msgid="3957093425905475065">"इस मीडिया सेशन को छिपाएं."</string>
- <!-- no translation found for controls_media_active_session (1984383994625845642) -->
- <skip />
+ <string name="controls_media_active_session" msgid="1984383994625845642">"मौजूदा मीडिया सत्र छिपाया नहीं जा सकता."</string>
<string name="controls_media_dismiss_button" msgid="9081375542265132213">"खारिज करें"</string>
<string name="controls_media_resume" msgid="1933520684481586053">"फिर से शुरू करें"</string>
<string name="controls_media_settings_button" msgid="5815790345117172504">"सेटिंग"</string>
diff --git a/packages/SystemUI/res/values-hr/strings.xml b/packages/SystemUI/res/values-hr/strings.xml
index b5671bf7abe0..9958a2c65998 100644
--- a/packages/SystemUI/res/values-hr/strings.xml
+++ b/packages/SystemUI/res/values-hr/strings.xml
@@ -86,8 +86,7 @@
<string name="screenshot_failed_to_save_unknown_text" msgid="1506621600548684129">"Pokušajte ponovo napraviti snimku zaslona"</string>
<string name="screenshot_failed_to_save_text" msgid="8344173457344027501">"Zaslon nije snimljen zbog ograničenog prostora za pohranu"</string>
<string name="screenshot_failed_to_capture_text" msgid="7818288545874407451">"Aplikacija ili vaša organizacija ne dopuštaju snimanje zaslona"</string>
- <!-- no translation found for screenshot_edit (3510496440489019191) -->
- <skip />
+ <string name="screenshot_edit" msgid="3510496440489019191">"Uređivanje snimke zaslona"</string>
<string name="screenshot_dismiss_ui_description" msgid="934736855340147968">"Odbacivanje snimke zaslona"</string>
<string name="screenshot_preview_description" msgid="7606510140714080474">"Pregled snimke zaslona"</string>
<string name="screenrecord_name" msgid="2596401223859996572">"Snimač zaslona"</string>
@@ -1071,8 +1070,7 @@
<string name="controls_seeding_in_progress" msgid="3033855341410264148">"Učitavanje preporuka"</string>
<string name="controls_media_title" msgid="1746947284862928133">"Mediji"</string>
<string name="controls_media_close_session" msgid="3957093425905475065">"Sakrij trenutačnu sesiju."</string>
- <!-- no translation found for controls_media_active_session (1984383994625845642) -->
- <skip />
+ <string name="controls_media_active_session" msgid="1984383994625845642">"Trenutačnu sesiju nije moguće sakriti."</string>
<string name="controls_media_dismiss_button" msgid="9081375542265132213">"Odbaci"</string>
<string name="controls_media_resume" msgid="1933520684481586053">"Nastavi"</string>
<string name="controls_media_settings_button" msgid="5815790345117172504">"Postavke"</string>
diff --git a/packages/SystemUI/res/values-hu/strings.xml b/packages/SystemUI/res/values-hu/strings.xml
index 291976e1f77c..0159ec617bf2 100644
--- a/packages/SystemUI/res/values-hu/strings.xml
+++ b/packages/SystemUI/res/values-hu/strings.xml
@@ -86,8 +86,7 @@
<string name="screenshot_failed_to_save_unknown_text" msgid="1506621600548684129">"Próbálja meg újra elkészíteni a képernyőképet"</string>
<string name="screenshot_failed_to_save_text" msgid="8344173457344027501">"Nem menthet képernyőképet, mert kevés a tárhely"</string>
<string name="screenshot_failed_to_capture_text" msgid="7818288545874407451">"Az alkalmazás vagy az Ön szervezete nem engedélyezi képernyőkép készítését"</string>
- <!-- no translation found for screenshot_edit (3510496440489019191) -->
- <skip />
+ <string name="screenshot_edit" msgid="3510496440489019191">"Képernyőkép szerkesztése"</string>
<string name="screenshot_dismiss_ui_description" msgid="934736855340147968">"Képernyőkép elvetése"</string>
<string name="screenshot_preview_description" msgid="7606510140714080474">"Képernyőkép előnézete"</string>
<string name="screenrecord_name" msgid="2596401223859996572">"Képernyőrögzítő"</string>
@@ -1065,8 +1064,7 @@
<string name="controls_seeding_in_progress" msgid="3033855341410264148">"Javaslatok betöltése…"</string>
<string name="controls_media_title" msgid="1746947284862928133">"Média"</string>
<string name="controls_media_close_session" msgid="3957093425905475065">"Jelenlegi munkamenet elrejtése."</string>
- <!-- no translation found for controls_media_active_session (1984383994625845642) -->
- <skip />
+ <string name="controls_media_active_session" msgid="1984383994625845642">"A jelenlegi munkamenetet nem lehet elrejteni."</string>
<string name="controls_media_dismiss_button" msgid="9081375542265132213">"Elvetés"</string>
<string name="controls_media_resume" msgid="1933520684481586053">"Folytatás"</string>
<string name="controls_media_settings_button" msgid="5815790345117172504">"Beállítások"</string>
diff --git a/packages/SystemUI/res/values-in/strings.xml b/packages/SystemUI/res/values-in/strings.xml
index f21952098a57..9aaf2705e657 100644
--- a/packages/SystemUI/res/values-in/strings.xml
+++ b/packages/SystemUI/res/values-in/strings.xml
@@ -86,8 +86,7 @@
<string name="screenshot_failed_to_save_unknown_text" msgid="1506621600548684129">"Coba ambil screenshot lagi"</string>
<string name="screenshot_failed_to_save_text" msgid="8344173457344027501">"Tidak dapat menyimpan screenshot karena ruang penyimpanan terbatas"</string>
<string name="screenshot_failed_to_capture_text" msgid="7818288545874407451">"Mengambil screenshot tidak diizinkan oleh aplikasi atau organisasi"</string>
- <!-- no translation found for screenshot_edit (3510496440489019191) -->
- <skip />
+ <string name="screenshot_edit" msgid="3510496440489019191">"Edit screenshot"</string>
<string name="screenshot_dismiss_ui_description" msgid="934736855340147968">"Menutup screenshot"</string>
<string name="screenshot_preview_description" msgid="7606510140714080474">"Pratinjau screenshot"</string>
<string name="screenrecord_name" msgid="2596401223859996572">"Perekam Layar"</string>
@@ -1065,8 +1064,7 @@
<string name="controls_seeding_in_progress" msgid="3033855341410264148">"Memuat rekomendasi"</string>
<string name="controls_media_title" msgid="1746947284862928133">"Media"</string>
<string name="controls_media_close_session" msgid="3957093425905475065">"Menyembunyikan sesi saat ini."</string>
- <!-- no translation found for controls_media_active_session (1984383994625845642) -->
- <skip />
+ <string name="controls_media_active_session" msgid="1984383994625845642">"Sesi saat ini tidak dapat disembunyikan."</string>
<string name="controls_media_dismiss_button" msgid="9081375542265132213">"Tutup"</string>
<string name="controls_media_resume" msgid="1933520684481586053">"Lanjutkan"</string>
<string name="controls_media_settings_button" msgid="5815790345117172504">"Setelan"</string>
diff --git a/packages/SystemUI/res/values-is/strings.xml b/packages/SystemUI/res/values-is/strings.xml
index 8f1049f7d5a9..bf49e97785c4 100644
--- a/packages/SystemUI/res/values-is/strings.xml
+++ b/packages/SystemUI/res/values-is/strings.xml
@@ -86,8 +86,7 @@
<string name="screenshot_failed_to_save_unknown_text" msgid="1506621600548684129">"Prófaðu að taka skjámynd aftur"</string>
<string name="screenshot_failed_to_save_text" msgid="8344173457344027501">"Ekki tókst að vista skjámynd vegna takmarkaðs geymslupláss"</string>
<string name="screenshot_failed_to_capture_text" msgid="7818288545874407451">"Forritið eða fyrirtækið þitt leyfir ekki skjámyndatöku"</string>
- <!-- no translation found for screenshot_edit (3510496440489019191) -->
- <skip />
+ <string name="screenshot_edit" msgid="3510496440489019191">"Breyta skjámynd"</string>
<string name="screenshot_dismiss_ui_description" msgid="934736855340147968">"Loka skjámynd"</string>
<string name="screenshot_preview_description" msgid="7606510140714080474">"Forskoðun skjámyndar"</string>
<string name="screenrecord_name" msgid="2596401223859996572">"Skjáupptaka"</string>
@@ -1065,8 +1064,7 @@
<string name="controls_seeding_in_progress" msgid="3033855341410264148">"Hleður tillögum"</string>
<string name="controls_media_title" msgid="1746947284862928133">"Margmiðlunarefni"</string>
<string name="controls_media_close_session" msgid="3957093425905475065">"Fela núverandi lotu."</string>
- <!-- no translation found for controls_media_active_session (1984383994625845642) -->
- <skip />
+ <string name="controls_media_active_session" msgid="1984383994625845642">"Ekki er hægt að fela núverandi lotu."</string>
<string name="controls_media_dismiss_button" msgid="9081375542265132213">"Hunsa"</string>
<string name="controls_media_resume" msgid="1933520684481586053">"Halda áfram"</string>
<string name="controls_media_settings_button" msgid="5815790345117172504">"Stillingar"</string>
diff --git a/packages/SystemUI/res/values-it/strings.xml b/packages/SystemUI/res/values-it/strings.xml
index a273ea8ad7ac..8e665ec31ba0 100644
--- a/packages/SystemUI/res/values-it/strings.xml
+++ b/packages/SystemUI/res/values-it/strings.xml
@@ -86,8 +86,7 @@
<string name="screenshot_failed_to_save_unknown_text" msgid="1506621600548684129">"Riprova ad acquisire lo screenshot"</string>
<string name="screenshot_failed_to_save_text" msgid="8344173457344027501">"Impossibile salvare lo screenshot a causa dello spazio di archiviazione limitato"</string>
<string name="screenshot_failed_to_capture_text" msgid="7818288545874407451">"L\'acquisizione di screenshot non è consentita dall\'app o dall\'organizzazione"</string>
- <!-- no translation found for screenshot_edit (3510496440489019191) -->
- <skip />
+ <string name="screenshot_edit" msgid="3510496440489019191">"Modifica screenshot"</string>
<string name="screenshot_dismiss_ui_description" msgid="934736855340147968">"Ignora screenshot"</string>
<string name="screenshot_preview_description" msgid="7606510140714080474">"Anteprima screenshot"</string>
<string name="screenrecord_name" msgid="2596401223859996572">"Registrazione dello schermo"</string>
@@ -1065,8 +1064,7 @@
<string name="controls_seeding_in_progress" msgid="3033855341410264148">"Caricamento dei consigli"</string>
<string name="controls_media_title" msgid="1746947284862928133">"Contenuti multimediali"</string>
<string name="controls_media_close_session" msgid="3957093425905475065">"Nascondi la sessione attuale."</string>
- <!-- no translation found for controls_media_active_session (1984383994625845642) -->
- <skip />
+ <string name="controls_media_active_session" msgid="1984383994625845642">"Impossibile nascondere la sessione corrente."</string>
<string name="controls_media_dismiss_button" msgid="9081375542265132213">"Ignora"</string>
<string name="controls_media_resume" msgid="1933520684481586053">"Riprendi"</string>
<string name="controls_media_settings_button" msgid="5815790345117172504">"Impostazioni"</string>
diff --git a/packages/SystemUI/res/values-iw/strings.xml b/packages/SystemUI/res/values-iw/strings.xml
index 5ae10ad72a45..052b721b6eef 100644
--- a/packages/SystemUI/res/values-iw/strings.xml
+++ b/packages/SystemUI/res/values-iw/strings.xml
@@ -86,8 +86,7 @@
<string name="screenshot_failed_to_save_unknown_text" msgid="1506621600548684129">"יש לנסות שוב לבצע צילום מסך"</string>
<string name="screenshot_failed_to_save_text" msgid="8344173457344027501">"לא היה מספיק מקום לשמור את צילום המסך"</string>
<string name="screenshot_failed_to_capture_text" msgid="7818288545874407451">"האפליקציה או הארגון שלך אינם מתירים ליצור צילומי מסך"</string>
- <!-- no translation found for screenshot_edit (3510496440489019191) -->
- <skip />
+ <string name="screenshot_edit" msgid="3510496440489019191">"עריכת צילום מסך"</string>
<string name="screenshot_dismiss_ui_description" msgid="934736855340147968">"סגירת צילום מסך"</string>
<string name="screenshot_preview_description" msgid="7606510140714080474">"תצוגה מקדימה של צילום מסך"</string>
<string name="screenrecord_name" msgid="2596401223859996572">"מקליט המסך"</string>
@@ -1077,8 +1076,7 @@
<string name="controls_seeding_in_progress" msgid="3033855341410264148">"בטעינת המלצות"</string>
<string name="controls_media_title" msgid="1746947284862928133">"מדיה"</string>
<string name="controls_media_close_session" msgid="3957093425905475065">"הסתרת הסשן הנוכחי."</string>
- <!-- no translation found for controls_media_active_session (1984383994625845642) -->
- <skip />
+ <string name="controls_media_active_session" msgid="1984383994625845642">"לא ניתן להסתיר את הסשן הנוכחי."</string>
<string name="controls_media_dismiss_button" msgid="9081375542265132213">"סגירה"</string>
<string name="controls_media_resume" msgid="1933520684481586053">"המשך"</string>
<string name="controls_media_settings_button" msgid="5815790345117172504">"הגדרות"</string>
diff --git a/packages/SystemUI/res/values-ja/strings.xml b/packages/SystemUI/res/values-ja/strings.xml
index 5d22c9a0c295..7e64155fae63 100644
--- a/packages/SystemUI/res/values-ja/strings.xml
+++ b/packages/SystemUI/res/values-ja/strings.xml
@@ -86,8 +86,7 @@
<string name="screenshot_failed_to_save_unknown_text" msgid="1506621600548684129">"スクリーンショットを撮り直してください"</string>
<string name="screenshot_failed_to_save_text" msgid="8344173457344027501">"空き容量が足りないため、スクリーンショットを保存できません"</string>
<string name="screenshot_failed_to_capture_text" msgid="7818288545874407451">"スクリーンショットの作成はアプリまたは組織で許可されていません"</string>
- <!-- no translation found for screenshot_edit (3510496440489019191) -->
- <skip />
+ <string name="screenshot_edit" msgid="3510496440489019191">"スクリーンショットの編集"</string>
<string name="screenshot_dismiss_ui_description" msgid="934736855340147968">"スクリーンショットを閉じます"</string>
<string name="screenshot_preview_description" msgid="7606510140714080474">"スクリーンショットのプレビュー"</string>
<string name="screenrecord_name" msgid="2596401223859996572">"スクリーン レコーダー"</string>
@@ -1065,8 +1064,7 @@
<string name="controls_seeding_in_progress" msgid="3033855341410264148">"候補を読み込んでいます"</string>
<string name="controls_media_title" msgid="1746947284862928133">"メディア"</string>
<string name="controls_media_close_session" msgid="3957093425905475065">"現在のセッションを非表示にします。"</string>
- <!-- no translation found for controls_media_active_session (1984383994625845642) -->
- <skip />
+ <string name="controls_media_active_session" msgid="1984383994625845642">"現在のセッションは非表示にできません。"</string>
<string name="controls_media_dismiss_button" msgid="9081375542265132213">"閉じる"</string>
<string name="controls_media_resume" msgid="1933520684481586053">"再開"</string>
<string name="controls_media_settings_button" msgid="5815790345117172504">"設定"</string>
diff --git a/packages/SystemUI/res/values-kk/strings.xml b/packages/SystemUI/res/values-kk/strings.xml
index 68cd2474c5aa..a6376e37741d 100644
--- a/packages/SystemUI/res/values-kk/strings.xml
+++ b/packages/SystemUI/res/values-kk/strings.xml
@@ -86,8 +86,7 @@
<string name="screenshot_failed_to_save_unknown_text" msgid="1506621600548684129">"Қайта скриншот жасап көріңіз"</string>
<string name="screenshot_failed_to_save_text" msgid="8344173457344027501">"Жадтағы шектеулі бос орынға байланысты скриншот сақталмайды"</string>
<string name="screenshot_failed_to_capture_text" msgid="7818288545874407451">"Қолданба немесе ұйым скриншоттар түсіруге рұқсат етпейді"</string>
- <!-- no translation found for screenshot_edit (3510496440489019191) -->
- <skip />
+ <string name="screenshot_edit" msgid="3510496440489019191">"Скриншотты өзгерту"</string>
<string name="screenshot_dismiss_ui_description" msgid="934736855340147968">"Скриншотты жабу"</string>
<string name="screenshot_preview_description" msgid="7606510140714080474">"Скриншотты алдын ала қарау"</string>
<string name="screenrecord_name" msgid="2596401223859996572">"Экран жазғыш"</string>
@@ -1065,8 +1064,7 @@
<string name="controls_seeding_in_progress" msgid="3033855341410264148">"Жүктеуге қатысты ұсыныстар"</string>
<string name="controls_media_title" msgid="1746947284862928133">"Мультимедиа"</string>
<string name="controls_media_close_session" msgid="3957093425905475065">"Ағымдағы сеансты жасыру"</string>
- <!-- no translation found for controls_media_active_session (1984383994625845642) -->
- <skip />
+ <string name="controls_media_active_session" msgid="1984383994625845642">"Қазіргі сеансты жасыру мүмкін емес."</string>
<string name="controls_media_dismiss_button" msgid="9081375542265132213">"Жабу"</string>
<string name="controls_media_resume" msgid="1933520684481586053">"Жалғастыру"</string>
<string name="controls_media_settings_button" msgid="5815790345117172504">"Параметрлер"</string>
diff --git a/packages/SystemUI/res/values-km/strings.xml b/packages/SystemUI/res/values-km/strings.xml
index 55f3f44f7b1f..b8d2fa8a04ba 100644
--- a/packages/SystemUI/res/values-km/strings.xml
+++ b/packages/SystemUI/res/values-km/strings.xml
@@ -86,8 +86,7 @@
<string name="screenshot_failed_to_save_unknown_text" msgid="1506621600548684129">"សាកល្បង​ថតរូបថត​អេក្រង់​ម្តងទៀត"</string>
<string name="screenshot_failed_to_save_text" msgid="8344173457344027501">"មិនអាច​រក្សាទុក​រូបថតអេក្រង់​បានទេ ​ដោយសារ​ទំហំផ្ទុក​មានកម្រិតទាប"</string>
<string name="screenshot_failed_to_capture_text" msgid="7818288545874407451">"ការថត​រូបអេក្រង់​មិនត្រូវ​បាន​អនុញ្ញាត​ដោយ​កម្មវិធី​នេះ ឬ​ស្ថាប័ន​របស់អ្នក"</string>
- <!-- no translation found for screenshot_edit (3510496440489019191) -->
- <skip />
+ <string name="screenshot_edit" msgid="3510496440489019191">"កែ​រូបថត​អេក្រង់"</string>
<string name="screenshot_dismiss_ui_description" msgid="934736855340147968">"ច្រានចោល​រូបថត​អេក្រង់"</string>
<string name="screenshot_preview_description" msgid="7606510140714080474">"ការមើល​រូបថត​អេក្រង់​សាកល្បង"</string>
<string name="screenrecord_name" msgid="2596401223859996572">"មុខងារថត​អេក្រង់"</string>
@@ -1065,8 +1064,7 @@
<string name="controls_seeding_in_progress" msgid="3033855341410264148">"កំពុងផ្ទុក​ការណែនាំ"</string>
<string name="controls_media_title" msgid="1746947284862928133">"មេឌៀ"</string>
<string name="controls_media_close_session" msgid="3957093425905475065">"លាក់វគ្គ​បច្ចុប្បន្ន។"</string>
- <!-- no translation found for controls_media_active_session (1984383994625845642) -->
- <skip />
+ <string name="controls_media_active_session" msgid="1984383994625845642">"មិនអាចលាក់​វគ្គបច្ចុប្បន្នបានទេ។"</string>
<string name="controls_media_dismiss_button" msgid="9081375542265132213">"ច្រាន​ចោល"</string>
<string name="controls_media_resume" msgid="1933520684481586053">"បន្ត"</string>
<string name="controls_media_settings_button" msgid="5815790345117172504">"ការកំណត់"</string>
diff --git a/packages/SystemUI/res/values-kn/strings.xml b/packages/SystemUI/res/values-kn/strings.xml
index 569837bc6612..5c502acc1e50 100644
--- a/packages/SystemUI/res/values-kn/strings.xml
+++ b/packages/SystemUI/res/values-kn/strings.xml
@@ -86,8 +86,7 @@
<string name="screenshot_failed_to_save_unknown_text" msgid="1506621600548684129">"ಸ್ಕ್ರೀನ್‌ಶಾಟ್ ಅನ್ನು ಪುನಃ ತೆಗೆದುಕೊಳ್ಳಲು ಪ್ರಯತ್ನಿಸಿ"</string>
<string name="screenshot_failed_to_save_text" msgid="8344173457344027501">"ಪರಿಮಿತ ಸಂಗ್ರಹಣೆ ಸ್ಥಳದ ಕಾರಣದಿಂದಾಗಿ ಸ್ಕ್ರೀನ್‌ಶಾಟ್ ಉಳಿಸಲು ಸಾಧ್ಯವಿಲ್ಲ"</string>
<string name="screenshot_failed_to_capture_text" msgid="7818288545874407451">"ಅಪ್ಲಿಕೇಶನ್ ಅಥವಾ ಸಂಸ್ಥೆಯು ಸ್ಕ್ರೀನ್‌ಶಾಟ್‌ಗಳನ್ನು ತೆಗೆಯುವುದನ್ನು ಅನುಮತಿಸುವುದಿಲ್ಲ"</string>
- <!-- no translation found for screenshot_edit (3510496440489019191) -->
- <skip />
+ <string name="screenshot_edit" msgid="3510496440489019191">"ಸ್ಕ್ರೀನ್‌ಶಾಟ್‌ ಅನ್ನು ಎಡಿಟ್ ಮಾಡಿ"</string>
<string name="screenshot_dismiss_ui_description" msgid="934736855340147968">"ಸ್ಕ್ರೀನ್‌ಶಾಟ್ ಅನ್ನು ವಜಾಗೊಳಿಸಿ"</string>
<string name="screenshot_preview_description" msgid="7606510140714080474">"ಸ್ಕ್ರೀನ್‍ಶಾಟ್‍ನ ಪೂರ್ವವೀಕ್ಷಣೆ"</string>
<string name="screenrecord_name" msgid="2596401223859996572">"ಸ್ಕ್ರೀನ್ ರೆಕಾರ್ಡರ್"</string>
@@ -1065,8 +1064,7 @@
<string name="controls_seeding_in_progress" msgid="3033855341410264148">"ಶಿಫಾರಸುಗಳು ಲೋಡ್ ಆಗುತ್ತಿವೆ"</string>
<string name="controls_media_title" msgid="1746947284862928133">"ಮಾಧ್ಯಮ"</string>
<string name="controls_media_close_session" msgid="3957093425905475065">"ಪ್ರಸ್ತುತ ಸೆಶನ್ ಅನ್ನು ಮರೆಮಾಡಿ."</string>
- <!-- no translation found for controls_media_active_session (1984383994625845642) -->
- <skip />
+ <string name="controls_media_active_session" msgid="1984383994625845642">"ಪ್ರಸ್ತುತ ಸೆಶನ್ ಅನ್ನು ಮರೆಮಾಡಲು ಸಾಧ್ಯವಿಲ್ಲ."</string>
<string name="controls_media_dismiss_button" msgid="9081375542265132213">"ವಜಾಗೊಳಿಸಿ"</string>
<string name="controls_media_resume" msgid="1933520684481586053">"ಪುನರಾರಂಭಿಸಿ"</string>
<string name="controls_media_settings_button" msgid="5815790345117172504">"ಸೆಟ್ಟಿಂಗ್‌ಗಳು"</string>
diff --git a/packages/SystemUI/res/values-ko/strings.xml b/packages/SystemUI/res/values-ko/strings.xml
index 1fdff749151f..cef515827b7d 100644
--- a/packages/SystemUI/res/values-ko/strings.xml
+++ b/packages/SystemUI/res/values-ko/strings.xml
@@ -86,8 +86,7 @@
<string name="screenshot_failed_to_save_unknown_text" msgid="1506621600548684129">"스크린샷을 다시 찍어 보세요."</string>
<string name="screenshot_failed_to_save_text" msgid="8344173457344027501">"저장용량이 부족하여 스크린샷을 저장할 수 없습니다"</string>
<string name="screenshot_failed_to_capture_text" msgid="7818288545874407451">"앱이나 조직에서 스크린샷 촬영을 허용하지 않습니다."</string>
- <!-- no translation found for screenshot_edit (3510496440489019191) -->
- <skip />
+ <string name="screenshot_edit" msgid="3510496440489019191">"스크린샷 수정"</string>
<string name="screenshot_dismiss_ui_description" msgid="934736855340147968">"스크린샷 닫기"</string>
<string name="screenshot_preview_description" msgid="7606510140714080474">"스크린샷 미리보기"</string>
<string name="screenrecord_name" msgid="2596401223859996572">"화면 녹화"</string>
@@ -1065,8 +1064,7 @@
<string name="controls_seeding_in_progress" msgid="3033855341410264148">"추천 제어 기능 로드 중"</string>
<string name="controls_media_title" msgid="1746947284862928133">"미디어"</string>
<string name="controls_media_close_session" msgid="3957093425905475065">"현재 세션을 숨깁니다."</string>
- <!-- no translation found for controls_media_active_session (1984383994625845642) -->
- <skip />
+ <string name="controls_media_active_session" msgid="1984383994625845642">"현재 세션은 숨길 수 없습니다."</string>
<string name="controls_media_dismiss_button" msgid="9081375542265132213">"닫기"</string>
<string name="controls_media_resume" msgid="1933520684481586053">"다시 시작"</string>
<string name="controls_media_settings_button" msgid="5815790345117172504">"설정"</string>
diff --git a/packages/SystemUI/res/values-ky/strings.xml b/packages/SystemUI/res/values-ky/strings.xml
index 970d5fab09cb..572c3e7944c8 100644
--- a/packages/SystemUI/res/values-ky/strings.xml
+++ b/packages/SystemUI/res/values-ky/strings.xml
@@ -86,8 +86,7 @@
<string name="screenshot_failed_to_save_unknown_text" msgid="1506621600548684129">"Скриншотту кайра тартып көрүңүз"</string>
<string name="screenshot_failed_to_save_text" msgid="8344173457344027501">"Сактагычта бош орун аз болгондуктан, скриншот сакталбай жатат"</string>
<string name="screenshot_failed_to_capture_text" msgid="7818288545874407451">"Скриншот тартууга колдонмо же ишканаңыз тыюу салган."</string>
- <!-- no translation found for screenshot_edit (3510496440489019191) -->
- <skip />
+ <string name="screenshot_edit" msgid="3510496440489019191">"Скриншотту түзөтүү"</string>
<string name="screenshot_dismiss_ui_description" msgid="934736855340147968">"Скриншотту четке кагуу"</string>
<string name="screenshot_preview_description" msgid="7606510140714080474">"Скриншотту алдын ала көрүү"</string>
<string name="screenrecord_name" msgid="2596401223859996572">"экрандан видео жаздырып алуу"</string>
@@ -1065,8 +1064,7 @@
<string name="controls_seeding_in_progress" msgid="3033855341410264148">"Сунуштар жүктөлүүдө"</string>
<string name="controls_media_title" msgid="1746947284862928133">"Медиа"</string>
<string name="controls_media_close_session" msgid="3957093425905475065">"Учурдагы сеансты жашыруу."</string>
- <!-- no translation found for controls_media_active_session (1984383994625845642) -->
- <skip />
+ <string name="controls_media_active_session" msgid="1984383994625845642">"Учудагы сеансты жашырууга болбойт."</string>
<string name="controls_media_dismiss_button" msgid="9081375542265132213">"Жабуу"</string>
<string name="controls_media_resume" msgid="1933520684481586053">"Улантуу"</string>
<string name="controls_media_settings_button" msgid="5815790345117172504">"Жөндөөлөр"</string>
diff --git a/packages/SystemUI/res/values-lo/strings.xml b/packages/SystemUI/res/values-lo/strings.xml
index 9f0f0ae0eb59..1cc1b4e4b6df 100644
--- a/packages/SystemUI/res/values-lo/strings.xml
+++ b/packages/SystemUI/res/values-lo/strings.xml
@@ -1064,7 +1064,7 @@
<string name="controls_seeding_in_progress" msgid="3033855341410264148">"ກຳລັງໂຫຼດຄຳແນະນຳ"</string>
<string name="controls_media_title" msgid="1746947284862928133">"ມີເດຍ"</string>
<string name="controls_media_close_session" msgid="3957093425905475065">"ເຊື່ອງເຊດຊັນປັດຈຸບັນ."</string>
- <string name="controls_media_active_session" msgid="1984383994625845642">"ບໍ່ສາມາດເຊື່ອເຊດຊັນປັດຈຸບັນໄດ້."</string>
+ <string name="controls_media_active_session" msgid="1984383994625845642">"ບໍ່ສາມາດເຊື່ອງເຊດຊັນປັດຈຸບັນໄດ້."</string>
<string name="controls_media_dismiss_button" msgid="9081375542265132213">"ປິດໄວ້"</string>
<string name="controls_media_resume" msgid="1933520684481586053">"ສືບຕໍ່"</string>
<string name="controls_media_settings_button" msgid="5815790345117172504">"ການຕັ້ງຄ່າ"</string>
diff --git a/packages/SystemUI/res/values-lt/strings.xml b/packages/SystemUI/res/values-lt/strings.xml
index 81696c2c88df..152a5323536b 100644
--- a/packages/SystemUI/res/values-lt/strings.xml
+++ b/packages/SystemUI/res/values-lt/strings.xml
@@ -86,8 +86,7 @@
<string name="screenshot_failed_to_save_unknown_text" msgid="1506621600548684129">"Pabandykite padaryti ekrano kopiją dar kartą"</string>
<string name="screenshot_failed_to_save_text" msgid="8344173457344027501">"Negalima išsaugoti ekrano kopijos dėl ribotos saugyklos vietos"</string>
<string name="screenshot_failed_to_capture_text" msgid="7818288545874407451">"Jūsų organizacijoje arba naudojant šią programą neleidžiama daryti ekrano kopijų"</string>
- <!-- no translation found for screenshot_edit (3510496440489019191) -->
- <skip />
+ <string name="screenshot_edit" msgid="3510496440489019191">"Redaguoti ekrano kopiją"</string>
<string name="screenshot_dismiss_ui_description" msgid="934736855340147968">"Praleisti ekrano kopiją"</string>
<string name="screenshot_preview_description" msgid="7606510140714080474">"Ekrano kopijos peržiūra"</string>
<string name="screenrecord_name" msgid="2596401223859996572">"Ekrano vaizdo įrašytuvas"</string>
@@ -1077,8 +1076,7 @@
<string name="controls_seeding_in_progress" msgid="3033855341410264148">"Įkeliamos rekomendacijos"</string>
<string name="controls_media_title" msgid="1746947284862928133">"Medija"</string>
<string name="controls_media_close_session" msgid="3957093425905475065">"Slėpti dabartinį seansą."</string>
- <!-- no translation found for controls_media_active_session (1984383994625845642) -->
- <skip />
+ <string name="controls_media_active_session" msgid="1984383994625845642">"Dabartinio seanso paslėpti negalima."</string>
<string name="controls_media_dismiss_button" msgid="9081375542265132213">"Atsisakyti"</string>
<string name="controls_media_resume" msgid="1933520684481586053">"Tęsti"</string>
<string name="controls_media_settings_button" msgid="5815790345117172504">"Nustatymai"</string>
diff --git a/packages/SystemUI/res/values-lv/strings.xml b/packages/SystemUI/res/values-lv/strings.xml
index d37dd914865c..ae67d0f22997 100644
--- a/packages/SystemUI/res/values-lv/strings.xml
+++ b/packages/SystemUI/res/values-lv/strings.xml
@@ -86,8 +86,7 @@
<string name="screenshot_failed_to_save_unknown_text" msgid="1506621600548684129">"Mēģiniet izveidot jaunu ekrānuzņēmumu."</string>
<string name="screenshot_failed_to_save_text" msgid="8344173457344027501">"Nevar saglabāt ekrānuzņēmumu, jo krātuvē nepietiek vietas."</string>
<string name="screenshot_failed_to_capture_text" msgid="7818288545874407451">"Lietotne vai jūsu organizācija neatļauj veikt ekrānuzņēmumus."</string>
- <!-- no translation found for screenshot_edit (3510496440489019191) -->
- <skip />
+ <string name="screenshot_edit" msgid="3510496440489019191">"Rediģēt ekrānuzņēmumu"</string>
<string name="screenshot_dismiss_ui_description" msgid="934736855340147968">"Nerādīt ekrānuzņēmumu"</string>
<string name="screenshot_preview_description" msgid="7606510140714080474">"Ekrānuzņēmuma priekšskatījums"</string>
<string name="screenrecord_name" msgid="2596401223859996572">"Ekrāna ierakstītājs"</string>
@@ -1071,8 +1070,7 @@
<string name="controls_seeding_in_progress" msgid="3033855341410264148">"Notiek ieteikumu ielāde"</string>
<string name="controls_media_title" msgid="1746947284862928133">"Multivide"</string>
<string name="controls_media_close_session" msgid="3957093425905475065">"Paslēpiet pašreizējo sesiju."</string>
- <!-- no translation found for controls_media_active_session (1984383994625845642) -->
- <skip />
+ <string name="controls_media_active_session" msgid="1984383994625845642">"Pašreizējo sesiju nevar paslēpt"</string>
<string name="controls_media_dismiss_button" msgid="9081375542265132213">"Nerādīt"</string>
<string name="controls_media_resume" msgid="1933520684481586053">"Atsākt"</string>
<string name="controls_media_settings_button" msgid="5815790345117172504">"Iestatījumi"</string>
diff --git a/packages/SystemUI/res/values-mk/strings.xml b/packages/SystemUI/res/values-mk/strings.xml
index 28c4ee7fc951..fca688d28f8e 100644
--- a/packages/SystemUI/res/values-mk/strings.xml
+++ b/packages/SystemUI/res/values-mk/strings.xml
@@ -86,8 +86,7 @@
<string name="screenshot_failed_to_save_unknown_text" msgid="1506621600548684129">"Повторно обидете се да направите слика од екранот"</string>
<string name="screenshot_failed_to_save_text" msgid="8344173457344027501">"Сликата од екранот не може да се зачува поради ограничена меморија"</string>
<string name="screenshot_failed_to_capture_text" msgid="7818288545874407451">"Апликацијата или вашата организација не дозволува снимање слики од екранот"</string>
- <!-- no translation found for screenshot_edit (3510496440489019191) -->
- <skip />
+ <string name="screenshot_edit" msgid="3510496440489019191">"Изменете ја сликата од екранот"</string>
<string name="screenshot_dismiss_ui_description" msgid="934736855340147968">"Отфрлете ја сликата од екранот"</string>
<string name="screenshot_preview_description" msgid="7606510140714080474">"Преглед на слика од екранот"</string>
<string name="screenrecord_name" msgid="2596401223859996572">"Снимач на екран"</string>
@@ -1065,8 +1064,7 @@
<string name="controls_seeding_in_progress" msgid="3033855341410264148">"Се вчитуваат препораки"</string>
<string name="controls_media_title" msgid="1746947284862928133">"Аудиовизуелни содржини"</string>
<string name="controls_media_close_session" msgid="3957093425905475065">"Сокриј ја тековнава сесија."</string>
- <!-- no translation found for controls_media_active_session (1984383994625845642) -->
- <skip />
+ <string name="controls_media_active_session" msgid="1984383994625845642">"Тековната сесија не може да се сокрие."</string>
<string name="controls_media_dismiss_button" msgid="9081375542265132213">"Отфрли"</string>
<string name="controls_media_resume" msgid="1933520684481586053">"Продолжи"</string>
<string name="controls_media_settings_button" msgid="5815790345117172504">"Поставки"</string>
diff --git a/packages/SystemUI/res/values-ml/strings.xml b/packages/SystemUI/res/values-ml/strings.xml
index f94264103549..2a6ed6e9bf65 100644
--- a/packages/SystemUI/res/values-ml/strings.xml
+++ b/packages/SystemUI/res/values-ml/strings.xml
@@ -86,8 +86,7 @@
<string name="screenshot_failed_to_save_unknown_text" msgid="1506621600548684129">"സ്‌ക്രീൻഷോട്ട് എടുക്കാൻ വീണ്ടും ശ്രമിക്കുക"</string>
<string name="screenshot_failed_to_save_text" msgid="8344173457344027501">"സ്‌റ്റോറേജ് ഇടം പരിമിതമായതിനാൽ സ്‌ക്രീൻഷോട്ട് സംരക്ഷിക്കാനാകുന്നില്ല"</string>
<string name="screenshot_failed_to_capture_text" msgid="7818288545874407451">"സ്ക്രീൻഷോട്ടുകൾ എടുക്കുന്നത് ആപ്പോ നിങ്ങളുടെ സ്ഥാപനമോ അനുവദിക്കുന്നില്ല"</string>
- <!-- no translation found for screenshot_edit (3510496440489019191) -->
- <skip />
+ <string name="screenshot_edit" msgid="3510496440489019191">"സ്ക്രീൻഷോട്ട് എഡിറ്റ് ചെയ്യുക"</string>
<string name="screenshot_dismiss_ui_description" msgid="934736855340147968">"സ്ക്രീൻഷോട്ട് ഡിസ്‌മിസ് ചെയ്യുക"</string>
<string name="screenshot_preview_description" msgid="7606510140714080474">"സ്‌ക്രീൻഷോട്ട് പ്രിവ്യു"</string>
<string name="screenrecord_name" msgid="2596401223859996572">"സ്ക്രീൻ റെക്കോർഡർ"</string>
@@ -1065,8 +1064,7 @@
<string name="controls_seeding_in_progress" msgid="3033855341410264148">"നിർദ്ദേശങ്ങൾ ലോഡ് ചെയ്യുന്നു"</string>
<string name="controls_media_title" msgid="1746947284862928133">"മീഡിയ"</string>
<string name="controls_media_close_session" msgid="3957093425905475065">"നിലവിലെ സെഷൻ മറയ്‌ക്കുക."</string>
- <!-- no translation found for controls_media_active_session (1984383994625845642) -->
- <skip />
+ <string name="controls_media_active_session" msgid="1984383994625845642">"നിലവിലെ സെഷൻ മറയ്ക്കാനാകില്ല."</string>
<string name="controls_media_dismiss_button" msgid="9081375542265132213">"ഡിസ്‌മിസ് ചെയ്യുക"</string>
<string name="controls_media_resume" msgid="1933520684481586053">"പുനരാരംഭിക്കുക"</string>
<string name="controls_media_settings_button" msgid="5815790345117172504">"ക്രമീകരണം"</string>
diff --git a/packages/SystemUI/res/values-mn/strings.xml b/packages/SystemUI/res/values-mn/strings.xml
index fc41f6cc0739..4eb2fb1076c3 100644
--- a/packages/SystemUI/res/values-mn/strings.xml
+++ b/packages/SystemUI/res/values-mn/strings.xml
@@ -86,8 +86,7 @@
<string name="screenshot_failed_to_save_unknown_text" msgid="1506621600548684129">"Дэлгэцийн зургийг дахин дарж үзнэ үү"</string>
<string name="screenshot_failed_to_save_text" msgid="8344173457344027501">"Сангийн багтаамж бага байгаа тул дэлгэцээс дарсан зургийг хадгалах боломжгүй байна"</string>
<string name="screenshot_failed_to_capture_text" msgid="7818288545874407451">"Таны апп, байгууллагад дэлгэцийн зураг авахыг зөвшөөрдөггүй"</string>
- <!-- no translation found for screenshot_edit (3510496440489019191) -->
- <skip />
+ <string name="screenshot_edit" msgid="3510496440489019191">"Дэлгэцийн агшныг засах"</string>
<string name="screenshot_dismiss_ui_description" msgid="934736855340147968">"Дэлгэцийн агшныг хаах"</string>
<string name="screenshot_preview_description" msgid="7606510140714080474">"Дэлгэцийн агшныг урьдчилан үзэх"</string>
<string name="screenrecord_name" msgid="2596401223859996572">"Дэлгэцийн үйлдэл бичигч"</string>
@@ -1065,8 +1064,7 @@
<string name="controls_seeding_in_progress" msgid="3033855341410264148">"Зөвлөмжүүдийг ачаалж байна"</string>
<string name="controls_media_title" msgid="1746947284862928133">"Медиа"</string>
<string name="controls_media_close_session" msgid="3957093425905475065">"Одоогийн харилцан үйлдлийг нуугаарай."</string>
- <!-- no translation found for controls_media_active_session (1984383994625845642) -->
- <skip />
+ <string name="controls_media_active_session" msgid="1984383994625845642">"Одоогийн харилцан үйлдлийг нуух боломжгүй."</string>
<string name="controls_media_dismiss_button" msgid="9081375542265132213">"Хаах"</string>
<string name="controls_media_resume" msgid="1933520684481586053">"Үргэлжлүүлэх"</string>
<string name="controls_media_settings_button" msgid="5815790345117172504">"Тохиргоо"</string>
diff --git a/packages/SystemUI/res/values-mr/strings.xml b/packages/SystemUI/res/values-mr/strings.xml
index 2b01fef142bd..57c1e07d3802 100644
--- a/packages/SystemUI/res/values-mr/strings.xml
+++ b/packages/SystemUI/res/values-mr/strings.xml
@@ -86,8 +86,7 @@
<string name="screenshot_failed_to_save_unknown_text" msgid="1506621600548684129">"स्क्रीनशॉट पुन्हा घेण्याचा प्रयत्न करा"</string>
<string name="screenshot_failed_to_save_text" msgid="8344173457344027501">"मर्यादित स्टोरेज जागेमुळे स्क्रीनशॉट सेव्ह करू शकत नाही"</string>
<string name="screenshot_failed_to_capture_text" msgid="7818288545874407451">"अ‍ॅप किंवा आपल्या संस्थेद्वारे स्क्रीनशॉट घेण्याची अनुमती नाही"</string>
- <!-- no translation found for screenshot_edit (3510496440489019191) -->
- <skip />
+ <string name="screenshot_edit" msgid="3510496440489019191">"स्क्रीनशॉट संपादित करा"</string>
<string name="screenshot_dismiss_ui_description" msgid="934736855340147968">"स्क्रीनशॉट डिसमिस करा"</string>
<string name="screenshot_preview_description" msgid="7606510140714080474">"स्क्रीनशॉटचे पूर्वावलोकन"</string>
<string name="screenrecord_name" msgid="2596401223859996572">"स्क्रीन रेकॉर्डर"</string>
@@ -115,10 +114,10 @@
<string name="screenrecord_delete_error" msgid="2870506119743013588">"स्क्रीन रेकॉर्डिंग हटवताना एरर आली"</string>
<string name="screenrecord_permission_error" msgid="7856841237023137686">"परवानग्या मिळवता आल्या नाहीत"</string>
<string name="screenrecord_start_error" msgid="2200660692479682368">"स्क्रीन रेकॉर्डिंग सुरू करताना एरर आली"</string>
- <string name="usb_preference_title" msgid="1439924437558480718">"USB फाईल स्थानांतरण पर्याय"</string>
+ <string name="usb_preference_title" msgid="1439924437558480718">"USB फाइल स्थानांतरण पर्याय"</string>
<string name="use_mtp_button_title" msgid="5036082897886518086">"मीडिया प्लेअर म्हणून माउंट करा (MTP)"</string>
<string name="use_ptp_button_title" msgid="7676427598943446826">"कॅमेरा म्हणून माउंट करा (PTP)"</string>
- <string name="installer_cd_button_title" msgid="5499998592841984743">"Mac साठी Android फाईल स्थानांतर अ‍ॅप इंस्टॉल करा"</string>
+ <string name="installer_cd_button_title" msgid="5499998592841984743">"Mac साठी Android फाइल स्थानांतर अ‍ॅप इंस्टॉल करा"</string>
<string name="accessibility_back" msgid="6530104400086152611">"मागे"</string>
<string name="accessibility_home" msgid="5430449841237966217">"होम"</string>
<string name="accessibility_menu" msgid="2701163794470513040">"मेनू"</string>
@@ -290,7 +289,7 @@
<string name="accessibility_quick_settings_location_changed_off" msgid="5132776369388699133">"स्थान अहवाल बंद केला."</string>
<string name="accessibility_quick_settings_location_changed_on" msgid="7159115433070112154">"स्थान अहवाल सुरू केला."</string>
<string name="accessibility_quick_settings_alarm" msgid="558094529584082090">"<xliff:g id="TIME">%s</xliff:g> साठी अलार्म सेट केला."</string>
- <string name="accessibility_quick_settings_close" msgid="2974895537860082341">"पॅनेल बंद करा."</string>
+ <string name="accessibility_quick_settings_close" msgid="2974895537860082341">"पॅनल बंद करा."</string>
<string name="accessibility_quick_settings_more_time" msgid="7646479831704665284">"अधिक वेळ."</string>
<string name="accessibility_quick_settings_less_time" msgid="9110364286464977870">"कमी वेळ."</string>
<string name="accessibility_quick_settings_flashlight_off" msgid="7606563260714825190">"फ्लॅशलाइट बंद."</string>
@@ -626,10 +625,10 @@
<string name="qs_status_phone_vibrate" msgid="7055409506885541979">"फोन व्हायब्रेटवर आहे"</string>
<string name="qs_status_phone_muted" msgid="3763664791309544103">"फोन म्यूट केला"</string>
<string name="volume_stream_content_description_unmute" msgid="7729576371406792977">"%1$s. सशब्द करण्यासाठी टॅप करा."</string>
- <string name="volume_stream_content_description_vibrate" msgid="4858111994183089761">"%1$s. व्हायब्रेट सेट करण्यासाठी टॅप करा. प्रवेशयोग्यता सेवा नि:शब्द केल्या जाऊ शकतात."</string>
- <string name="volume_stream_content_description_mute" msgid="4079046784917920984">"%1$s. नि:शब्द करण्यासाठी टॅप करा. प्रवेशक्षमता सेवा नि:शब्द केल्या जाऊ शकतात."</string>
+ <string name="volume_stream_content_description_vibrate" msgid="4858111994183089761">"%1$s. व्हायब्रेट सेट करण्यासाठी टॅप करा. प्रवेशयोग्यता सेवा म्यूट केल्या जाऊ शकतात."</string>
+ <string name="volume_stream_content_description_mute" msgid="4079046784917920984">"%1$s. म्यूट करण्यासाठी टॅप करा. प्रवेशक्षमता सेवा म्यूट केल्या जाऊ शकतात."</string>
<string name="volume_stream_content_description_vibrate_a11y" msgid="2742330052979397471">"%1$s. व्हायब्रेट सेट करण्यासाठी टॅप करा."</string>
- <string name="volume_stream_content_description_mute_a11y" msgid="5743548478357238156">"%1$s. नि:शब्द करण्यासाठी टॅप करा."</string>
+ <string name="volume_stream_content_description_mute_a11y" msgid="5743548478357238156">"%1$s. म्यूट करण्यासाठी टॅप करा."</string>
<string name="volume_ringer_hint_mute" msgid="4263821214125126614">"म्यूट करा"</string>
<string name="volume_ringer_hint_unmute" msgid="6119086890306456976">"म्यूट काढून टाका"</string>
<string name="volume_ringer_hint_vibrate" msgid="6211609047099337509">"व्हायब्रेट करा"</string>
@@ -1065,8 +1064,7 @@
<string name="controls_seeding_in_progress" msgid="3033855341410264148">"शिफारशी लोड करत आहे"</string>
<string name="controls_media_title" msgid="1746947284862928133">"मीडिया"</string>
<string name="controls_media_close_session" msgid="3957093425905475065">"सध्याचे सेशन लपवा."</string>
- <!-- no translation found for controls_media_active_session (1984383994625845642) -->
- <skip />
+ <string name="controls_media_active_session" msgid="1984383994625845642">"सध्याचे सेशन लपवता येणार नाही."</string>
<string name="controls_media_dismiss_button" msgid="9081375542265132213">"डिसमिस करा"</string>
<string name="controls_media_resume" msgid="1933520684481586053">"पुन्हा सुरू करा"</string>
<string name="controls_media_settings_button" msgid="5815790345117172504">"सेटिंग्ज"</string>
diff --git a/packages/SystemUI/res/values-ms/strings.xml b/packages/SystemUI/res/values-ms/strings.xml
index 5b0f91f5f967..058055f54c95 100644
--- a/packages/SystemUI/res/values-ms/strings.xml
+++ b/packages/SystemUI/res/values-ms/strings.xml
@@ -86,8 +86,7 @@
<string name="screenshot_failed_to_save_unknown_text" msgid="1506621600548684129">"Cuba ambil tangkapan skrin sekali lagi"</string>
<string name="screenshot_failed_to_save_text" msgid="8344173457344027501">"Tidak dapat menyimpan tangkapan skrin kerana ruang storan terhad"</string>
<string name="screenshot_failed_to_capture_text" msgid="7818288545874407451">"Pengambilan tangkapan skrin tidak dibenarkan oleh apl atau organisasi anda"</string>
- <!-- no translation found for screenshot_edit (3510496440489019191) -->
- <skip />
+ <string name="screenshot_edit" msgid="3510496440489019191">"Edit tangkapan skrin"</string>
<string name="screenshot_dismiss_ui_description" msgid="934736855340147968">"Ketepikan tangkapan skrin"</string>
<string name="screenshot_preview_description" msgid="7606510140714080474">"Pratonton tangkapan skrin"</string>
<string name="screenrecord_name" msgid="2596401223859996572">"Perakam Skrin"</string>
@@ -1065,8 +1064,7 @@
<string name="controls_seeding_in_progress" msgid="3033855341410264148">"Memuatkan cadangan"</string>
<string name="controls_media_title" msgid="1746947284862928133">"Media"</string>
<string name="controls_media_close_session" msgid="3957093425905475065">"Sembunyikan sesi semasa."</string>
- <!-- no translation found for controls_media_active_session (1984383994625845642) -->
- <skip />
+ <string name="controls_media_active_session" msgid="1984383994625845642">"Sesi semasa tidak boleh disembunyikan."</string>
<string name="controls_media_dismiss_button" msgid="9081375542265132213">"Tolak"</string>
<string name="controls_media_resume" msgid="1933520684481586053">"Sambung semula"</string>
<string name="controls_media_settings_button" msgid="5815790345117172504">"Tetapan"</string>
diff --git a/packages/SystemUI/res/values-my/strings.xml b/packages/SystemUI/res/values-my/strings.xml
index b814607226e3..5249efa4d48e 100644
--- a/packages/SystemUI/res/values-my/strings.xml
+++ b/packages/SystemUI/res/values-my/strings.xml
@@ -86,8 +86,7 @@
<string name="screenshot_failed_to_save_unknown_text" msgid="1506621600548684129">"မျက်နှာပြင်ပုံကို ထပ်ရိုက်ကြည့်ပါ"</string>
<string name="screenshot_failed_to_save_text" msgid="8344173457344027501">"သိုလှောင်ခန်းနေရာ အကန့်အသတ်ရှိသောကြောင့် ဖန်သားပြင်ဓာတ်ပုံကို သိမ်းဆည်း၍မရပါ"</string>
<string name="screenshot_failed_to_capture_text" msgid="7818288545874407451">"ဖန်သားပြင်ဓာတ်ပုံရိုက်ကူးခြင်းကို ဤအက်ပ် သို့မဟုတ် သင်၏အဖွဲ့အစည်းက ခွင့်မပြုပါ"</string>
- <!-- no translation found for screenshot_edit (3510496440489019191) -->
- <skip />
+ <string name="screenshot_edit" msgid="3510496440489019191">"ဖန်သားပြင်ဓာတ်ပုံကို တည်းဖြတ်သည်"</string>
<string name="screenshot_dismiss_ui_description" msgid="934736855340147968">"ဖန်သားပြင်ဓာတ်ပုံ ပယ်ရန်"</string>
<string name="screenshot_preview_description" msgid="7606510140714080474">"ဖန်သားပြင်ဓာတ်ပုံ အစမ်းကြည့်ရှုခြင်း"</string>
<string name="screenrecord_name" msgid="2596401223859996572">"ဖန်သားပြင် ရိုက်ကူးမှု"</string>
@@ -1065,8 +1064,7 @@
<string name="controls_seeding_in_progress" msgid="3033855341410264148">"အကြံပြုချက်များ ဖွင့်နေသည်"</string>
<string name="controls_media_title" msgid="1746947284862928133">"မီဒီယာ"</string>
<string name="controls_media_close_session" msgid="3957093425905475065">"လက်ရှိ စက်ရှင်ကို ဖျောက်ထားမည်။"</string>
- <!-- no translation found for controls_media_active_session (1984383994625845642) -->
- <skip />
+ <string name="controls_media_active_session" msgid="1984383994625845642">"လက်ရှိစက်ရှင်ကို ဝှက်၍မရနိုင်ပါ။"</string>
<string name="controls_media_dismiss_button" msgid="9081375542265132213">"ပယ်ရန်"</string>
<string name="controls_media_resume" msgid="1933520684481586053">"ဆက်လုပ်ရန်"</string>
<string name="controls_media_settings_button" msgid="5815790345117172504">"ဆက်တင်များ"</string>
diff --git a/packages/SystemUI/res/values-ne/strings.xml b/packages/SystemUI/res/values-ne/strings.xml
index 5eea7fd4abb1..c3c8903c809c 100644
--- a/packages/SystemUI/res/values-ne/strings.xml
+++ b/packages/SystemUI/res/values-ne/strings.xml
@@ -86,8 +86,7 @@
<string name="screenshot_failed_to_save_unknown_text" msgid="1506621600548684129">"स्क्रिनसट फेरि लिएर हेर्नुहोस्"</string>
<string name="screenshot_failed_to_save_text" msgid="8344173457344027501">"भण्डारण ठाउँ सीमित भएका कारण स्क्रिनसट सुरक्षित गर्न सकिएन"</string>
<string name="screenshot_failed_to_capture_text" msgid="7818288545874407451">"उक्त एप वा तपाईंको संगठनले स्क्रिनसटहरू लिन दिँदैन"</string>
- <!-- no translation found for screenshot_edit (3510496440489019191) -->
- <skip />
+ <string name="screenshot_edit" msgid="3510496440489019191">"स्क्रिनसट सम्पादन गर्नुहोस्"</string>
<string name="screenshot_dismiss_ui_description" msgid="934736855340147968">"स्क्रिनसट हटाउनुहोस्"</string>
<string name="screenshot_preview_description" msgid="7606510140714080474">"स्क्रिनसटको पूर्वावलोकन"</string>
<string name="screenrecord_name" msgid="2596401223859996572">"स्क्रिन रेकर्डर"</string>
@@ -1065,8 +1064,7 @@
<string name="controls_seeding_in_progress" msgid="3033855341410264148">"सिफारिसहरू लोड गर्दै"</string>
<string name="controls_media_title" msgid="1746947284862928133">"मिडिया"</string>
<string name="controls_media_close_session" msgid="3957093425905475065">"हालको सत्र लुकाउनुहोस्।"</string>
- <!-- no translation found for controls_media_active_session (1984383994625845642) -->
- <skip />
+ <string name="controls_media_active_session" msgid="1984383994625845642">"हाल चलिरहेको सत्र लुकाउन सकिँदैन।"</string>
<string name="controls_media_dismiss_button" msgid="9081375542265132213">"हटाउनुहोस्"</string>
<string name="controls_media_resume" msgid="1933520684481586053">"सुचारु गर्नुहोस्"</string>
<string name="controls_media_settings_button" msgid="5815790345117172504">"सेटिङ"</string>
diff --git a/packages/SystemUI/res/values-nl/strings.xml b/packages/SystemUI/res/values-nl/strings.xml
index 2126b1a451f7..691bfcbc57f7 100644
--- a/packages/SystemUI/res/values-nl/strings.xml
+++ b/packages/SystemUI/res/values-nl/strings.xml
@@ -86,8 +86,7 @@
<string name="screenshot_failed_to_save_unknown_text" msgid="1506621600548684129">"Probeer opnieuw een screenshot te maken"</string>
<string name="screenshot_failed_to_save_text" msgid="8344173457344027501">"Kan screenshot niet opslaan vanwege beperkte opslagruimte"</string>
<string name="screenshot_failed_to_capture_text" msgid="7818288545874407451">"Het maken van screenshots wordt niet toegestaan door de app of je organisatie"</string>
- <!-- no translation found for screenshot_edit (3510496440489019191) -->
- <skip />
+ <string name="screenshot_edit" msgid="3510496440489019191">"Screenshot bewerken"</string>
<string name="screenshot_dismiss_ui_description" msgid="934736855340147968">"Screenshot sluiten"</string>
<string name="screenshot_preview_description" msgid="7606510140714080474">"Voorbeeld van screenshot"</string>
<string name="screenrecord_name" msgid="2596401223859996572">"Schermopname"</string>
@@ -1065,8 +1064,7 @@
<string name="controls_seeding_in_progress" msgid="3033855341410264148">"Aanbevelingen laden"</string>
<string name="controls_media_title" msgid="1746947284862928133">"Media"</string>
<string name="controls_media_close_session" msgid="3957093425905475065">"De huidige sessie verbergen."</string>
- <!-- no translation found for controls_media_active_session (1984383994625845642) -->
- <skip />
+ <string name="controls_media_active_session" msgid="1984383994625845642">"De huidige sessie kan niet worden verborgen."</string>
<string name="controls_media_dismiss_button" msgid="9081375542265132213">"Sluiten"</string>
<string name="controls_media_resume" msgid="1933520684481586053">"Hervatten"</string>
<string name="controls_media_settings_button" msgid="5815790345117172504">"Instellingen"</string>
diff --git a/packages/SystemUI/res/values-or/strings.xml b/packages/SystemUI/res/values-or/strings.xml
index b55fd67ba6a1..de48527f1980 100644
--- a/packages/SystemUI/res/values-or/strings.xml
+++ b/packages/SystemUI/res/values-or/strings.xml
@@ -86,8 +86,7 @@
<string name="screenshot_failed_to_save_unknown_text" msgid="1506621600548684129">"ପୁଣିଥରେ ସ୍କ୍ରୀନ୍‌ଶଟ୍ ନେବାକୁ ଚେଷ୍ଟା କରନ୍ତୁ"</string>
<string name="screenshot_failed_to_save_text" msgid="8344173457344027501">"ସୀମିତ ଷ୍ଟୋରେଜ୍‍ ସ୍ପେସ୍‍ ହେତୁ ସ୍କ୍ରୀନଶଟ୍‍ ସେଭ୍‍ ହୋଇପାରିବ ନାହିଁ"</string>
<string name="screenshot_failed_to_capture_text" msgid="7818288545874407451">"ଆପ୍‍ କିମ୍ବା ସଂସ୍ଥା ଦ୍ୱାରା ସ୍କ୍ରୀନଶଟ୍‍ ନେବାକୁ ଅନୁମତି ଦିଆଯାଇ ନାହିଁ"</string>
- <!-- no translation found for screenshot_edit (3510496440489019191) -->
- <skip />
+ <string name="screenshot_edit" msgid="3510496440489019191">"ସ୍କ୍ରିନସଟକୁ ଏଡିଟ୍ କରନ୍ତୁ"</string>
<string name="screenshot_dismiss_ui_description" msgid="934736855340147968">"ସ୍କ୍ରିନସଟ୍ ଖାରଜ କରନ୍ତୁ"</string>
<string name="screenshot_preview_description" msgid="7606510140714080474">"ସ୍କ୍ରିନସଟର ପ୍ରିଭ୍ୟୁ"</string>
<string name="screenrecord_name" msgid="2596401223859996572">"ସ୍କ୍ରିନ୍ ରେକର୍ଡର୍"</string>
@@ -1065,8 +1064,7 @@
<string name="controls_seeding_in_progress" msgid="3033855341410264148">"ସୁପାରିଶଗୁଡ଼ିକ ଲୋଡ୍ କରାଯାଉଛି"</string>
<string name="controls_media_title" msgid="1746947284862928133">"ମିଡିଆ"</string>
<string name="controls_media_close_session" msgid="3957093425905475065">"ବର୍ତ୍ତମାନର ସେସନ୍ ଲୁଚାନ୍ତୁ।"</string>
- <!-- no translation found for controls_media_active_session (1984383994625845642) -->
- <skip />
+ <string name="controls_media_active_session" msgid="1984383994625845642">"ବର୍ତ୍ତମାନର ସେସନକୁ ଲୁଚାଯାଇପାରିବ ନାହିଁ।"</string>
<string name="controls_media_dismiss_button" msgid="9081375542265132213">"ଖାରଜ କରନ୍ତୁ"</string>
<string name="controls_media_resume" msgid="1933520684481586053">"ପୁଣି ଆରମ୍ଭ କରନ୍ତୁ"</string>
<string name="controls_media_settings_button" msgid="5815790345117172504">"ସେଟିଂସ୍"</string>
diff --git a/packages/SystemUI/res/values-pa/strings.xml b/packages/SystemUI/res/values-pa/strings.xml
index 9714f34ab0cc..13f45067ce7a 100644
--- a/packages/SystemUI/res/values-pa/strings.xml
+++ b/packages/SystemUI/res/values-pa/strings.xml
@@ -86,8 +86,7 @@
<string name="screenshot_failed_to_save_unknown_text" msgid="1506621600548684129">"ਸਕ੍ਰੀਨਸ਼ਾਟ ਦੁਬਾਰਾ ਲੈ ਕੇ ਦੇਖੋ"</string>
<string name="screenshot_failed_to_save_text" msgid="8344173457344027501">"ਸੀਮਿਤ ਸਟੋਰੇਜ ਹੋਣ ਕਾਰਨ ਸਕ੍ਰੀਨਸ਼ਾਟ ਰੱਖਿਅਤ ਨਹੀਂ ਕੀਤਾ ਜਾ ਸਕਦਾ"</string>
<string name="screenshot_failed_to_capture_text" msgid="7818288545874407451">"ਐਪ ਜਾਂ ਤੁਹਾਡੀ ਸੰਸਥਾ ਵੱਲੋਂ ਸਕ੍ਰੀਨਸ਼ਾਟ ਲੈਣ ਦੀ ਇਜਾਜ਼ਤ ਨਹੀਂ ਦਿੱਤੀ ਗਈ ਹੈ"</string>
- <!-- no translation found for screenshot_edit (3510496440489019191) -->
- <skip />
+ <string name="screenshot_edit" msgid="3510496440489019191">"ਸਕ੍ਰੀਨਸ਼ਾਟ ਦਾ ਸੰਪਾਦਨ ਕਰੋ"</string>
<string name="screenshot_dismiss_ui_description" msgid="934736855340147968">"ਸਕ੍ਰੀਨਸ਼ਾਟ ਖਾਰਜ ਕਰੋ"</string>
<string name="screenshot_preview_description" msgid="7606510140714080474">"ਸਕ੍ਰੀਨਸ਼ਾਟ ਪੂਰਵ-ਝਲਕ"</string>
<string name="screenrecord_name" msgid="2596401223859996572">"ਸਕ੍ਰੀਨ ਰਿਕਾਰਡਰ"</string>
@@ -1065,8 +1064,7 @@
<string name="controls_seeding_in_progress" msgid="3033855341410264148">"ਸਿਫ਼ਾਰਸ਼ਾਂ ਲੋਡ ਹੋ ਰਹੀਆਂ ਹਨ"</string>
<string name="controls_media_title" msgid="1746947284862928133">"ਮੀਡੀਆ"</string>
<string name="controls_media_close_session" msgid="3957093425905475065">"ਮੌਜੂਦਾ ਸੈਸ਼ਨ ਨੂੰ ਲੁਕਾਓ।"</string>
- <!-- no translation found for controls_media_active_session (1984383994625845642) -->
- <skip />
+ <string name="controls_media_active_session" msgid="1984383994625845642">"ਮੌਜੂਦਾ ਸੈਸ਼ਨ ਨੂੰ ਲੁਕਾਇਆ ਨਹੀਂ ਜਾ ਸਕਦਾ।"</string>
<string name="controls_media_dismiss_button" msgid="9081375542265132213">"ਖਾਰਜ ਕਰੋ"</string>
<string name="controls_media_resume" msgid="1933520684481586053">"ਮੁੜ-ਚਾਲੂ ਕਰੋ"</string>
<string name="controls_media_settings_button" msgid="5815790345117172504">"ਸੈਟਿੰਗਾਂ"</string>
diff --git a/packages/SystemUI/res/values-pl/strings.xml b/packages/SystemUI/res/values-pl/strings.xml
index f5bcdba5cede..6da167dffd34 100644
--- a/packages/SystemUI/res/values-pl/strings.xml
+++ b/packages/SystemUI/res/values-pl/strings.xml
@@ -86,8 +86,7 @@
<string name="screenshot_failed_to_save_unknown_text" msgid="1506621600548684129">"Spróbuj jeszcze raz wykonać zrzut ekranu"</string>
<string name="screenshot_failed_to_save_text" msgid="8344173457344027501">"Nie można zapisać zrzutu ekranu, bo brakuje miejsca w pamięci"</string>
<string name="screenshot_failed_to_capture_text" msgid="7818288545874407451">"Nie możesz wykonać zrzutu ekranu, bo nie zezwala na to aplikacja lub Twoja organizacja."</string>
- <!-- no translation found for screenshot_edit (3510496440489019191) -->
- <skip />
+ <string name="screenshot_edit" msgid="3510496440489019191">"Edytuj zrzut ekranu"</string>
<string name="screenshot_dismiss_ui_description" msgid="934736855340147968">"Zamknij zrzut ekranu"</string>
<string name="screenshot_preview_description" msgid="7606510140714080474">"Podgląd zrzutu ekranu"</string>
<string name="screenrecord_name" msgid="2596401223859996572">"Nagrywanie ekranu"</string>
@@ -1077,8 +1076,7 @@
<string name="controls_seeding_in_progress" msgid="3033855341410264148">"Wczytuję rekomendacje"</string>
<string name="controls_media_title" msgid="1746947284862928133">"Multimedia"</string>
<string name="controls_media_close_session" msgid="3957093425905475065">"Ukryj bieżącą sesję."</string>
- <!-- no translation found for controls_media_active_session (1984383994625845642) -->
- <skip />
+ <string name="controls_media_active_session" msgid="1984383994625845642">"Nie można ukryć bieżącej sesji."</string>
<string name="controls_media_dismiss_button" msgid="9081375542265132213">"Odrzuć"</string>
<string name="controls_media_resume" msgid="1933520684481586053">"Wznów"</string>
<string name="controls_media_settings_button" msgid="5815790345117172504">"Ustawienia"</string>
diff --git a/packages/SystemUI/res/values-ro/strings.xml b/packages/SystemUI/res/values-ro/strings.xml
index 9c73e5a1fcfd..24e71fbe1392 100644
--- a/packages/SystemUI/res/values-ro/strings.xml
+++ b/packages/SystemUI/res/values-ro/strings.xml
@@ -86,8 +86,7 @@
<string name="screenshot_failed_to_save_unknown_text" msgid="1506621600548684129">"Încercați să faceți din nou o captură de ecran"</string>
<string name="screenshot_failed_to_save_text" msgid="8344173457344027501">"Captura de ecran nu poate fi salvată din cauza spațiului de stocare limitat"</string>
<string name="screenshot_failed_to_capture_text" msgid="7818288545874407451">"Crearea capturilor de ecran nu este permisă de aplicație sau de organizația dvs."</string>
- <!-- no translation found for screenshot_edit (3510496440489019191) -->
- <skip />
+ <string name="screenshot_edit" msgid="3510496440489019191">"Editați captura de ecran"</string>
<string name="screenshot_dismiss_ui_description" msgid="934736855340147968">"Închideți captura de ecran"</string>
<string name="screenshot_preview_description" msgid="7606510140714080474">"Previzualizare a capturii de ecran"</string>
<string name="screenrecord_name" msgid="2596401223859996572">"Recorder pentru ecran"</string>
@@ -1071,8 +1070,7 @@
<string name="controls_seeding_in_progress" msgid="3033855341410264148">"Se încarcă recomandările"</string>
<string name="controls_media_title" msgid="1746947284862928133">"Media"</string>
<string name="controls_media_close_session" msgid="3957093425905475065">"Ascunde sesiunea actuală."</string>
- <!-- no translation found for controls_media_active_session (1984383994625845642) -->
- <skip />
+ <string name="controls_media_active_session" msgid="1984383994625845642">"Sesiunea actuală nu se poate ascunde."</string>
<string name="controls_media_dismiss_button" msgid="9081375542265132213">"Închideți"</string>
<string name="controls_media_resume" msgid="1933520684481586053">"Reia"</string>
<string name="controls_media_settings_button" msgid="5815790345117172504">"Setări"</string>
diff --git a/packages/SystemUI/res/values-ru/strings.xml b/packages/SystemUI/res/values-ru/strings.xml
index b51a5b2d1644..1ca1c80738c2 100644
--- a/packages/SystemUI/res/values-ru/strings.xml
+++ b/packages/SystemUI/res/values-ru/strings.xml
@@ -86,8 +86,7 @@
<string name="screenshot_failed_to_save_unknown_text" msgid="1506621600548684129">"Попробуйте сделать скриншот снова."</string>
<string name="screenshot_failed_to_save_text" msgid="8344173457344027501">"Не удалось сохранить скриншот: недостаточно места."</string>
<string name="screenshot_failed_to_capture_text" msgid="7818288545874407451">"Не удалось сделать скриншот: нет разрешения от приложения или организации."</string>
- <!-- no translation found for screenshot_edit (3510496440489019191) -->
- <skip />
+ <string name="screenshot_edit" msgid="3510496440489019191">"Изменить скриншот"</string>
<string name="screenshot_dismiss_ui_description" msgid="934736855340147968">"Закрыть скриншот"</string>
<string name="screenshot_preview_description" msgid="7606510140714080474">"Предварительный просмотр скриншота"</string>
<string name="screenrecord_name" msgid="2596401223859996572">"Запись видео с экрана"</string>
@@ -1077,8 +1076,7 @@
<string name="controls_seeding_in_progress" msgid="3033855341410264148">"Загрузка рекомендаций…"</string>
<string name="controls_media_title" msgid="1746947284862928133">"Медиа"</string>
<string name="controls_media_close_session" msgid="3957093425905475065">"Скрыть текущий сеанс?"</string>
- <!-- no translation found for controls_media_active_session (1984383994625845642) -->
- <skip />
+ <string name="controls_media_active_session" msgid="1984383994625845642">"Скрыть текущий сеанс нельзя."</string>
<string name="controls_media_dismiss_button" msgid="9081375542265132213">"Скрыть"</string>
<string name="controls_media_resume" msgid="1933520684481586053">"Возобновить"</string>
<string name="controls_media_settings_button" msgid="5815790345117172504">"Настройки"</string>
diff --git a/packages/SystemUI/res/values-si/strings.xml b/packages/SystemUI/res/values-si/strings.xml
index 5d019e949a17..eb789c1e9181 100644
--- a/packages/SystemUI/res/values-si/strings.xml
+++ b/packages/SystemUI/res/values-si/strings.xml
@@ -86,8 +86,7 @@
<string name="screenshot_failed_to_save_unknown_text" msgid="1506621600548684129">"තිර රුව නැවත ගැනීමට උත්සාහ කරන්න"</string>
<string name="screenshot_failed_to_save_text" msgid="8344173457344027501">"සීමිත ගබඩා ඉඩ නිසා තිර රුව සුරැකිය නොහැකිය"</string>
<string name="screenshot_failed_to_capture_text" msgid="7818288545874407451">"තිර රූ ගැනීමට යෙදුම හෝ ඔබගේ සංවිධානය ඉඩ නොදේ"</string>
- <!-- no translation found for screenshot_edit (3510496440489019191) -->
- <skip />
+ <string name="screenshot_edit" msgid="3510496440489019191">"තිර රුව සංස්කරණය කරන්න"</string>
<string name="screenshot_dismiss_ui_description" msgid="934736855340147968">"තිර රුව ඉවත ලන්න"</string>
<string name="screenshot_preview_description" msgid="7606510140714080474">"තිර රූ පෙර දසුන"</string>
<string name="screenrecord_name" msgid="2596401223859996572">"තිර රෙකෝඩරය"</string>
@@ -1065,8 +1064,7 @@
<string name="controls_seeding_in_progress" msgid="3033855341410264148">"නිර්දේශ පූරණය කරමින්"</string>
<string name="controls_media_title" msgid="1746947284862928133">"මාධ්‍ය"</string>
<string name="controls_media_close_session" msgid="3957093425905475065">"වත්මන් සැසිය සඟවන්න."</string>
- <!-- no translation found for controls_media_active_session (1984383994625845642) -->
- <skip />
+ <string name="controls_media_active_session" msgid="1984383994625845642">"වත්මන් සැසිය සැඟවිය නොහැකිය."</string>
<string name="controls_media_dismiss_button" msgid="9081375542265132213">"ඉවත ලන්න"</string>
<string name="controls_media_resume" msgid="1933520684481586053">"නැවත පටන් ගන්න"</string>
<string name="controls_media_settings_button" msgid="5815790345117172504">"සැකසීම්"</string>
diff --git a/packages/SystemUI/res/values-sk/strings.xml b/packages/SystemUI/res/values-sk/strings.xml
index 88cc1a2cab60..9ec0771c89f9 100644
--- a/packages/SystemUI/res/values-sk/strings.xml
+++ b/packages/SystemUI/res/values-sk/strings.xml
@@ -86,8 +86,7 @@
<string name="screenshot_failed_to_save_unknown_text" msgid="1506621600548684129">"Skúste snímku urobiť znova"</string>
<string name="screenshot_failed_to_save_text" msgid="8344173457344027501">"Snímka obrazovky sa nedá uložiť z dôvodu nedostatku miesta v úložisku"</string>
<string name="screenshot_failed_to_capture_text" msgid="7818288545874407451">"Vytváranie snímok obrazovky je zakázané aplikáciou alebo vašou organizáciou"</string>
- <!-- no translation found for screenshot_edit (3510496440489019191) -->
- <skip />
+ <string name="screenshot_edit" msgid="3510496440489019191">"Upraviť snímku obrazovky"</string>
<string name="screenshot_dismiss_ui_description" msgid="934736855340147968">"Zavrieť snímku obrazovky"</string>
<string name="screenshot_preview_description" msgid="7606510140714080474">"Ukážka snímky obrazovky"</string>
<string name="screenrecord_name" msgid="2596401223859996572">"Rekordér obrazovky"</string>
@@ -1077,8 +1076,7 @@
<string name="controls_seeding_in_progress" msgid="3033855341410264148">"Načítavajú sa odporúčania"</string>
<string name="controls_media_title" msgid="1746947284862928133">"Médiá"</string>
<string name="controls_media_close_session" msgid="3957093425905475065">"Skryť aktuálnu reláciu."</string>
- <!-- no translation found for controls_media_active_session (1984383994625845642) -->
- <skip />
+ <string name="controls_media_active_session" msgid="1984383994625845642">"Aktuálnu reláciu nie je možné skryť."</string>
<string name="controls_media_dismiss_button" msgid="9081375542265132213">"Zavrieť"</string>
<string name="controls_media_resume" msgid="1933520684481586053">"Pokračovať"</string>
<string name="controls_media_settings_button" msgid="5815790345117172504">"Nastavenia"</string>
diff --git a/packages/SystemUI/res/values-sl/strings.xml b/packages/SystemUI/res/values-sl/strings.xml
index d1d14b26ebcf..14f6553ddcfc 100644
--- a/packages/SystemUI/res/values-sl/strings.xml
+++ b/packages/SystemUI/res/values-sl/strings.xml
@@ -86,8 +86,7 @@
<string name="screenshot_failed_to_save_unknown_text" msgid="1506621600548684129">"Poskusite znova ustvariti posnetek zaslona"</string>
<string name="screenshot_failed_to_save_text" msgid="8344173457344027501">"Shranjevanje posnetka zaslona ni mogoče zaradi omejenega prostora za shranjevanje"</string>
<string name="screenshot_failed_to_capture_text" msgid="7818288545874407451">"Aplikacija ali vaša organizacija ne dovoljuje posnetkov zaslona"</string>
- <!-- no translation found for screenshot_edit (3510496440489019191) -->
- <skip />
+ <string name="screenshot_edit" msgid="3510496440489019191">"Urejanje posnetka zaslona"</string>
<string name="screenshot_dismiss_ui_description" msgid="934736855340147968">"Opusti posnetek zaslona"</string>
<string name="screenshot_preview_description" msgid="7606510140714080474">"Predogled posnetka zaslona"</string>
<string name="screenrecord_name" msgid="2596401223859996572">"Snemalnik zaslona"</string>
@@ -1077,8 +1076,7 @@
<string name="controls_seeding_in_progress" msgid="3033855341410264148">"Nalaganje priporočil"</string>
<string name="controls_media_title" msgid="1746947284862928133">"Predstavnost"</string>
<string name="controls_media_close_session" msgid="3957093425905475065">"Skrije trenutno sejo."</string>
- <!-- no translation found for controls_media_active_session (1984383994625845642) -->
- <skip />
+ <string name="controls_media_active_session" msgid="1984383994625845642">"Trenutne seje ni mogoče skriti."</string>
<string name="controls_media_dismiss_button" msgid="9081375542265132213">"Opusti"</string>
<string name="controls_media_resume" msgid="1933520684481586053">"Nadaljuj"</string>
<string name="controls_media_settings_button" msgid="5815790345117172504">"Nastavitve"</string>
diff --git a/packages/SystemUI/res/values-sq/strings.xml b/packages/SystemUI/res/values-sq/strings.xml
index 8d79aa423691..87ca508d3893 100644
--- a/packages/SystemUI/res/values-sq/strings.xml
+++ b/packages/SystemUI/res/values-sq/strings.xml
@@ -86,8 +86,7 @@
<string name="screenshot_failed_to_save_unknown_text" msgid="1506621600548684129">"Provo ta nxjerrësh përsëri pamjen e ekranit"</string>
<string name="screenshot_failed_to_save_text" msgid="8344173457344027501">"Pamja e ekranit nuk mund të ruhet për shkak të hapësirës ruajtëse të kufizuar"</string>
<string name="screenshot_failed_to_capture_text" msgid="7818288545874407451">"Nxjerrja e pamjeve të ekranit nuk lejohet nga aplikacioni ose organizata jote."</string>
- <!-- no translation found for screenshot_edit (3510496440489019191) -->
- <skip />
+ <string name="screenshot_edit" msgid="3510496440489019191">"Modifiko pamjen e ekranit"</string>
<string name="screenshot_dismiss_ui_description" msgid="934736855340147968">"Hiq pamjen e ekranit"</string>
<string name="screenshot_preview_description" msgid="7606510140714080474">"Pamja paraprake e imazhit"</string>
<string name="screenrecord_name" msgid="2596401223859996572">"Regjistruesi i ekranit"</string>
@@ -1065,8 +1064,7 @@
<string name="controls_seeding_in_progress" msgid="3033855341410264148">"Po ngarkon rekomandimet"</string>
<string name="controls_media_title" msgid="1746947284862928133">"Media"</string>
<string name="controls_media_close_session" msgid="3957093425905475065">"Fshih sesionin aktual."</string>
- <!-- no translation found for controls_media_active_session (1984383994625845642) -->
- <skip />
+ <string name="controls_media_active_session" msgid="1984383994625845642">"Sesioni aktual nuk mund të fshihet."</string>
<string name="controls_media_dismiss_button" msgid="9081375542265132213">"Hiq"</string>
<string name="controls_media_resume" msgid="1933520684481586053">"Vazhdo"</string>
<string name="controls_media_settings_button" msgid="5815790345117172504">"Cilësimet"</string>
diff --git a/packages/SystemUI/res/values-sr/strings.xml b/packages/SystemUI/res/values-sr/strings.xml
index 5affcdfb31a0..cd958854f53e 100644
--- a/packages/SystemUI/res/values-sr/strings.xml
+++ b/packages/SystemUI/res/values-sr/strings.xml
@@ -86,8 +86,7 @@
<string name="screenshot_failed_to_save_unknown_text" msgid="1506621600548684129">"Пробајте да поново направите снимак екрана"</string>
<string name="screenshot_failed_to_save_text" msgid="8344173457344027501">"Чување снимка екрана није успело због ограниченог меморијског простора"</string>
<string name="screenshot_failed_to_capture_text" msgid="7818288545874407451">"Апликација или организација не дозвољавају прављење снимака екрана"</string>
- <!-- no translation found for screenshot_edit (3510496440489019191) -->
- <skip />
+ <string name="screenshot_edit" msgid="3510496440489019191">"Измените снимак екрана"</string>
<string name="screenshot_dismiss_ui_description" msgid="934736855340147968">"Одбаците снимак екрана"</string>
<string name="screenshot_preview_description" msgid="7606510140714080474">"Преглед снимка екрана"</string>
<string name="screenrecord_name" msgid="2596401223859996572">"Снимач екрана"</string>
@@ -1071,8 +1070,7 @@
<string name="controls_seeding_in_progress" msgid="3033855341410264148">"Учитавају се препоруке"</string>
<string name="controls_media_title" msgid="1746947284862928133">"Медији"</string>
<string name="controls_media_close_session" msgid="3957093425905475065">"Сакријте актуелну сесију."</string>
- <!-- no translation found for controls_media_active_session (1984383994625845642) -->
- <skip />
+ <string name="controls_media_active_session" msgid="1984383994625845642">"Актуелна сесија не може да се сакрије."</string>
<string name="controls_media_dismiss_button" msgid="9081375542265132213">"Одбаци"</string>
<string name="controls_media_resume" msgid="1933520684481586053">"Настави"</string>
<string name="controls_media_settings_button" msgid="5815790345117172504">"Подешавања"</string>
diff --git a/packages/SystemUI/res/values-sv/strings.xml b/packages/SystemUI/res/values-sv/strings.xml
index a51ed2879cb5..d34c814f2aa7 100644
--- a/packages/SystemUI/res/values-sv/strings.xml
+++ b/packages/SystemUI/res/values-sv/strings.xml
@@ -86,8 +86,7 @@
<string name="screenshot_failed_to_save_unknown_text" msgid="1506621600548684129">"Testa att ta en skärmdump igen"</string>
<string name="screenshot_failed_to_save_text" msgid="8344173457344027501">"Det går inte att spara skärmdumpen eftersom lagringsutrymmet inte räcker"</string>
<string name="screenshot_failed_to_capture_text" msgid="7818288545874407451">"Appen eller organisationen tillåter inte att du tar skärmdumpar"</string>
- <!-- no translation found for screenshot_edit (3510496440489019191) -->
- <skip />
+ <string name="screenshot_edit" msgid="3510496440489019191">"Redigera skärmdump"</string>
<string name="screenshot_dismiss_ui_description" msgid="934736855340147968">"Stäng skärmdump"</string>
<string name="screenshot_preview_description" msgid="7606510140714080474">"Förhandsgranskning av skärmdump"</string>
<string name="screenrecord_name" msgid="2596401223859996572">"Skärminspelare"</string>
@@ -1065,8 +1064,7 @@
<string name="controls_seeding_in_progress" msgid="3033855341410264148">"Rekommendationer läses in"</string>
<string name="controls_media_title" msgid="1746947284862928133">"Media"</string>
<string name="controls_media_close_session" msgid="3957093425905475065">"Dölj den aktuella sessionen."</string>
- <!-- no translation found for controls_media_active_session (1984383994625845642) -->
- <skip />
+ <string name="controls_media_active_session" msgid="1984383994625845642">"Det går inte att dölja den aktuella sessionen."</string>
<string name="controls_media_dismiss_button" msgid="9081375542265132213">"Stäng"</string>
<string name="controls_media_resume" msgid="1933520684481586053">"Återuppta"</string>
<string name="controls_media_settings_button" msgid="5815790345117172504">"Inställningar"</string>
diff --git a/packages/SystemUI/res/values-ta/strings.xml b/packages/SystemUI/res/values-ta/strings.xml
index 3c1c12ac8ea0..a72ebeff0ddc 100644
--- a/packages/SystemUI/res/values-ta/strings.xml
+++ b/packages/SystemUI/res/values-ta/strings.xml
@@ -86,8 +86,7 @@
<string name="screenshot_failed_to_save_unknown_text" msgid="1506621600548684129">"ஸ்கிரீன் ஷாட்டை மீண்டும் எடுக்க முயலவும்"</string>
<string name="screenshot_failed_to_save_text" msgid="8344173457344027501">"போதுமான சேமிப்பிடம் இல்லாததால் ஸ்கிரீன்ஷாட்டைச் சேமிக்க முடியவில்லை"</string>
<string name="screenshot_failed_to_capture_text" msgid="7818288545874407451">"ஸ்கிரீன் ஷாட்டுகளை எடுப்பதை, ஆப்ஸ் அல்லது உங்கள் நிறுவனம் அனுமதிக்கவில்லை"</string>
- <!-- no translation found for screenshot_edit (3510496440489019191) -->
- <skip />
+ <string name="screenshot_edit" msgid="3510496440489019191">"ஸ்கிரீன்ஷாட்டைத் திருத்தும்"</string>
<string name="screenshot_dismiss_ui_description" msgid="934736855340147968">"ஸ்கிரீன்ஷாட்டை நிராகரி"</string>
<string name="screenshot_preview_description" msgid="7606510140714080474">"ஸ்கிரீன்ஷாட்டின் மாதிரிக்காட்சி"</string>
<string name="screenrecord_name" msgid="2596401223859996572">"ஸ்கிரீன் ரெக்கார்டர்"</string>
@@ -1065,8 +1064,7 @@
<string name="controls_seeding_in_progress" msgid="3033855341410264148">"பரிந்துரைகளை ஏற்றுகிறது"</string>
<string name="controls_media_title" msgid="1746947284862928133">"மீடியா"</string>
<string name="controls_media_close_session" msgid="3957093425905475065">"இந்த அமர்வை மறையுங்கள்."</string>
- <!-- no translation found for controls_media_active_session (1984383994625845642) -->
- <skip />
+ <string name="controls_media_active_session" msgid="1984383994625845642">"தற்போதைய அமர்வை மறைக்க முடியாது."</string>
<string name="controls_media_dismiss_button" msgid="9081375542265132213">"மூடுக"</string>
<string name="controls_media_resume" msgid="1933520684481586053">"தொடர்க"</string>
<string name="controls_media_settings_button" msgid="5815790345117172504">"அமைப்புகள்"</string>
diff --git a/packages/SystemUI/res/values-te/strings.xml b/packages/SystemUI/res/values-te/strings.xml
index 2680d22efb97..0d23f25409b4 100644
--- a/packages/SystemUI/res/values-te/strings.xml
+++ b/packages/SystemUI/res/values-te/strings.xml
@@ -86,8 +86,7 @@
<string name="screenshot_failed_to_save_unknown_text" msgid="1506621600548684129">"స్క్రీన్‌షాట్ తీయడానికి మళ్లీ ప్రయత్నించండి"</string>
<string name="screenshot_failed_to_save_text" msgid="8344173457344027501">"నిల్వ స్థలం పరిమితంగా ఉన్న కారణంగా స్క్రీన్‌షాట్‌ను సేవ్ చేయడం సాధ్యపడదు"</string>
<string name="screenshot_failed_to_capture_text" msgid="7818288545874407451">"స్క్రీన్‌షాట్‌లు తీయడానికి యాప్ లేదా మీ సంస్థ అనుమతించలేదు"</string>
- <!-- no translation found for screenshot_edit (3510496440489019191) -->
- <skip />
+ <string name="screenshot_edit" msgid="3510496440489019191">"స్క్రీన్‌షాట్‌ను ఎడిట్ చేస్తుంది"</string>
<string name="screenshot_dismiss_ui_description" msgid="934736855340147968">"స్క్రీన్‌షాట్‌ను మూసివేస్తుంది"</string>
<string name="screenshot_preview_description" msgid="7606510140714080474">"స్క్రీన్‌షాట్ ప్రివ్యూ"</string>
<string name="screenrecord_name" msgid="2596401223859996572">"స్క్రీన్ రికార్డర్"</string>
@@ -1065,8 +1064,7 @@
<string name="controls_seeding_in_progress" msgid="3033855341410264148">"సిఫార్సులు లోడ్ అవుతున్నాయి"</string>
<string name="controls_media_title" msgid="1746947284862928133">"మీడియా"</string>
<string name="controls_media_close_session" msgid="3957093425905475065">"ప్రస్తుత సెషన్‌ను దాచు."</string>
- <!-- no translation found for controls_media_active_session (1984383994625845642) -->
- <skip />
+ <string name="controls_media_active_session" msgid="1984383994625845642">"ప్రస్తుత సెషన్‌ను దాచడం సాధ్యం కాదు."</string>
<string name="controls_media_dismiss_button" msgid="9081375542265132213">"విస్మరించు"</string>
<string name="controls_media_resume" msgid="1933520684481586053">"కొనసాగించండి"</string>
<string name="controls_media_settings_button" msgid="5815790345117172504">"సెట్టింగ్‌లు"</string>
diff --git a/packages/SystemUI/res/values-th/strings.xml b/packages/SystemUI/res/values-th/strings.xml
index 2e4682bd2541..094cb765a49b 100644
--- a/packages/SystemUI/res/values-th/strings.xml
+++ b/packages/SystemUI/res/values-th/strings.xml
@@ -86,8 +86,7 @@
<string name="screenshot_failed_to_save_unknown_text" msgid="1506621600548684129">"ลองบันทึกภาพหน้าจออีกครั้ง"</string>
<string name="screenshot_failed_to_save_text" msgid="8344173457344027501">"บันทึกภาพหน้าจอไม่ได้เนื่องจากพื้นที่เก็บข้อมูลมีจำกัด"</string>
<string name="screenshot_failed_to_capture_text" msgid="7818288545874407451">"แอปหรือองค์กรของคุณไม่อนุญาตให้จับภาพหน้าจอ"</string>
- <!-- no translation found for screenshot_edit (3510496440489019191) -->
- <skip />
+ <string name="screenshot_edit" msgid="3510496440489019191">"แก้ไขภาพหน้าจอ"</string>
<string name="screenshot_dismiss_ui_description" msgid="934736855340147968">"ปิดภาพหน้าจอ"</string>
<string name="screenshot_preview_description" msgid="7606510140714080474">"ตัวอย่างภาพหน้าจอ"</string>
<string name="screenrecord_name" msgid="2596401223859996572">"โปรแกรมอัดหน้าจอ"</string>
@@ -1065,8 +1064,7 @@
<string name="controls_seeding_in_progress" msgid="3033855341410264148">"กำลังโหลดคำแนะนำ"</string>
<string name="controls_media_title" msgid="1746947284862928133">"สื่อ"</string>
<string name="controls_media_close_session" msgid="3957093425905475065">"ซ่อนเซสชันปัจจุบัน"</string>
- <!-- no translation found for controls_media_active_session (1984383994625845642) -->
- <skip />
+ <string name="controls_media_active_session" msgid="1984383994625845642">"ซ่อนเซสชันปัจจุบันไม่ได้"</string>
<string name="controls_media_dismiss_button" msgid="9081375542265132213">"ปิด"</string>
<string name="controls_media_resume" msgid="1933520684481586053">"เล่นต่อ"</string>
<string name="controls_media_settings_button" msgid="5815790345117172504">"การตั้งค่า"</string>
diff --git a/packages/SystemUI/res/values-tl/strings.xml b/packages/SystemUI/res/values-tl/strings.xml
index ae69c4fc3a04..8ef18697cd4d 100644
--- a/packages/SystemUI/res/values-tl/strings.xml
+++ b/packages/SystemUI/res/values-tl/strings.xml
@@ -86,8 +86,7 @@
<string name="screenshot_failed_to_save_unknown_text" msgid="1506621600548684129">"Subukang kumuhang muli ng screenshot"</string>
<string name="screenshot_failed_to_save_text" msgid="8344173457344027501">"Hindi ma-save ang screenshot dahil sa limitadong espasyo ng storage"</string>
<string name="screenshot_failed_to_capture_text" msgid="7818288545874407451">"Hindi pinahihintulutan ng app o ng iyong organisasyon ang pagkuha ng mga screenshot"</string>
- <!-- no translation found for screenshot_edit (3510496440489019191) -->
- <skip />
+ <string name="screenshot_edit" msgid="3510496440489019191">"I-edit ang screenshot"</string>
<string name="screenshot_dismiss_ui_description" msgid="934736855340147968">"I-dismiss ang screenshot"</string>
<string name="screenshot_preview_description" msgid="7606510140714080474">"Preview ng screenshot"</string>
<string name="screenrecord_name" msgid="2596401223859996572">"Recorder ng Screen"</string>
@@ -1065,8 +1064,7 @@
<string name="controls_seeding_in_progress" msgid="3033855341410264148">"Nilo-load ang rekomendasyon"</string>
<string name="controls_media_title" msgid="1746947284862928133">"Media"</string>
<string name="controls_media_close_session" msgid="3957093425905475065">"Itago ang kasalukuyang session."</string>
- <!-- no translation found for controls_media_active_session (1984383994625845642) -->
- <skip />
+ <string name="controls_media_active_session" msgid="1984383994625845642">"Hindi maitatago ang kasalukuyang session."</string>
<string name="controls_media_dismiss_button" msgid="9081375542265132213">"I-dismiss"</string>
<string name="controls_media_resume" msgid="1933520684481586053">"Ituloy"</string>
<string name="controls_media_settings_button" msgid="5815790345117172504">"Mga Setting"</string>
diff --git a/packages/SystemUI/res/values-tr/strings.xml b/packages/SystemUI/res/values-tr/strings.xml
index 026517671be2..c17c8f710079 100644
--- a/packages/SystemUI/res/values-tr/strings.xml
+++ b/packages/SystemUI/res/values-tr/strings.xml
@@ -86,8 +86,7 @@
<string name="screenshot_failed_to_save_unknown_text" msgid="1506621600548684129">"Tekrar ekran görüntüsü almayı deneyin"</string>
<string name="screenshot_failed_to_save_text" msgid="8344173457344027501">"Depolama alanı sınırlı olduğundan ekran görüntüsü kaydedilemiyor"</string>
<string name="screenshot_failed_to_capture_text" msgid="7818288545874407451">"Uygulama veya kuruluşunuz, ekran görüntüsü alınmasına izin vermiyor."</string>
- <!-- no translation found for screenshot_edit (3510496440489019191) -->
- <skip />
+ <string name="screenshot_edit" msgid="3510496440489019191">"Ekran görüntüsünü düzenleyin"</string>
<string name="screenshot_dismiss_ui_description" msgid="934736855340147968">"Ekran görüntüsünü kapat"</string>
<string name="screenshot_preview_description" msgid="7606510140714080474">"Ekran görüntüsü önizlemesi"</string>
<string name="screenrecord_name" msgid="2596401223859996572">"Ekran Kaydedicisi"</string>
@@ -1065,8 +1064,7 @@
<string name="controls_seeding_in_progress" msgid="3033855341410264148">"Öneriler yükleniyor"</string>
<string name="controls_media_title" msgid="1746947284862928133">"Medya"</string>
<string name="controls_media_close_session" msgid="3957093425905475065">"Mevcut oturumu gizle."</string>
- <!-- no translation found for controls_media_active_session (1984383994625845642) -->
- <skip />
+ <string name="controls_media_active_session" msgid="1984383994625845642">"Mevcut oturum gizlenemez."</string>
<string name="controls_media_dismiss_button" msgid="9081375542265132213">"Kapat"</string>
<string name="controls_media_resume" msgid="1933520684481586053">"Devam ettir"</string>
<string name="controls_media_settings_button" msgid="5815790345117172504">"Ayarlar"</string>
diff --git a/packages/SystemUI/res/values-uk/strings.xml b/packages/SystemUI/res/values-uk/strings.xml
index c9fd5032609e..7dcfc3b175ac 100644
--- a/packages/SystemUI/res/values-uk/strings.xml
+++ b/packages/SystemUI/res/values-uk/strings.xml
@@ -86,8 +86,7 @@
<string name="screenshot_failed_to_save_unknown_text" msgid="1506621600548684129">"Спробуйте зробити знімок екрана ще раз"</string>
<string name="screenshot_failed_to_save_text" msgid="8344173457344027501">"Не вдалося зберегти знімок екрана через обмежений обсяг пам’яті"</string>
<string name="screenshot_failed_to_capture_text" msgid="7818288545874407451">"Додаток або адміністратор вашої організації не дозволяють робити знімки екрана"</string>
- <!-- no translation found for screenshot_edit (3510496440489019191) -->
- <skip />
+ <string name="screenshot_edit" msgid="3510496440489019191">"Редагувати знімок екрана"</string>
<string name="screenshot_dismiss_ui_description" msgid="934736855340147968">"Закрити знімок екрана"</string>
<string name="screenshot_preview_description" msgid="7606510140714080474">"Перегляд знімка екрана"</string>
<string name="screenrecord_name" msgid="2596401223859996572">"Відеозапис екрана"</string>
@@ -1077,8 +1076,7 @@
<string name="controls_seeding_in_progress" msgid="3033855341410264148">"Завантаження рекомендацій"</string>
<string name="controls_media_title" msgid="1746947284862928133">"Медіа"</string>
<string name="controls_media_close_session" msgid="3957093425905475065">"Приховати поточний сеанс."</string>
- <!-- no translation found for controls_media_active_session (1984383994625845642) -->
- <skip />
+ <string name="controls_media_active_session" msgid="1984383994625845642">"Поточний сеанс не можна приховати."</string>
<string name="controls_media_dismiss_button" msgid="9081375542265132213">"Закрити"</string>
<string name="controls_media_resume" msgid="1933520684481586053">"Відновити"</string>
<string name="controls_media_settings_button" msgid="5815790345117172504">"Налаштування"</string>
diff --git a/packages/SystemUI/res/values-ur/strings.xml b/packages/SystemUI/res/values-ur/strings.xml
index 1bfa85394559..4c0ebaad9275 100644
--- a/packages/SystemUI/res/values-ur/strings.xml
+++ b/packages/SystemUI/res/values-ur/strings.xml
@@ -86,8 +86,7 @@
<string name="screenshot_failed_to_save_unknown_text" msgid="1506621600548684129">"دوبارہ اسکرین شاٹ لینے کی کوشش کریں"</string>
<string name="screenshot_failed_to_save_text" msgid="8344173457344027501">"اسٹوریج کی محدود جگہ کی وجہ سے اسکرین شاٹ کو محفوظ نہیں کیا جا سکتا"</string>
<string name="screenshot_failed_to_capture_text" msgid="7818288545874407451">"ایپ یا آپ کی تنظیم کی جانب سے اسکرین شاٹس لینے کی اجازت نہیں ہے"</string>
- <!-- no translation found for screenshot_edit (3510496440489019191) -->
- <skip />
+ <string name="screenshot_edit" msgid="3510496440489019191">"اسکرین شاٹ میں ترمیم کریں"</string>
<string name="screenshot_dismiss_ui_description" msgid="934736855340147968">"اسکرین شاٹ برخاست کریں"</string>
<string name="screenshot_preview_description" msgid="7606510140714080474">"اسکرین شاٹ کا پیش منظر"</string>
<string name="screenrecord_name" msgid="2596401223859996572">"سکرین ریکارڈر"</string>
@@ -1065,8 +1064,7 @@
<string name="controls_seeding_in_progress" msgid="3033855341410264148">"تجاویز لوڈ ہو رہی ہیں"</string>
<string name="controls_media_title" msgid="1746947284862928133">"میڈیا"</string>
<string name="controls_media_close_session" msgid="3957093425905475065">"موجودہ سیشن چھپائیں۔"</string>
- <!-- no translation found for controls_media_active_session (1984383994625845642) -->
- <skip />
+ <string name="controls_media_active_session" msgid="1984383994625845642">"موجودہ سیشن کو چھپایا نہیں جا سکتا۔"</string>
<string name="controls_media_dismiss_button" msgid="9081375542265132213">"برخاست کریں"</string>
<string name="controls_media_resume" msgid="1933520684481586053">"دوبارہ شروع کریں"</string>
<string name="controls_media_settings_button" msgid="5815790345117172504">"ترتیبات"</string>
diff --git a/packages/SystemUI/res/values-uz/strings.xml b/packages/SystemUI/res/values-uz/strings.xml
index 332a26daee92..33d4f4ca14b7 100644
--- a/packages/SystemUI/res/values-uz/strings.xml
+++ b/packages/SystemUI/res/values-uz/strings.xml
@@ -1064,7 +1064,7 @@
<string name="controls_seeding_in_progress" msgid="3033855341410264148">"Tavsiyalar yuklanmoqda"</string>
<string name="controls_media_title" msgid="1746947284862928133">"Media"</string>
<string name="controls_media_close_session" msgid="3957093425905475065">"Joriy seans berkitilsin."</string>
- <string name="controls_media_active_session" msgid="1984383994625845642">"Joriy seans berkilmaydi."</string>
+ <string name="controls_media_active_session" msgid="1984383994625845642">"Joriy seansni berkitish imkonsiz."</string>
<string name="controls_media_dismiss_button" msgid="9081375542265132213">"Yopish"</string>
<string name="controls_media_resume" msgid="1933520684481586053">"Davom etish"</string>
<string name="controls_media_settings_button" msgid="5815790345117172504">"Sozlamalar"</string>
diff --git a/packages/SystemUI/res/values-vi/strings.xml b/packages/SystemUI/res/values-vi/strings.xml
index 947bd435c777..179f7c265496 100644
--- a/packages/SystemUI/res/values-vi/strings.xml
+++ b/packages/SystemUI/res/values-vi/strings.xml
@@ -86,8 +86,7 @@
<string name="screenshot_failed_to_save_unknown_text" msgid="1506621600548684129">"Hãy thử chụp lại màn hình"</string>
<string name="screenshot_failed_to_save_text" msgid="8344173457344027501">"Không thể lưu ảnh chụp màn hình do giới hạn dung lượng bộ nhớ"</string>
<string name="screenshot_failed_to_capture_text" msgid="7818288545874407451">"Ứng dụng hoặc tổ chức của bạn không cho phép chụp ảnh màn hình"</string>
- <!-- no translation found for screenshot_edit (3510496440489019191) -->
- <skip />
+ <string name="screenshot_edit" msgid="3510496440489019191">"Chỉnh sửa ảnh chụp màn hình"</string>
<string name="screenshot_dismiss_ui_description" msgid="934736855340147968">"Đóng ảnh chụp màn hình"</string>
<string name="screenshot_preview_description" msgid="7606510140714080474">"Xem trước ảnh chụp màn hình"</string>
<string name="screenrecord_name" msgid="2596401223859996572">"Trình ghi màn hình"</string>
@@ -1065,8 +1064,7 @@
<string name="controls_seeding_in_progress" msgid="3033855341410264148">"Đang tải các đề xuất"</string>
<string name="controls_media_title" msgid="1746947284862928133">"Nội dung nghe nhìn"</string>
<string name="controls_media_close_session" msgid="3957093425905475065">"Ẩn phiên hiện tại."</string>
- <!-- no translation found for controls_media_active_session (1984383994625845642) -->
- <skip />
+ <string name="controls_media_active_session" msgid="1984383994625845642">"Bạn không thể ẩn phiên hiện tại."</string>
<string name="controls_media_dismiss_button" msgid="9081375542265132213">"Đóng"</string>
<string name="controls_media_resume" msgid="1933520684481586053">"Tiếp tục"</string>
<string name="controls_media_settings_button" msgid="5815790345117172504">"Cài đặt"</string>
diff --git a/packages/SystemUI/res/values-zh-rCN/strings.xml b/packages/SystemUI/res/values-zh-rCN/strings.xml
index 730fa81a5975..e1f483c78e7f 100644
--- a/packages/SystemUI/res/values-zh-rCN/strings.xml
+++ b/packages/SystemUI/res/values-zh-rCN/strings.xml
@@ -86,8 +86,7 @@
<string name="screenshot_failed_to_save_unknown_text" msgid="1506621600548684129">"请再次尝试截屏"</string>
<string name="screenshot_failed_to_save_text" msgid="8344173457344027501">"由于存储空间有限,无法保存屏幕截图"</string>
<string name="screenshot_failed_to_capture_text" msgid="7818288545874407451">"此应用或您所在的单位不允许进行屏幕截图"</string>
- <!-- no translation found for screenshot_edit (3510496440489019191) -->
- <skip />
+ <string name="screenshot_edit" msgid="3510496440489019191">"编辑屏幕截图"</string>
<string name="screenshot_dismiss_ui_description" msgid="934736855340147968">"关闭屏幕截图"</string>
<string name="screenshot_preview_description" msgid="7606510140714080474">"屏幕截图预览"</string>
<string name="screenrecord_name" msgid="2596401223859996572">"屏幕录制器"</string>
@@ -1065,8 +1064,7 @@
<string name="controls_seeding_in_progress" msgid="3033855341410264148">"正在加载推荐内容"</string>
<string name="controls_media_title" msgid="1746947284862928133">"媒体"</string>
<string name="controls_media_close_session" msgid="3957093425905475065">"隐藏当前会话。"</string>
- <!-- no translation found for controls_media_active_session (1984383994625845642) -->
- <skip />
+ <string name="controls_media_active_session" msgid="1984383994625845642">"无法隐藏当前会话。"</string>
<string name="controls_media_dismiss_button" msgid="9081375542265132213">"关闭"</string>
<string name="controls_media_resume" msgid="1933520684481586053">"继续播放"</string>
<string name="controls_media_settings_button" msgid="5815790345117172504">"设置"</string>
diff --git a/packages/SystemUI/res/values-zh-rHK/strings.xml b/packages/SystemUI/res/values-zh-rHK/strings.xml
index 42361079a9bb..f986ef33ca28 100644
--- a/packages/SystemUI/res/values-zh-rHK/strings.xml
+++ b/packages/SystemUI/res/values-zh-rHK/strings.xml
@@ -86,8 +86,7 @@
<string name="screenshot_failed_to_save_unknown_text" msgid="1506621600548684129">"請再嘗試拍攝螢幕擷取畫面"</string>
<string name="screenshot_failed_to_save_text" msgid="8344173457344027501">"由於儲存空間有限,因此無法儲存螢幕擷取畫面"</string>
<string name="screenshot_failed_to_capture_text" msgid="7818288545874407451">"應用程式或您的機構不允許擷取螢幕畫面"</string>
- <!-- no translation found for screenshot_edit (3510496440489019191) -->
- <skip />
+ <string name="screenshot_edit" msgid="3510496440489019191">"編輯螢幕截圖"</string>
<string name="screenshot_dismiss_ui_description" msgid="934736855340147968">"關閉螢幕截圖"</string>
<string name="screenshot_preview_description" msgid="7606510140714080474">"螢幕截圖預覽"</string>
<string name="screenrecord_name" msgid="2596401223859996572">"螢幕畫面錄影工具"</string>
@@ -1065,8 +1064,7 @@
<string name="controls_seeding_in_progress" msgid="3033855341410264148">"正在載入建議"</string>
<string name="controls_media_title" msgid="1746947284862928133">"媒體"</string>
<string name="controls_media_close_session" msgid="3957093425905475065">"隱藏目前的工作階段。"</string>
- <!-- no translation found for controls_media_active_session (1984383994625845642) -->
- <skip />
+ <string name="controls_media_active_session" msgid="1984383994625845642">"無法隱藏目前的工作階段。"</string>
<string name="controls_media_dismiss_button" msgid="9081375542265132213">"關閉"</string>
<string name="controls_media_resume" msgid="1933520684481586053">"繼續播放"</string>
<string name="controls_media_settings_button" msgid="5815790345117172504">"設定"</string>
diff --git a/packages/SystemUI/res/values-zh-rTW/strings.xml b/packages/SystemUI/res/values-zh-rTW/strings.xml
index c7407ef03730..b442b792e95f 100644
--- a/packages/SystemUI/res/values-zh-rTW/strings.xml
+++ b/packages/SystemUI/res/values-zh-rTW/strings.xml
@@ -86,8 +86,7 @@
<string name="screenshot_failed_to_save_unknown_text" msgid="1506621600548684129">"請再次嘗試拍攝螢幕截圖"</string>
<string name="screenshot_failed_to_save_text" msgid="8344173457344027501">"由於儲存空間有限,因此無法儲存螢幕截圖"</string>
<string name="screenshot_failed_to_capture_text" msgid="7818288545874407451">"這個應用程式或貴機構不允許擷取螢幕畫面"</string>
- <!-- no translation found for screenshot_edit (3510496440489019191) -->
- <skip />
+ <string name="screenshot_edit" msgid="3510496440489019191">"編輯螢幕截圖"</string>
<string name="screenshot_dismiss_ui_description" msgid="934736855340147968">"關閉螢幕截圖"</string>
<string name="screenshot_preview_description" msgid="7606510140714080474">"螢幕截圖預覽"</string>
<string name="screenrecord_name" msgid="2596401223859996572">"螢幕錄影器"</string>
@@ -1065,8 +1064,7 @@
<string name="controls_seeding_in_progress" msgid="3033855341410264148">"正在載入建議控制項"</string>
<string name="controls_media_title" msgid="1746947284862928133">"媒體"</string>
<string name="controls_media_close_session" msgid="3957093425905475065">"隱藏目前的工作階段。"</string>
- <!-- no translation found for controls_media_active_session (1984383994625845642) -->
- <skip />
+ <string name="controls_media_active_session" msgid="1984383994625845642">"無法隱藏目前的工作階段。"</string>
<string name="controls_media_dismiss_button" msgid="9081375542265132213">"關閉"</string>
<string name="controls_media_resume" msgid="1933520684481586053">"繼續播放"</string>
<string name="controls_media_settings_button" msgid="5815790345117172504">"設定"</string>
diff --git a/packages/SystemUI/res/values-zu/strings.xml b/packages/SystemUI/res/values-zu/strings.xml
index dd7f6f65b86c..764f0b719702 100644
--- a/packages/SystemUI/res/values-zu/strings.xml
+++ b/packages/SystemUI/res/values-zu/strings.xml
@@ -86,8 +86,7 @@
<string name="screenshot_failed_to_save_unknown_text" msgid="1506621600548684129">"Zama ukuthatha isithombe-skrini futhi"</string>
<string name="screenshot_failed_to_save_text" msgid="8344173457344027501">"Ayikwazi ukulondoloza isithombe-skrini ngenxa yesikhala sesitoreji esikhawulelwe"</string>
<string name="screenshot_failed_to_capture_text" msgid="7818288545874407451">"Ukuthatha izithombe-skrini akuvunyelwe uhlelo lokusebenza noma inhlangano yakho"</string>
- <!-- no translation found for screenshot_edit (3510496440489019191) -->
- <skip />
+ <string name="screenshot_edit" msgid="3510496440489019191">"Hlela isithombe-skrini"</string>
<string name="screenshot_dismiss_ui_description" msgid="934736855340147968">"Cashisa isithombe-skrini"</string>
<string name="screenshot_preview_description" msgid="7606510140714080474">"Ukubuka kuqala isithombe-skrini"</string>
<string name="screenrecord_name" msgid="2596401223859996572">"Irekhoda yesikrini"</string>
@@ -1065,8 +1064,7 @@
<string name="controls_seeding_in_progress" msgid="3033855341410264148">"Ilayisha izincomo"</string>
<string name="controls_media_title" msgid="1746947284862928133">"Imidiya"</string>
<string name="controls_media_close_session" msgid="3957093425905475065">"Fihla iseshini yamanje."</string>
- <!-- no translation found for controls_media_active_session (1984383994625845642) -->
- <skip />
+ <string name="controls_media_active_session" msgid="1984383994625845642">"Iseshini yamanje ayikwazi ukufihlwa."</string>
<string name="controls_media_dismiss_button" msgid="9081375542265132213">"Cashisa"</string>
<string name="controls_media_resume" msgid="1933520684481586053">"Qalisa kabusha"</string>
<string name="controls_media_settings_button" msgid="5815790345117172504">"Izilungiselelo"</string>
diff --git a/packages/SystemUI/res/xml/people_space_widget_info.xml b/packages/SystemUI/res/xml/people_space_widget_info.xml
new file mode 100644
index 000000000000..f08c8c80f961
--- /dev/null
+++ b/packages/SystemUI/res/xml/people_space_widget_info.xml
@@ -0,0 +1,24 @@
+<!--
+ ~ Copyright (C) 2020 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License.
+ -->
+
+<appwidget-provider xmlns:android="http://schemas.android.com/apk/res/android"
+ android:minWidth="72dp"
+ android:minHeight="150dp"
+ android:updatePeriodMillis="60000"
+ android:previewImage="@drawable/cloud"
+ android:resizeMode="horizontal|vertical"
+ android:initialLayout="@layout/people_space_widget">
+</appwidget-provider>
diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/recents/model/ThumbnailData.java b/packages/SystemUI/shared/src/com/android/systemui/shared/recents/model/ThumbnailData.java
index 9d3620f34186..3de0b4b78e06 100644
--- a/packages/SystemUI/shared/src/com/android/systemui/shared/recents/model/ThumbnailData.java
+++ b/packages/SystemUI/shared/src/com/android/systemui/shared/recents/model/ThumbnailData.java
@@ -61,18 +61,28 @@ public class ThumbnailData {
snapshotId = 0;
}
- public ThumbnailData(TaskSnapshot snapshot) {
+ private static Bitmap makeThumbnail(TaskSnapshot snapshot) {
final HardwareBuffer buffer = snapshot.getHardwareBuffer();
- if (buffer == null || (buffer.getUsage() & HardwareBuffer.USAGE_GPU_SAMPLED_IMAGE) == 0) {
+ Bitmap thumbnail = null;
+ try {
+ if (buffer != null) {
+ thumbnail = Bitmap.wrapHardwareBuffer(buffer, snapshot.getColorSpace());
+ }
+ } catch (IllegalArgumentException ex) {
// TODO(b/157562905): Workaround for a crash when we get a snapshot without this state
Log.e("ThumbnailData", "Unexpected snapshot without USAGE_GPU_SAMPLED_IMAGE: "
- + buffer);
+ + buffer, ex);
+ }
+ if (thumbnail == null) {
Point taskSize = snapshot.getTaskSize();
thumbnail = Bitmap.createBitmap(taskSize.x, taskSize.y, ARGB_8888);
thumbnail.eraseColor(Color.BLACK);
- } else {
- thumbnail = Bitmap.wrapHardwareBuffer(buffer, snapshot.getColorSpace());
}
+ return thumbnail;
+ }
+
+ public ThumbnailData(TaskSnapshot snapshot) {
+ thumbnail = makeThumbnail(snapshot);
insets = new Rect(snapshot.getContentInsets());
orientation = snapshot.getOrientation();
rotation = snapshot.getRotation();
diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/system/TaskStackChangeListener.java b/packages/SystemUI/shared/src/com/android/systemui/shared/system/TaskStackChangeListener.java
index 44372d76bb23..8d010c743d81 100644
--- a/packages/SystemUI/shared/src/com/android/systemui/shared/system/TaskStackChangeListener.java
+++ b/packages/SystemUI/shared/src/com/android/systemui/shared/system/TaskStackChangeListener.java
@@ -62,21 +62,6 @@ public abstract class TaskStackChangeListener {
onActivityLaunchOnSecondaryDisplayRerouted();
}
- /**
- * Called when contents are drawn for the first time on a display which can only contain one
- * task.
- *
- * @param displayId the id of the display on which contents are drawn.
- */
- public void onSingleTaskDisplayDrawn(int displayId) { }
-
- /**
- * Called when the last task is removed from a display which can only contain one task.
- *
- * @param displayId the id of the display from which the window is removed.
- */
- public void onSingleTaskDisplayEmpty(int displayId) {}
-
public void onTaskProfileLocked(int taskId, int userId) { }
public void onTaskCreated(int taskId, ComponentName componentName) { }
public void onTaskRemoved(int taskId) { }
diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/system/TaskStackChangeListeners.java b/packages/SystemUI/shared/src/com/android/systemui/shared/system/TaskStackChangeListeners.java
index 765cd3de4222..adaee5557a8d 100644
--- a/packages/SystemUI/shared/src/com/android/systemui/shared/system/TaskStackChangeListeners.java
+++ b/packages/SystemUI/shared/src/com/android/systemui/shared/system/TaskStackChangeListeners.java
@@ -90,13 +90,11 @@ public class TaskStackChangeListeners extends TaskStackListener {
private static final int ON_ACTIVITY_LAUNCH_ON_SECONDARY_DISPLAY_REROUTED = 16;
private static final int ON_SIZE_COMPAT_MODE_ACTIVITY_CHANGED = 17;
private static final int ON_BACK_PRESSED_ON_TASK_ROOT = 18;
- private static final int ON_SINGLE_TASK_DISPLAY_DRAWN = 19;
- private static final int ON_TASK_DISPLAY_CHANGED = 20;
- private static final int ON_TASK_LIST_UPDATED = 21;
- private static final int ON_SINGLE_TASK_DISPLAY_EMPTY = 22;
- private static final int ON_TASK_LIST_FROZEN_UNFROZEN = 23;
- private static final int ON_TASK_DESCRIPTION_CHANGED = 24;
- private static final int ON_ACTIVITY_ROTATION = 25;
+ private static final int ON_TASK_DISPLAY_CHANGED = 19;
+ private static final int ON_TASK_LIST_UPDATED = 20;
+ private static final int ON_TASK_LIST_FROZEN_UNFROZEN = 21;
+ private static final int ON_TASK_DESCRIPTION_CHANGED = 22;
+ private static final int ON_ACTIVITY_ROTATION = 23;
/**
* List of {@link TaskStackChangeListener} registered from {@link #addListener}.
@@ -257,18 +255,6 @@ public class TaskStackChangeListeners extends TaskStackListener {
}
@Override
- public void onSingleTaskDisplayDrawn(int displayId) {
- mHandler.obtainMessage(ON_SINGLE_TASK_DISPLAY_DRAWN, displayId,
- 0 /* unused */).sendToTarget();
- }
-
- @Override
- public void onSingleTaskDisplayEmpty(int displayId) {
- mHandler.obtainMessage(ON_SINGLE_TASK_DISPLAY_EMPTY, displayId,
- 0 /* unused */).sendToTarget();
- }
-
- @Override
public void onTaskDisplayChanged(int taskId, int newDisplayId) {
mHandler.obtainMessage(ON_TASK_DISPLAY_CHANGED, taskId, newDisplayId).sendToTarget();
}
@@ -419,18 +405,6 @@ public class TaskStackChangeListeners extends TaskStackListener {
}
break;
}
- case ON_SINGLE_TASK_DISPLAY_DRAWN: {
- for (int i = mTaskStackListeners.size() - 1; i >= 0; i--) {
- mTaskStackListeners.get(i).onSingleTaskDisplayDrawn(msg.arg1);
- }
- break;
- }
- case ON_SINGLE_TASK_DISPLAY_EMPTY: {
- for (int i = mTaskStackListeners.size() - 1; i >= 0; i--) {
- mTaskStackListeners.get(i).onSingleTaskDisplayEmpty(msg.arg1);
- }
- break;
- }
case ON_TASK_DISPLAY_CHANGED: {
for (int i = mTaskStackListeners.size() - 1; i >= 0; i--) {
mTaskStackListeners.get(i).onTaskDisplayChanged(msg.arg1, msg.arg2);
diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/system/WindowManagerWrapper.java b/packages/SystemUI/shared/src/com/android/systemui/shared/system/WindowManagerWrapper.java
index 97196d1ef451..5b41d5f90975 100644
--- a/packages/SystemUI/shared/src/com/android/systemui/shared/system/WindowManagerWrapper.java
+++ b/packages/SystemUI/shared/src/com/android/systemui/shared/system/WindowManagerWrapper.java
@@ -55,8 +55,6 @@ public class WindowManagerWrapper {
WindowManager.TRANSIT_WALLPAPER_INTRA_CLOSE;
public static final int TRANSIT_TASK_OPEN_BEHIND = WindowManager.TRANSIT_TASK_OPEN_BEHIND;
public static final int TRANSIT_ACTIVITY_RELAUNCH = WindowManager.TRANSIT_ACTIVITY_RELAUNCH;
- public static final int TRANSIT_DOCK_TASK_FROM_RECENTS =
- WindowManager.TRANSIT_DOCK_TASK_FROM_RECENTS;
public static final int TRANSIT_KEYGUARD_GOING_AWAY = WindowManager.TRANSIT_KEYGUARD_GOING_AWAY;
public static final int TRANSIT_KEYGUARD_GOING_AWAY_ON_WALLPAPER =
WindowManager.TRANSIT_KEYGUARD_GOING_AWAY_ON_WALLPAPER;
diff --git a/packages/SystemUI/src/com/android/keyguard/GradientTextClock.java b/packages/SystemUI/src/com/android/keyguard/GradientTextClock.java
new file mode 100644
index 000000000000..7cf1bd0b3e79
--- /dev/null
+++ b/packages/SystemUI/src/com/android/keyguard/GradientTextClock.java
@@ -0,0 +1,102 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.keyguard;
+
+import android.content.Context;
+import android.graphics.LinearGradient;
+import android.graphics.Shader;
+import android.util.AttributeSet;
+import android.widget.TextClock;
+
+/**
+ * Displays the time with the hour positioned above the minutes. (ie: 09 above 30 is 9:30)
+ * The time's text color is a gradient that changes its colors based on its controller.
+ */
+public class GradientTextClock extends TextClock {
+ private int[] mGradientColors;
+ private float[] mPositions;
+
+ public GradientTextClock(Context context) {
+ this(context, null, 0, 0);
+ }
+
+ public GradientTextClock(Context context, AttributeSet attrs) {
+ this(context, attrs, 0, 0);
+ }
+
+ public GradientTextClock(Context context, AttributeSet attrs, int defStyleAttr) {
+ this(context, attrs, defStyleAttr, 0);
+ }
+
+ public GradientTextClock(Context context, AttributeSet attrs, int defStyleAttr,
+ int defStyleRes) {
+ super(context, attrs, defStyleAttr, defStyleRes);
+ }
+
+ @Override
+ public void onAttachedToWindow() {
+ super.onAttachedToWindow();
+ addOnLayoutChangeListener(mOnLayoutChangeListener);
+ }
+
+ @Override
+ public void onDetachedFromWindow() {
+ super.onDetachedFromWindow();
+ removeOnLayoutChangeListener(mOnLayoutChangeListener);
+ }
+
+ @Override
+ public void refreshTime() {
+ super.refreshTime();
+ }
+
+ @Override
+ public void setFormat12Hour(CharSequence format) {
+ super.setFormat12Hour(FORMAT_12);
+ }
+
+ @Override
+ public void setFormat24Hour(CharSequence format) {
+ super.setFormat24Hour(FORMAT_24);
+ }
+
+ public void setGradientColors(int[] colors) {
+ mGradientColors = colors;
+ updatePaint();
+ }
+
+ public void setColorPositions(float[] positions) {
+ mPositions = positions;
+ }
+
+ private void updatePaint() {
+ getPaint().setShader(
+ new LinearGradient(
+ getX(), getY(), getX(), getMeasuredHeight() + getY(),
+ mGradientColors, mPositions, Shader.TileMode.REPEAT));
+ }
+
+ private final OnLayoutChangeListener mOnLayoutChangeListener =
+ (v, left, top, right, bottom, oldLeft, oldTop, oldRight, oldBottom) -> {
+ if (bottom != oldBottom || top != oldTop) {
+ updatePaint();
+ }
+ };
+
+ public static final CharSequence FORMAT_12 = "hh\nmm";
+ public static final CharSequence FORMAT_24 = "HH\nmm";
+}
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardClockSwitch.java b/packages/SystemUI/src/com/android/keyguard/KeyguardClockSwitch.java
index 272954df6dd6..c6ee15fcf4e3 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardClockSwitch.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardClockSwitch.java
@@ -15,6 +15,7 @@ import android.transition.TransitionValues;
import android.util.AttributeSet;
import android.util.Log;
import android.util.MathUtils;
+import android.util.TypedValue;
import android.view.View;
import android.view.ViewGroup;
import android.widget.FrameLayout;
@@ -72,6 +73,16 @@ public class KeyguardClockSwitch extends RelativeLayout {
private TextClock mClockViewBold;
/**
+ * Gradient clock for usage when mode != KeyguardUpdateMonitor.LOCK_SCREEN_MODE_NORMAL.
+ */
+ private TimeBasedColorsClockController mNewLockscreenClockViewController;
+
+ /**
+ * Frame for clock when mode != KeyguardUpdateMonitor.LOCK_SCREEN_MODE_NORMAL.
+ */
+ private FrameLayout mNewLockscreenClockFrame;
+
+ /**
* Frame for default and custom clock.
*/
private FrameLayout mSmallClockFrame;
@@ -137,23 +148,28 @@ public class KeyguardClockSwitch extends RelativeLayout {
mLockScreenMode = mode;
RelativeLayout.LayoutParams statusAreaLP = (RelativeLayout.LayoutParams)
mKeyguardStatusArea.getLayoutParams();
- RelativeLayout.LayoutParams clockLP = (RelativeLayout.LayoutParams)
- mSmallClockFrame.getLayoutParams();
if (mode == KeyguardUpdateMonitor.LOCK_SCREEN_MODE_LAYOUT_1) {
+ final int startEndPadding = (int) TypedValue.applyDimension(
+ TypedValue.COMPLEX_UNIT_DIP,
+ 12,
+ getResources().getDisplayMetrics());
+ setPaddingRelative(startEndPadding, 0, startEndPadding, 0);
+ mSmallClockFrame.setVisibility(GONE);
+ mNewLockscreenClockFrame.setVisibility(VISIBLE);
+ mNewLockscreenClockViewController.init();
+
statusAreaLP.removeRule(RelativeLayout.BELOW);
- statusAreaLP.addRule(RelativeLayout.LEFT_OF, R.id.clock_view);
+ statusAreaLP.addRule(RelativeLayout.LEFT_OF, R.id.new_lockscreen_clock_view);
statusAreaLP.addRule(RelativeLayout.ALIGN_PARENT_START);
-
- clockLP.addRule(RelativeLayout.ALIGN_PARENT_END);
- clockLP.width = ViewGroup.LayoutParams.WRAP_CONTENT;
} else {
+ setPaddingRelative(0, 0, 0, 0);
+ mSmallClockFrame.setVisibility(VISIBLE);
+ mNewLockscreenClockFrame.setVisibility(GONE);
+
statusAreaLP.removeRule(RelativeLayout.LEFT_OF);
statusAreaLP.removeRule(RelativeLayout.ALIGN_PARENT_START);
statusAreaLP.addRule(RelativeLayout.BELOW, R.id.clock_view);
-
- clockLP.removeRule(RelativeLayout.ALIGN_PARENT_END);
- clockLP.width = ViewGroup.LayoutParams.MATCH_PARENT;
}
requestLayout();
@@ -164,6 +180,9 @@ public class KeyguardClockSwitch extends RelativeLayout {
super.onFinishInflate();
mClockView = findViewById(R.id.default_clock_view);
mClockViewBold = findViewById(R.id.default_clock_view_bold);
+ mNewLockscreenClockFrame = findViewById(R.id.new_lockscreen_clock_view);
+ mNewLockscreenClockViewController =
+ new TimeBasedColorsClockController(findViewById(R.id.gradient_clock_view));
mSmallClockFrame = findViewById(R.id.clock_view);
mKeyguardStatusArea = findViewById(R.id.keyguard_status_area);
}
@@ -286,6 +305,7 @@ public class KeyguardClockSwitch extends RelativeLayout {
if (mClockPlugin != null) {
mClockPlugin.setDarkAmount(darkAmount);
}
+ mNewLockscreenClockViewController.setDarkAmount(darkAmount);
updateBigClockAlpha();
}
@@ -336,6 +356,7 @@ public class KeyguardClockSwitch extends RelativeLayout {
* Refresh the time of the clock, due to either time tick broadcast or doze time tick alarm.
*/
public void refresh() {
+ mNewLockscreenClockViewController.refreshTime(System.currentTimeMillis());
mClockView.refreshTime();
mClockViewBold.refreshTime();
if (mClockPlugin != null) {
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardRootViewController.java b/packages/SystemUI/src/com/android/keyguard/KeyguardRootViewController.java
index 5c125fcc95cb..4e375c2d1227 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardRootViewController.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardRootViewController.java
@@ -19,7 +19,7 @@ package com.android.keyguard;
import android.view.ViewGroup;
import com.android.keyguard.dagger.KeyguardBouncerScope;
-import com.android.keyguard.dagger.RootView;
+import com.android.systemui.dagger.qualifiers.RootView;
import com.android.systemui.statusbar.phone.KeyguardBouncer;
import com.android.systemui.util.ViewController;
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardSliceView.java b/packages/SystemUI/src/com/android/keyguard/KeyguardSliceView.java
index a479bca56c2a..a9c06edf46cc 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardSliceView.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardSliceView.java
@@ -33,9 +33,11 @@ import android.text.TextUtils;
import android.text.TextUtils.TruncateAt;
import android.util.AttributeSet;
import android.util.TypedValue;
+import android.view.Gravity;
import android.view.View;
import android.view.animation.Animation;
import android.widget.LinearLayout;
+import android.widget.RelativeLayout;
import android.widget.TextView;
import androidx.slice.SliceItem;
@@ -55,8 +57,10 @@ import com.android.systemui.util.wakelock.KeepAwakeAnimationListener;
import java.io.FileDescriptor;
import java.io.PrintWriter;
import java.util.HashMap;
+import java.util.HashSet;
import java.util.List;
import java.util.Map;
+import java.util.Set;
/**
* View visible under the clock on the lock screen and AoD.
@@ -86,6 +90,8 @@ public class KeyguardSliceView extends LinearLayout {
private float mRowWithHeaderTextSize;
private View.OnClickListener mOnClickListener;
+ private int mLockScreenMode = KeyguardUpdateMonitor.LOCK_SCREEN_MODE_NORMAL;
+
public KeyguardSliceView(Context context, AttributeSet attrs) {
super(context, attrs);
@@ -142,6 +148,40 @@ public class KeyguardSliceView extends LinearLayout {
}
}
+ /**
+ * Updates the lockscreen mode which may change the layout of the keyguard slice view.
+ */
+ public void updateLockScreenMode(int mode) {
+ mLockScreenMode = mode;
+ if (mLockScreenMode == KeyguardUpdateMonitor.LOCK_SCREEN_MODE_LAYOUT_1) {
+ // add top padding to better align with top of clock
+ final int topPadding = (int) TypedValue.applyDimension(
+ TypedValue.COMPLEX_UNIT_DIP,
+ 20,
+ getResources().getDisplayMetrics());
+ mTitle.setPaddingRelative(0, topPadding, 0, 0);
+ mTitle.setGravity(Gravity.START);
+ setGravity(Gravity.START);
+ RelativeLayout.LayoutParams lp = (RelativeLayout.LayoutParams) getLayoutParams();
+ lp.removeRule(RelativeLayout.CENTER_HORIZONTAL);
+ setLayoutParams(lp);
+ } else {
+ final int horizontalPaddingDpValue = (int) TypedValue.applyDimension(
+ TypedValue.COMPLEX_UNIT_DIP,
+ 44,
+ getResources().getDisplayMetrics()
+ );
+ mTitle.setPaddingRelative(horizontalPaddingDpValue, 0, horizontalPaddingDpValue, 0);
+ mTitle.setGravity(Gravity.CENTER_HORIZONTAL);
+ setGravity(Gravity.CENTER_HORIZONTAL);
+ RelativeLayout.LayoutParams lp = (RelativeLayout.LayoutParams) getLayoutParams();
+ lp.addRule(RelativeLayout.CENTER_HORIZONTAL);
+ setLayoutParams(lp);
+ }
+ mRow.setLockscreenMode(mode);
+ requestLayout();
+ }
+
Map<View, PendingIntent> showSlice(RowContent header, List<SliceContent> subItems) {
Trace.beginSection("KeyguardSliceView#showSlice");
mHasHeader = header != null;
@@ -166,6 +206,8 @@ public class KeyguardSliceView extends LinearLayout {
final int startIndex = mHasHeader ? 1 : 0; // First item is header; skip it
mRow.setVisibility(subItemsCount > 0 ? VISIBLE : GONE);
LinearLayout.LayoutParams layoutParams = (LayoutParams) mRow.getLayoutParams();
+ layoutParams.gravity = mLockScreenMode != KeyguardUpdateMonitor.LOCK_SCREEN_MODE_NORMAL
+ ? Gravity.START : Gravity.CENTER;
layoutParams.topMargin = mHasHeader ? mRowWithHeaderPadding : mRowPadding;
mRow.setLayoutParams(layoutParams);
@@ -282,6 +324,7 @@ public class KeyguardSliceView extends LinearLayout {
pw.println(" mTextColor: " + Integer.toHexString(mTextColor));
pw.println(" mDarkAmount: " + mDarkAmount);
pw.println(" mHasHeader: " + mHasHeader);
+ pw.println(" mLockScreenMode: " + mLockScreenMode);
}
@Override
@@ -291,6 +334,8 @@ public class KeyguardSliceView extends LinearLayout {
}
public static class Row extends LinearLayout {
+ private Set<KeyguardSliceTextView> mKeyguardSliceTextViewSet = new HashSet();
+ private int mLockScreenModeRow = KeyguardUpdateMonitor.LOCK_SCREEN_MODE_NORMAL;
/**
* This view is visible in AOD, which means that the device will sleep if we
@@ -361,12 +406,18 @@ public class KeyguardSliceView extends LinearLayout {
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
int width = MeasureSpec.getSize(widthMeasureSpec);
int childCount = getChildCount();
+
for (int i = 0; i < childCount; i++) {
View child = getChildAt(i);
if (child instanceof KeyguardSliceTextView) {
- ((KeyguardSliceTextView) child).setMaxWidth(width / 3);
+ if (mLockScreenModeRow == KeyguardUpdateMonitor.LOCK_SCREEN_MODE_LAYOUT_1) {
+ ((KeyguardSliceTextView) child).setMaxWidth(Integer.MAX_VALUE);
+ } else {
+ ((KeyguardSliceTextView) child).setMaxWidth(width / 3);
+ }
}
}
+
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
}
@@ -384,6 +435,42 @@ public class KeyguardSliceView extends LinearLayout {
public boolean hasOverlappingRendering() {
return false;
}
+
+ @Override
+ public void addView(View view, int index) {
+ super.addView(view, index);
+
+ if (view instanceof KeyguardSliceTextView) {
+ ((KeyguardSliceTextView) view).setLockScreenMode(mLockScreenModeRow);
+ mKeyguardSliceTextViewSet.add((KeyguardSliceTextView) view);
+ }
+ }
+
+ @Override
+ public void removeView(View view) {
+ super.removeView(view);
+ if (view instanceof KeyguardSliceTextView) {
+ mKeyguardSliceTextViewSet.remove((KeyguardSliceTextView) view);
+ }
+ }
+
+ /**
+ * Updates the lockscreen mode which may change the layout of this view.
+ */
+ public void setLockscreenMode(int mode) {
+ mLockScreenModeRow = mode;
+ if (mLockScreenModeRow == KeyguardUpdateMonitor.LOCK_SCREEN_MODE_LAYOUT_1) {
+ setOrientation(LinearLayout.VERTICAL);
+ setGravity(Gravity.START);
+ } else {
+ setOrientation(LinearLayout.HORIZONTAL);
+ setGravity(Gravity.CENTER);
+ }
+
+ for (KeyguardSliceTextView textView : mKeyguardSliceTextViewSet) {
+ textView.setLockScreenMode(mLockScreenModeRow);
+ }
+ }
}
/**
@@ -392,6 +479,7 @@ public class KeyguardSliceView extends LinearLayout {
@VisibleForTesting
static class KeyguardSliceTextView extends TextView implements
ConfigurationController.ConfigurationListener {
+ private int mLockScreenMode = KeyguardUpdateMonitor.LOCK_SCREEN_MODE_NORMAL;
@StyleRes
private static int sStyleId = R.style.TextAppearance_Keyguard_Secondary;
@@ -432,9 +520,16 @@ public class KeyguardSliceView extends LinearLayout {
private void updatePadding() {
boolean hasText = !TextUtils.isEmpty(getText());
- int horizontalPadding = (int) getContext().getResources()
+ int padding = (int) getContext().getResources()
.getDimension(R.dimen.widget_horizontal_padding) / 2;
- setPadding(horizontalPadding, 0, horizontalPadding * (hasText ? 1 : -1), 0);
+ if (mLockScreenMode == KeyguardUpdateMonitor.LOCK_SCREEN_MODE_LAYOUT_1) {
+ // orientation is vertical, so add padding to top & bottom
+ setPadding(0, padding, 0, padding * (hasText ? 1 : -1));
+ } else {
+ // oreintation is horizontal, so add padding to left & right
+ setPadding(padding, 0, padding * (hasText ? 1 : -1), 0);
+ }
+
setCompoundDrawablePadding((int) mContext.getResources()
.getDimension(R.dimen.widget_icon_padding));
}
@@ -461,5 +556,18 @@ public class KeyguardSliceView extends LinearLayout {
}
}
}
+
+ /**
+ * Updates the lockscreen mode which may change the layout of this view.
+ */
+ public void setLockScreenMode(int mode) {
+ mLockScreenMode = mode;
+ if (mLockScreenMode == KeyguardUpdateMonitor.LOCK_SCREEN_MODE_LAYOUT_1) {
+ setGravity(Gravity.START);
+ } else {
+ setGravity(Gravity.CENTER);
+ }
+ updatePadding();
+ }
}
}
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardSliceViewController.java b/packages/SystemUI/src/com/android/keyguard/KeyguardSliceViewController.java
index 3be7e0a2b0b3..8b55b06e5e5e 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardSliceViewController.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardSliceViewController.java
@@ -44,6 +44,7 @@ import com.android.systemui.keyguard.KeyguardSliceProvider;
import com.android.systemui.plugins.ActivityStarter;
import com.android.systemui.statusbar.policy.ConfigurationController;
import com.android.systemui.tuner.TunerService;
+import com.android.systemui.util.ViewController;
import java.io.FileDescriptor;
import java.io.PrintWriter;
@@ -55,10 +56,10 @@ import javax.inject.Inject;
/** Controller for a {@link KeyguardSliceView}. */
@KeyguardStatusViewScope
-public class KeyguardSliceViewController implements Dumpable {
+public class KeyguardSliceViewController extends ViewController<KeyguardSliceView> implements
+ Dumpable {
private static final String TAG = "KeyguardSliceViewCtrl";
- private final KeyguardSliceView mView;
private final ActivityStarter mActivityStarter;
private final ConfigurationController mConfigurationController;
private final TunerService mTunerService;
@@ -68,41 +69,7 @@ public class KeyguardSliceViewController implements Dumpable {
private Uri mKeyguardSliceUri;
private Slice mSlice;
private Map<View, PendingIntent> mClickActions;
-
- private final View.OnAttachStateChangeListener mOnAttachStateChangeListener =
- new View.OnAttachStateChangeListener() {
-
- @Override
- public void onViewAttachedToWindow(View v) {
-
- Display display = mView.getDisplay();
- if (display != null) {
- mDisplayId = display.getDisplayId();
- }
- mTunerService.addTunable(mTunable, Settings.Secure.KEYGUARD_SLICE_URI);
- // Make sure we always have the most current slice
- if (mDisplayId == DEFAULT_DISPLAY && mLiveData != null) {
- mLiveData.observeForever(mObserver);
- }
- mConfigurationController.addCallback(mConfigurationListener);
- mDumpManager.registerDumpable(
- TAG + "@" + Integer.toHexString(
- KeyguardSliceViewController.this.hashCode()),
- KeyguardSliceViewController.this);
- }
-
- @Override
- public void onViewDetachedFromWindow(View v) {
-
- // TODO(b/117344873) Remove below work around after this issue be fixed.
- if (mDisplayId == DEFAULT_DISPLAY) {
- mLiveData.removeObserver(mObserver);
- }
- mTunerService.removeTunable(mTunable);
- mConfigurationController.removeCallback(mConfigurationListener);
- mDumpManager.unregisterDumpable(TAG);
- }
- };
+ private int mLockScreenMode = KeyguardUpdateMonitor.LOCK_SCREEN_MODE_NORMAL;
TunerService.Tunable mTunable = (key, newValue) -> setupUri(newValue);
@@ -133,24 +100,57 @@ public class KeyguardSliceViewController implements Dumpable {
};
@Inject
- public KeyguardSliceViewController(KeyguardSliceView keyguardSliceView,
+ public KeyguardSliceViewController(
+ KeyguardSliceView keyguardSliceView,
ActivityStarter activityStarter,
- ConfigurationController configurationController, TunerService tunerService,
+ ConfigurationController configurationController,
+ TunerService tunerService,
DumpManager dumpManager) {
- mView = keyguardSliceView;
+ super(keyguardSliceView);
mActivityStarter = activityStarter;
mConfigurationController = configurationController;
mTunerService = tunerService;
mDumpManager = dumpManager;
}
- /** Initialize the controller. */
- public void init() {
- if (mView.isAttachedToWindow()) {
- mOnAttachStateChangeListener.onViewAttachedToWindow(mView);
+ @Override
+ protected void onViewAttached() {
+ Display display = mView.getDisplay();
+ if (display != null) {
+ mDisplayId = display.getDisplayId();
+ }
+ mTunerService.addTunable(mTunable, Settings.Secure.KEYGUARD_SLICE_URI);
+ // Make sure we always have the most current slice
+ if (mDisplayId == DEFAULT_DISPLAY && mLiveData != null) {
+ mLiveData.observeForever(mObserver);
+ }
+ mConfigurationController.addCallback(mConfigurationListener);
+ mDumpManager.registerDumpable(
+ TAG + "@" + Integer.toHexString(
+ KeyguardSliceViewController.this.hashCode()),
+ KeyguardSliceViewController.this);
+ mView.updateLockScreenMode(mLockScreenMode);
+ }
+
+ @Override
+ protected void onViewDetached() {
+ // TODO(b/117344873) Remove below work around after this issue be fixed.
+ if (mDisplayId == DEFAULT_DISPLAY) {
+ mLiveData.removeObserver(mObserver);
}
- mView.addOnAttachStateChangeListener(mOnAttachStateChangeListener);
- mView.setOnClickListener(mOnClickListener);
+ mTunerService.removeTunable(mTunable);
+ mConfigurationController.removeCallback(mConfigurationListener);
+ mDumpManager.unregisterDumpable(
+ TAG + "@" + Integer.toHexString(
+ KeyguardSliceViewController.this.hashCode()));
+ }
+
+ /**
+ * Updates the lockscreen mode which may change the layout of the keyguard slice view.
+ */
+ public void updateLockScreenMode(int mode) {
+ mLockScreenMode = mode;
+ mView.updateLockScreenMode(mLockScreenMode);
}
/**
@@ -224,10 +224,10 @@ public class KeyguardSliceViewController implements Dumpable {
Trace.endSection();
}
-
@Override
public void dump(@NonNull FileDescriptor fd, @NonNull PrintWriter pw, @NonNull String[] args) {
pw.println(" mSlice: " + mSlice);
pw.println(" mClickActions: " + mClickActions);
+ pw.println(" mLockScreenMode: " + mLockScreenMode);
}
}
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardStatusViewController.java b/packages/SystemUI/src/com/android/keyguard/KeyguardStatusViewController.java
index 0efb5eea4217..7705db4e3147 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardStatusViewController.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardStatusViewController.java
@@ -267,6 +267,7 @@ public class KeyguardStatusViewController extends ViewController<KeyguardStatusV
@Override
public void onLockScreenModeChanged(int mode) {
mKeyguardClockSwitchController.updateLockScreenMode(mode);
+ mKeyguardSliceViewController.updateLockScreenMode(mode);
}
@Override
diff --git a/packages/SystemUI/src/com/android/keyguard/TimeBasedColorsClockController.java b/packages/SystemUI/src/com/android/keyguard/TimeBasedColorsClockController.java
new file mode 100644
index 000000000000..3cbae0a18937
--- /dev/null
+++ b/packages/SystemUI/src/com/android/keyguard/TimeBasedColorsClockController.java
@@ -0,0 +1,178 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.keyguard;
+
+import android.util.MathUtils;
+
+import com.android.internal.graphics.ColorUtils;
+import com.android.settingslib.Utils;
+import com.android.systemui.R;
+import com.android.systemui.util.ViewController;
+
+import java.util.Calendar;
+import java.util.GregorianCalendar;
+
+/**
+ * Changes the color of the text clock based on the time of day.
+ */
+public class TimeBasedColorsClockController extends ViewController<GradientTextClock> {
+ private final int[] mGradientColors = new int[3];
+ private final float[] mPositions = new float[3];
+
+ /**
+ * 0 = fully awake
+ * between 0 and 1 = transitioning between awake and doze
+ * 1 = fully in doze
+ */
+ private float mDarkAmount = 0f;
+
+ public TimeBasedColorsClockController(GradientTextClock view) {
+ super(view);
+ }
+
+ @Override
+ protected void onViewAttached() {
+ refreshTime(System.currentTimeMillis());
+ }
+
+ @Override
+ protected void onViewDetached() {
+
+ }
+
+ /**
+ * Updates the time for this view. Also updates any color changes.
+ */
+ public void refreshTime(long timeInMillis) {
+ updateColors(timeInMillis);
+ updatePositions(timeInMillis);
+ mView.refreshTime();
+ }
+
+ /**
+ * Set the amount (ratio) that the device has transitioned to doze.
+ *
+ * @param darkAmount Amount of transition to doze: 1f for doze and 0f for awake.
+ */
+ public void setDarkAmount(float darkAmount) {
+ mDarkAmount = darkAmount;
+
+ // TODO: (b/170228350) currently this relayouts throughout the animation;
+ // eventually this should use new Text APIs to animate the variable font weight
+ refreshTime(System.currentTimeMillis());
+
+ int weight = (int) MathUtils.lerp(200, 400, 1f - darkAmount);
+ mView.setFontVariationSettings("'wght' " + weight);
+ }
+
+ private int getTimeIndex(long timeInMillis) {
+ Calendar now = getCalendar(timeInMillis);
+ int hour = now.get(Calendar.HOUR_OF_DAY); // 0 - 23
+ if (hour < mTimes[0]) {
+ return mTimes.length - 1;
+ }
+
+ for (int i = 1; i < mTimes.length; i++) {
+ if (hour < mTimes[i]) {
+ return i - 1;
+ }
+ }
+
+ return mTimes.length - 1;
+ }
+
+ private void updateColors(long timeInMillis) {
+ final int index = getTimeIndex(timeInMillis);
+ final int wallpaperTextColor =
+ Utils.getColorAttrDefaultColor(mView.getContext(), R.attr.wallpaperTextColor);
+ for (int i = 0; i < mGradientColors.length; i++) {
+ // wallpaperTextColor on LS when mDarkAmount = 0f
+ // full color on AOD when mDarkAmount = 1f
+ mGradientColors[i] =
+ ColorUtils.blendARGB(wallpaperTextColor, COLORS[index][i], mDarkAmount);
+ }
+ mView.setGradientColors(mGradientColors);
+ }
+
+ private void updatePositions(long timeInMillis) {
+ Calendar now = getCalendar(timeInMillis);
+ final int index = getTimeIndex(timeInMillis);
+
+ final Calendar startTime = new GregorianCalendar();
+ startTime.setTimeInMillis(now.getTimeInMillis());
+ startTime.set(Calendar.HOUR_OF_DAY, mTimes[index]);
+ if (startTime.getTimeInMillis() > now.getTimeInMillis()) {
+ // start should be earlier than 'now'
+ startTime.add(Calendar.DATE, -1);
+ }
+
+ final Calendar endTime = new GregorianCalendar();
+ endTime.setTimeInMillis(now.getTimeInMillis());
+ if (index == mTimes.length - 1) {
+ endTime.set(Calendar.HOUR_OF_DAY, mTimes[0]);
+ endTime.add(Calendar.DATE, 1); // end time is tomorrow
+ } else {
+ endTime.set(Calendar.HOUR_OF_DAY, mTimes[index + 1]);
+ }
+
+ long totalTimeInThisColorGradient = endTime.getTimeInMillis() - startTime.getTimeInMillis();
+ long timeIntoThisColorGradient = now.getTimeInMillis() - startTime.getTimeInMillis();
+ float percentageWithinGradient =
+ (float) timeIntoThisColorGradient / (float) totalTimeInThisColorGradient;
+
+ for (int i = 0; i < mPositions.length; i++) {
+ // currently hard-coded .3 movement of gradient
+ mPositions[i] = POSITIONS[index][i] - (.3f * percentageWithinGradient);
+ }
+ mView.setColorPositions(mPositions);
+ }
+
+ private Calendar getCalendar(long timeInMillis) {
+ Calendar now = new GregorianCalendar();
+ now.setTimeInMillis(timeInMillis);
+ return now;
+ }
+
+ private static final int[] SUNRISE = new int[] {0xFF6F75AA, 0xFFAFF0FF, 0xFFFFDEBF};
+ private static final int[] DAY = new int[] {0xFF9BD8FB, 0xFFD7F5FF, 0xFFFFF278};
+ private static final int[] NIGHT = new int[] {0xFF333D5E, 0xFFC5A1D6, 0xFF907359};
+
+ private static final float[] SUNRISE_START_POSITIONS = new float[] {.3f, .5f, .8f};
+ private static final float[] DAY_START_POSITIONS = new float[] {.4f, .8f, 1f};
+ private static final float[] NIGHT_START_POSITIONS = new float[] {.25f, .5f, .8f};
+
+ // TODO (b/170228350): use TwilightManager to set sunrise/sunset times
+ private final int mSunriseTime = 6; // 6am
+ private final int mDaytime = 9; // 9 am
+ private final int mNightTime = 19; // 7pm
+
+ private int[] mTimes = new int[] {
+ mSunriseTime,
+ mDaytime,
+ mNightTime
+ };
+ private static final int[][] COLORS = new int[][] {
+ SUNRISE,
+ DAY,
+ NIGHT
+ };
+ private static final float[][] POSITIONS = new float[][] {
+ SUNRISE_START_POSITIONS,
+ DAY_START_POSITIONS,
+ NIGHT_START_POSITIONS
+ };
+}
diff --git a/packages/SystemUI/src/com/android/keyguard/dagger/KeyguardBouncerModule.java b/packages/SystemUI/src/com/android/keyguard/dagger/KeyguardBouncerModule.java
index 881108858b51..4fad9a916d0d 100644
--- a/packages/SystemUI/src/com/android/keyguard/dagger/KeyguardBouncerModule.java
+++ b/packages/SystemUI/src/com/android/keyguard/dagger/KeyguardBouncerModule.java
@@ -24,6 +24,7 @@ import com.android.keyguard.KeyguardMessageArea;
import com.android.keyguard.KeyguardSecurityContainer;
import com.android.keyguard.KeyguardSecurityViewFlipper;
import com.android.systemui.R;
+import com.android.systemui.dagger.qualifiers.RootView;
import com.android.systemui.statusbar.phone.KeyguardBouncer;
import dagger.Module;
diff --git a/packages/SystemUI/src/com/android/systemui/Dependency.java b/packages/SystemUI/src/com/android/systemui/Dependency.java
index 9f28e0936d7f..8ac6edb9dfa2 100644
--- a/packages/SystemUI/src/com/android/systemui/Dependency.java
+++ b/packages/SystemUI/src/com/android/systemui/Dependency.java
@@ -119,13 +119,11 @@ import com.android.systemui.statusbar.policy.ZenModeController;
import com.android.systemui.tracing.ProtoTracer;
import com.android.systemui.tuner.TunablePadding.TunablePaddingService;
import com.android.systemui.tuner.TunerService;
+import com.android.systemui.util.DeviceConfigProxy;
import com.android.systemui.util.leak.GarbageMonitor;
import com.android.systemui.util.leak.LeakDetector;
import com.android.systemui.util.leak.LeakReporter;
import com.android.systemui.util.sensors.AsyncSensorManager;
-import com.android.wm.shell.common.DisplayController;
-import com.android.wm.shell.common.DisplayImeController;
-import com.android.wm.shell.common.SystemWindows;
import java.util.concurrent.Executor;
import java.util.function.Consumer;
@@ -340,12 +338,10 @@ public class Dependency {
@Inject Lazy<CommandQueue> mCommandQueue;
@Inject Lazy<Recents> mRecents;
@Inject Lazy<StatusBar> mStatusBar;
- @Inject Lazy<DisplayController> mDisplayController;
- @Inject Lazy<SystemWindows> mSystemWindows;
- @Inject Lazy<DisplayImeController> mDisplayImeController;
@Inject Lazy<RecordingController> mRecordingController;
@Inject Lazy<ProtoTracer> mProtoTracer;
@Inject Lazy<MediaOutputDialogFactory> mMediaOutputDialogFactory;
+ @Inject Lazy<DeviceConfigProxy> mDeviceConfigProxy;
@Inject
public Dependency() {
@@ -530,10 +526,8 @@ public class Dependency {
mProviders.put(CommandQueue.class, mCommandQueue::get);
mProviders.put(Recents.class, mRecents::get);
mProviders.put(StatusBar.class, mStatusBar::get);
- mProviders.put(DisplayController.class, mDisplayController::get);
- mProviders.put(SystemWindows.class, mSystemWindows::get);
- mProviders.put(DisplayImeController.class, mDisplayImeController::get);
mProviders.put(ProtoTracer.class, mProtoTracer::get);
+ mProviders.put(DeviceConfigProxy.class, mDeviceConfigProxy::get);
// TODO(b/118592525): to support multi-display , we start to add something which is
// per-display, while others may be global. I think it's time to add
diff --git a/packages/SystemUI/src/com/android/systemui/SystemUIApplication.java b/packages/SystemUI/src/com/android/systemui/SystemUIApplication.java
index 7dcec3d75367..3348bd1d1e23 100644
--- a/packages/SystemUI/src/com/android/systemui/SystemUIApplication.java
+++ b/packages/SystemUI/src/com/android/systemui/SystemUIApplication.java
@@ -19,15 +19,18 @@ package com.android.systemui;
import android.app.ActivityThread;
import android.app.Application;
import android.content.BroadcastReceiver;
+import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.pm.ApplicationInfo;
+import android.content.pm.PackageManager;
import android.content.res.Configuration;
import android.os.Process;
import android.os.SystemProperties;
import android.os.Trace;
import android.os.UserHandle;
+import android.provider.Settings;
import android.util.Log;
import android.util.TimingsTraceLog;
@@ -35,6 +38,8 @@ import com.android.systemui.dagger.ContextComponentHelper;
import com.android.systemui.dagger.GlobalRootComponent;
import com.android.systemui.dagger.SysUIComponent;
import com.android.systemui.dump.DumpManager;
+import com.android.systemui.people.PeopleSpaceActivity;
+import com.android.systemui.people.widget.PeopleSpaceWidgetProvider;
import com.android.systemui.util.NotificationChannels;
import java.lang.reflect.Constructor;
@@ -104,6 +109,35 @@ public class SystemUIApplication extends Application implements
mServices[i].onBootCompleted();
}
}
+ // If flag SHOW_PEOPLE_SPACE is true, enable People Space launcher icon.
+ // TODO(b/170396074): Remove this when we don't need an icon anymore.
+ try {
+ int showPeopleSpace = Settings.Global.getInt(context.getContentResolver(),
+ Settings.Global.SHOW_PEOPLE_SPACE);
+ context.getPackageManager().setComponentEnabledSetting(
+ new ComponentName(context, PeopleSpaceActivity.class),
+ showPeopleSpace == 1
+ ? PackageManager.COMPONENT_ENABLED_STATE_ENABLED
+ : PackageManager.COMPONENT_ENABLED_STATE_DISABLED,
+ PackageManager.DONT_KILL_APP);
+ } catch (Exception e) {
+ Log.w(TAG, "Error enabling People Space launch icon:", e);
+ }
+
+ // If SHOW_PEOPLE_SPACE is true, enable People Space widget provider.
+ // TODO(b/170396074): Remove this when we don't need a widget anymore.
+ try {
+ int showPeopleSpace = Settings.Global.getInt(context.getContentResolver(),
+ Settings.Global.SHOW_PEOPLE_SPACE);
+ context.getPackageManager().setComponentEnabledSetting(
+ new ComponentName(context, PeopleSpaceWidgetProvider.class),
+ showPeopleSpace == 1
+ ? PackageManager.COMPONENT_ENABLED_STATE_ENABLED
+ : PackageManager.COMPONENT_ENABLED_STATE_DISABLED,
+ PackageManager.DONT_KILL_APP);
+ } catch (Exception e) {
+ Log.w(TAG, "Error enabling People Space widget:", e);
+ }
}
}, bootCompletedFilter);
diff --git a/packages/SystemUI/src/com/android/systemui/SystemUIFactory.java b/packages/SystemUI/src/com/android/systemui/SystemUIFactory.java
index 80253b424335..bdd0b55b27ea 100644
--- a/packages/SystemUI/src/com/android/systemui/SystemUIFactory.java
+++ b/packages/SystemUI/src/com/android/systemui/SystemUIFactory.java
@@ -30,6 +30,7 @@ import com.android.systemui.dagger.WMComponent;
import com.android.systemui.navigationbar.gestural.BackGestureTfClassifierProvider;
import com.android.systemui.screenshot.ScreenshotNotificationSmartActionsProvider;
+import java.util.Optional;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Executor;
@@ -49,6 +50,11 @@ public class SystemUIFactory {
}
public static void createFromConfig(Context context) {
+ createFromConfig(context, false);
+ }
+
+ @VisibleForTesting
+ public static void createFromConfig(Context context, boolean fromTest) {
if (mFactory != null) {
return;
}
@@ -62,7 +68,7 @@ public class SystemUIFactory {
Class<?> cls = null;
cls = context.getClassLoader().loadClass(clsName);
mFactory = (SystemUIFactory) cls.newInstance();
- mFactory.init(context);
+ mFactory.init(context, fromTest);
} catch (Throwable t) {
Log.w(TAG, "Error creating SystemUIFactory component: " + clsName, t);
throw new RuntimeException(t);
@@ -76,16 +82,40 @@ public class SystemUIFactory {
public SystemUIFactory() {}
- private void init(Context context) throws ExecutionException, InterruptedException {
+ @VisibleForTesting
+ public void init(Context context, boolean fromTest)
+ throws ExecutionException, InterruptedException {
+ final boolean initializeComponents = !fromTest
+ && android.os.Process.myUserHandle().isSystem();
mRootComponent = buildGlobalRootComponent(context);
// Stand up WMComponent
mWMComponent = mRootComponent.getWMComponentBuilder().build();
+ if (initializeComponents) {
+ // Only initialize when not starting from tests since this currently initializes some
+ // components that shouldn't be run in the test environment
+ mWMComponent.init();
+ }
// And finally, retrieve whatever SysUI needs from WMShell and build SysUI.
- // TODO: StubAPIClass is just a placeholder.
- mSysUIComponent = mRootComponent.getSysUIComponent()
- .setStubAPIClass(mWMComponent.createStubAPIClass())
+ SysUIComponent.Builder builder = mRootComponent.getSysUIComponent();
+ if (initializeComponents) {
+ // Only initialize when not starting from tests since this currently initializes some
+ // components that shouldn't be run in the test environment
+ builder = builder.setPip(mWMComponent.getPip())
+ .setSplitScreen(mWMComponent.getSplitScreen())
+ .setOneHanded(mWMComponent.getOneHanded());
+ } else {
+ builder = builder.setPip(Optional.ofNullable(null))
+ .setSplitScreen(Optional.ofNullable(null))
+ .setOneHanded(Optional.ofNullable(null));
+ }
+ mSysUIComponent = builder
+ .setInputConsumerController(mWMComponent.getInputConsumerController())
+ .setShellTaskOrganizer(mWMComponent.getShellTaskOrganizer())
.build();
+ if (initializeComponents) {
+ mSysUIComponent.init();
+ }
// Every other part of our codebase currently relies on Dependency, so we
// really need to ensure the Dependency gets initialized early on.
@@ -93,6 +123,16 @@ public class SystemUIFactory {
dependency.start();
}
+ /**
+ * Prepares the SysUIComponent builder before it is built.
+ * @param sysUIBuilder the builder provided by the root component's getSysUIComponent() method
+ * @param wm the built WMComponent from the root component's getWMComponent() method
+ */
+ protected SysUIComponent.Builder prepareSysUIComponentBuilder(
+ SysUIComponent.Builder sysUIBuilder, WMComponent wm) {
+ return sysUIBuilder;
+ }
+
protected GlobalRootComponent buildGlobalRootComponent(Context context) {
return DaggerGlobalRootComponent.builder()
.context(context)
diff --git a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleController.java b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleController.java
index 3f94b00d3c60..0c3dc8222a34 100644
--- a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleController.java
+++ b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleController.java
@@ -177,6 +177,7 @@ public class BubbleController implements Bubbles, ConfigurationController.Config
private ScrimView mBubbleScrim;
@Nullable private BubbleStackView mStackView;
private BubbleIconFactory mBubbleIconFactory;
+ private BubblePositioner mBubblePositioner;
/**
* The relative position of the stack when we removed it and nulled it out. If the stack is
@@ -244,7 +245,7 @@ public class BubbleController implements Bubbles, ConfigurationController.Config
private boolean mInflateSynchronously;
- private MultiWindowTaskListener mTaskListener;
+ private ShellTaskOrganizer mTaskOrganizer;
// TODO (b/145659174): allow for multiple callbacks to support the "shadow" new notif pipeline
private final List<NotifCallback> mCallbacks = new ArrayList<>();
@@ -387,7 +388,7 @@ public class BubbleController implements Bubbles, ConfigurationController.Config
dumpManager, floatingContentCoordinator,
new BubbleDataRepository(context, launcherApps), sysUiState, notificationManager,
statusBarService, windowManager, windowManagerShellWrapper, launcherApps, logger,
- mainHandler, organizer);
+ mainHandler, organizer, new BubblePositioner(context, windowManager));
}
/**
@@ -419,7 +420,8 @@ public class BubbleController implements Bubbles, ConfigurationController.Config
LauncherApps launcherApps,
BubbleLogger bubbleLogger,
Handler mainHandler,
- ShellTaskOrganizer organizer) {
+ ShellTaskOrganizer organizer,
+ BubblePositioner positioner) {
dumpManager.registerDumpable(TAG, this);
mContext = context;
mShadeController = shadeController;
@@ -529,7 +531,8 @@ public class BubbleController implements Bubbles, ConfigurationController.Config
});
mBubbleIconFactory = new BubbleIconFactory(context);
- mTaskListener = new MultiWindowTaskListener(mMainHandler, organizer);
+ mTaskOrganizer = organizer;
+ mBubblePositioner = positioner;
launcherApps.registerCallback(new LauncherApps.Callback() {
@Override
@@ -805,8 +808,13 @@ public class BubbleController implements Bubbles, ConfigurationController.Config
}
@Override
- public MultiWindowTaskListener getTaskManager() {
- return mTaskListener;
+ public ShellTaskOrganizer getTaskOrganizer() {
+ return mTaskOrganizer;
+ }
+
+ @Override
+ public BubblePositioner getPositioner() {
+ return mBubblePositioner;
}
/**
@@ -818,9 +826,10 @@ public class BubbleController implements Bubbles, ConfigurationController.Config
mStackView = new BubbleStackView(
mContext, mBubbleData, mSurfaceSynchronizer, mFloatingContentCoordinator,
this::onAllBubblesAnimatedOut, this::onImeVisibilityChanged,
- this::hideCurrentInputMethod, this::onBubbleExpandChanged);
+ this::hideCurrentInputMethod, this::onBubbleExpandChanged, mBubblePositioner);
mStackView.setStackStartPosition(mPositionFromRemovedStack);
mStackView.addView(mBubbleScrim);
+ mStackView.onOrientationChanged();
if (mExpandListener != null) {
mStackView.setExpandListener(mExpandListener);
}
@@ -978,10 +987,14 @@ public class BubbleController implements Bubbles, ConfigurationController.Config
@Override
public void onConfigChanged(Configuration newConfig) {
+ if (mBubblePositioner != null) {
+ // This doesn't trigger any changes, always update it
+ mBubblePositioner.update(newConfig.orientation);
+ }
if (mStackView != null && newConfig != null) {
if (newConfig.orientation != mOrientation) {
mOrientation = newConfig.orientation;
- mStackView.onOrientationChanged(newConfig.orientation);
+ mStackView.onOrientationChanged();
}
if (newConfig.densityDpi != mDensityDpi) {
mDensityDpi = newConfig.densityDpi;
diff --git a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleExpandedView.java b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleExpandedView.java
index 98a2257d2daa..bc060209132b 100644
--- a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleExpandedView.java
+++ b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleExpandedView.java
@@ -38,7 +38,6 @@ import android.content.res.Resources;
import android.content.res.TypedArray;
import android.graphics.Color;
import android.graphics.Outline;
-import android.graphics.Point;
import android.graphics.Rect;
import android.graphics.drawable.ShapeDrawable;
import android.os.Bundle;
@@ -48,7 +47,6 @@ import android.view.SurfaceControl;
import android.view.View;
import android.view.ViewGroup;
import android.view.ViewOutlineProvider;
-import android.view.WindowManager;
import android.view.accessibility.AccessibilityNodeInfo;
import android.widget.FrameLayout;
import android.widget.LinearLayout;
@@ -60,6 +58,7 @@ import com.android.systemui.Dependency;
import com.android.systemui.R;
import com.android.systemui.recents.TriangleShape;
import com.android.systemui.statusbar.AlphaOptimizedButton;
+import com.android.wm.shell.common.HandlerExecutor;
import java.io.FileDescriptor;
import java.io.PrintWriter;
@@ -83,24 +82,26 @@ public class BubbleExpandedView extends LinearLayout {
private boolean mImeVisible;
private boolean mNeedsNewHeight;
- private Point mDisplaySize;
private int mMinHeight;
private int mOverflowHeight;
private int mSettingsIconHeight;
private int mPointerWidth;
private int mPointerHeight;
- private ShapeDrawable mPointerDrawable;
+ private ShapeDrawable mCurrentPointer;
+ private ShapeDrawable mTopPointer;
+ private ShapeDrawable mLeftPointer;
+ private ShapeDrawable mRightPointer;
private int mExpandedViewPadding;
private float mCornerRadius = 0f;
@Nullable private Bubble mBubble;
private PendingIntent mPendingIntent;
-
+ // TODO(b/170891664): Don't use a flag, set the BubbleOverflow object instead
private boolean mIsOverflow;
private Bubbles mBubbles = Dependency.get(Bubbles.class);
- private WindowManager mWindowManager;
private BubbleStackView mStackView;
+ private BubblePositioner mPositioner;
/**
* Container for the ActivityView that has a solid, round-rect background that shows if the
@@ -136,6 +137,7 @@ public class BubbleExpandedView extends LinearLayout {
}
try {
if (!mIsOverflow && mBubble.hasMetadataShortcutId()) {
+ options.setApplyActivityFlagsForBubbles(true);
mTaskView.startShortcutActivity(mBubble.getShortcutInfo(),
options, null /* sourceBounds */);
} else {
@@ -224,17 +226,6 @@ public class BubbleExpandedView extends LinearLayout {
updateDimensions();
}
- void updateDimensions() {
- mDisplaySize = new Point();
- mWindowManager = (WindowManager) mContext.getSystemService(Context.WINDOW_SERVICE);
- // Get the real size -- this includes screen decorations (notches, statusbar, navbar).
- mWindowManager.getDefaultDisplay().getRealSize(mDisplaySize);
- Resources res = getResources();
- mMinHeight = res.getDimensionPixelSize(R.dimen.bubble_expanded_default_height);
- mOverflowHeight = res.getDimensionPixelSize(R.dimen.bubble_overflow_height);
- mPointerMargin = res.getDimensionPixelSize(R.dimen.bubble_pointer_margin);
- }
-
@SuppressLint("ClickableViewAccessibility")
@Override
protected void onFinishInflate() {
@@ -245,15 +236,24 @@ public class BubbleExpandedView extends LinearLayout {
mPointerWidth = res.getDimensionPixelSize(R.dimen.bubble_pointer_width);
mPointerHeight = res.getDimensionPixelSize(R.dimen.bubble_pointer_height);
- mPointerDrawable = new ShapeDrawable(TriangleShape.create(
+ mTopPointer = new ShapeDrawable(TriangleShape.create(
mPointerWidth, mPointerHeight, true /* pointUp */));
+ mLeftPointer = new ShapeDrawable(TriangleShape.createHorizontal(
+ mPointerWidth, mPointerHeight, true /* pointLeft */));
+ mRightPointer = new ShapeDrawable(TriangleShape.createHorizontal(
+ mPointerWidth, mPointerHeight, false /* pointLeft */));
+
+ mCurrentPointer = mTopPointer;
mPointerView.setVisibility(INVISIBLE);
mSettingsIconHeight = getContext().getResources().getDimensionPixelSize(
R.dimen.bubble_manage_button_height);
mSettingsIcon = findViewById(R.id.settings_button);
- mTaskView = new TaskView(mContext, mBubbles.getTaskManager());
+ mPositioner = mBubbles.getPositioner();
+
+ mTaskView = new TaskView(mContext, mBubbles.getTaskOrganizer(),
+ new HandlerExecutor(getHandler()));
// Set ActivityView's alpha value as zero, since there is no view content to be shown.
setContentVisibility(false);
@@ -282,8 +282,7 @@ public class BubbleExpandedView extends LinearLayout {
applyThemeAttrs();
mExpandedViewPadding = res.getDimensionPixelSize(R.dimen.bubble_expanded_view_padding);
- setPadding(mExpandedViewPadding, mExpandedViewPadding, mExpandedViewPadding,
- mExpandedViewPadding);
+ setClipToPadding(false);
setOnTouchListener((view, motionEvent) -> {
if (mTaskView == null) {
return false;
@@ -311,6 +310,52 @@ public class BubbleExpandedView extends LinearLayout {
setLayoutDirection(LAYOUT_DIRECTION_LOCALE);
}
+ void updateDimensions() {
+ Resources res = getResources();
+ mMinHeight = res.getDimensionPixelSize(R.dimen.bubble_expanded_default_height);
+ mOverflowHeight = res.getDimensionPixelSize(R.dimen.bubble_overflow_height);
+ mPointerMargin = res.getDimensionPixelSize(R.dimen.bubble_pointer_margin);
+ }
+
+ void applyThemeAttrs() {
+ final TypedArray ta = mContext.obtainStyledAttributes(new int[] {
+ android.R.attr.dialogCornerRadius,
+ android.R.attr.colorBackgroundFloating});
+ mCornerRadius = ta.getDimensionPixelSize(0, 0);
+ mExpandedViewContainer.setBackgroundColor(ta.getColor(1, Color.WHITE));
+ ta.recycle();
+
+ if (mTaskView != null && ScreenDecorationsUtils.supportsRoundedCornersOnWindows(
+ mContext.getResources())) {
+ mTaskView.setCornerRadius(mCornerRadius);
+ }
+ updatePointerView();
+ }
+
+ private void updatePointerView() {
+ final int mode =
+ getResources().getConfiguration().uiMode & Configuration.UI_MODE_NIGHT_MASK;
+ switch (mode) {
+ case Configuration.UI_MODE_NIGHT_NO:
+ mCurrentPointer.setTint(getResources().getColor(R.color.bubbles_light));
+ break;
+ case Configuration.UI_MODE_NIGHT_YES:
+ mCurrentPointer.setTint(getResources().getColor(R.color.bubbles_dark));
+ break;
+ }
+ LayoutParams lp = (LayoutParams) mPointerView.getLayoutParams();
+ if (mCurrentPointer == mLeftPointer || mCurrentPointer == mRightPointer) {
+ lp.width = mPointerHeight;
+ lp.height = mPointerWidth;
+ } else {
+ lp.width = mPointerWidth;
+ lp.height = mPointerHeight;
+ }
+ mPointerView.setLayoutParams(lp);
+ mPointerView.setBackground(mCurrentPointer);
+ }
+
+
private String getBubbleKey() {
return mBubble != null ? mBubble.getKey() : "null";
}
@@ -371,32 +416,6 @@ public class BubbleExpandedView extends LinearLayout {
}
}
- void applyThemeAttrs() {
- final TypedArray ta = mContext.obtainStyledAttributes(new int[] {
- android.R.attr.dialogCornerRadius,
- android.R.attr.colorBackgroundFloating});
- mCornerRadius = ta.getDimensionPixelSize(0, 0);
- mExpandedViewContainer.setBackgroundColor(ta.getColor(1, Color.WHITE));
- ta.recycle();
-
- if (mTaskView != null && ScreenDecorationsUtils.supportsRoundedCornersOnWindows(
- mContext.getResources())) {
- mTaskView.setCornerRadius(mCornerRadius);
- }
-
- final int mode =
- getResources().getConfiguration().uiMode & Configuration.UI_MODE_NIGHT_MASK;
- switch (mode) {
- case Configuration.UI_MODE_NIGHT_NO:
- mPointerDrawable.setTint(getResources().getColor(R.color.bubbles_light));
- break;
- case Configuration.UI_MODE_NIGHT_YES:
- mPointerDrawable.setTint(getResources().getColor(R.color.bubbles_dark));
- break;
- }
- mPointerView.setBackground(mPointerDrawable);
- }
-
@Override
protected void onDetachedFromWindow() {
super.onDetachedFromWindow();
@@ -522,12 +541,12 @@ public class BubbleExpandedView extends LinearLayout {
}
if (mBubble != null || mIsOverflow) {
- float desiredHeight = mOverflowHeight;
- if (!mIsOverflow) {
- desiredHeight = Math.max(mBubble.getDesiredHeight(mContext), mMinHeight);
- }
+ float desiredHeight = mIsOverflow
+ ? mOverflowHeight
+ : mBubble.getDesiredHeight(mContext);
+ desiredHeight = Math.max(desiredHeight, mMinHeight);
float height = Math.min(desiredHeight, getMaxExpandedHeight());
- height = Math.max(height, mIsOverflow ? mOverflowHeight : mMinHeight);
+ height = Math.max(height, mMinHeight);
FrameLayout.LayoutParams lp = (FrameLayout.LayoutParams) mTaskView.getLayoutParams();
mNeedsNewHeight = lp.height != height;
if (!mImeVisible) {
@@ -546,21 +565,17 @@ public class BubbleExpandedView extends LinearLayout {
}
private int getMaxExpandedHeight() {
- mWindowManager.getDefaultDisplay().getRealSize(mDisplaySize);
int expandedContainerY = mExpandedViewContainerLocation != null
- ? mExpandedViewContainerLocation[1]
+ // Remove top insets back here because availableRect.height would account for that
+ ? mExpandedViewContainerLocation[1] - mPositioner.getInsets().top
: 0;
- int bottomInset = getRootWindowInsets() != null
- ? getRootWindowInsets().getStableInsetBottom()
- : 0;
-
- return mDisplaySize.y
+ return mPositioner.getAvailableRect().height()
- expandedContainerY
- getPaddingTop()
- getPaddingBottom()
- mSettingsIconHeight
- mPointerHeight
- - mPointerMargin - bottomInset;
+ - mPointerMargin;
}
/**
@@ -585,12 +600,25 @@ public class BubbleExpandedView extends LinearLayout {
}
/**
- * Set the x position that the tip of the triangle should point to.
+ * Set the position that the tip of the triangle should point to.
*/
- public void setPointerPosition(float x) {
- float halfPointerWidth = mPointerWidth / 2f;
- float pointerLeft = x - halfPointerWidth - mExpandedViewPadding;
- mPointerView.setTranslationX(pointerLeft);
+ public void setPointerPosition(float x, float y, boolean isLandscape, boolean onLeft) {
+ // Pointer gets drawn in the padding
+ int paddingLeft = (isLandscape && onLeft) ? mPointerHeight : 0;
+ int paddingRight = (isLandscape && !onLeft) ? mPointerHeight : 0;
+ int paddingTop = isLandscape ? 0 : mExpandedViewPadding;
+ setPadding(paddingLeft, paddingTop, paddingRight, 0);
+
+ if (isLandscape) {
+ // TODO: why setY vs setTranslationY ? linearlayout?
+ mPointerView.setY(y - (mPointerWidth / 2f));
+ mPointerView.setTranslationX(onLeft ? -mPointerHeight : x - mExpandedViewPadding);
+ } else {
+ mPointerView.setTranslationY(0f);
+ mPointerView.setTranslationX(x - mExpandedViewPadding - (mPointerWidth / 2f));
+ }
+ mCurrentPointer = isLandscape ? onLeft ? mLeftPointer : mRightPointer : mTopPointer;
+ updatePointerView();
mPointerView.setVisibility(VISIBLE);
}
diff --git a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleFlyoutView.java b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleFlyoutView.java
index 009114ffa0be..d8b32500db85 100644
--- a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleFlyoutView.java
+++ b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleFlyoutView.java
@@ -61,7 +61,8 @@ public class BubbleFlyoutView extends FrameLayout {
/** Translation Y of fade animation. */
private static final float FLYOUT_FADE_Y = 40f;
- private static final long FLYOUT_FADE_DURATION = 200L;
+ private static final long FLYOUT_FADE_OUT_DURATION = 150L;
+ private static final long FLYOUT_FADE_IN_DURATION = 250L;
private final int mFlyoutPadding;
private final int mFlyoutSpaceFromBubble;
@@ -235,26 +236,32 @@ public class BubbleFlyoutView extends FrameLayout {
* Fade animation for consecutive flyouts.
*/
void animateUpdate(Bubble.FlyoutMessage flyoutMessage, float parentWidth, float stackY) {
- fade(false /* in */);
- updateFlyoutMessage(flyoutMessage, parentWidth);
- // Wait for TextViews to layout with updated height.
- post(() -> {
- mFlyoutY = stackY + (mBubbleSize - mFlyoutTextContainer.getHeight()) / 2f;
- fade(true /* in */);
- });
+ final Runnable afterFadeOut = () -> {
+ updateFlyoutMessage(flyoutMessage, parentWidth);
+ // Wait for TextViews to layout with updated height.
+ post(() -> {
+ mFlyoutY = stackY + (mBubbleSize - mFlyoutTextContainer.getHeight()) / 2f;
+ fade(true /* in */, () -> {} /* after */);
+ } /* after */ );
+ };
+ fade(false /* in */, afterFadeOut);
}
- private void fade(boolean in) {
+ /*
+ * Fade-out above or fade-in from below.
+ */
+ private void fade(boolean in, Runnable afterFade) {
setAlpha(in ? 0f : 1f);
- setTranslationY(in ? mFlyoutY : mFlyoutY + FLYOUT_FADE_Y);
+ setTranslationY(in ? mFlyoutY + FLYOUT_FADE_Y : mFlyoutY);
animate()
.alpha(in ? 1f : 0f)
- .setDuration(FLYOUT_FADE_DURATION)
+ .setDuration(in ? FLYOUT_FADE_IN_DURATION : FLYOUT_FADE_OUT_DURATION)
.setInterpolator(in ? ALPHA_IN : ALPHA_OUT);
animate()
.translationY(in ? mFlyoutY : mFlyoutY - FLYOUT_FADE_Y)
- .setDuration(FLYOUT_FADE_DURATION)
- .setInterpolator(in ? ALPHA_IN : ALPHA_OUT);
+ .setDuration(in ? FLYOUT_FADE_IN_DURATION : FLYOUT_FADE_OUT_DURATION)
+ .setInterpolator(in ? ALPHA_IN : ALPHA_OUT)
+ .withEndAction(afterFade);
}
private void updateFlyoutMessage(Bubble.FlyoutMessage flyoutMessage, float parentWidth) {
diff --git a/packages/SystemUI/src/com/android/systemui/bubbles/BubblePositioner.java b/packages/SystemUI/src/com/android/systemui/bubbles/BubblePositioner.java
new file mode 100644
index 000000000000..029caee6364f
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/bubbles/BubblePositioner.java
@@ -0,0 +1,89 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.bubbles;
+
+import android.content.Context;
+import android.content.res.Configuration;
+import android.graphics.Insets;
+import android.graphics.Rect;
+import android.view.WindowInsets;
+import android.view.WindowManager;
+import android.view.WindowMetrics;
+
+import androidx.annotation.VisibleForTesting;
+
+/**
+ * Keeps track of display size, configuration, and specific bubble sizes. One place for all
+ * placement and positioning calculations to refer to.
+ */
+public class BubblePositioner {
+
+ private WindowManager mWindowManager;
+ private Rect mPositionRect;
+ private int mOrientation;
+ private Insets mInsets;
+
+ public BubblePositioner(Context context, WindowManager windowManager) {
+ mWindowManager = windowManager;
+ update(Configuration.ORIENTATION_UNDEFINED);
+ }
+
+ public void update(int orientation) {
+ WindowMetrics windowMetrics = mWindowManager.getCurrentWindowMetrics();
+ mPositionRect = new Rect(windowMetrics.getBounds());
+ WindowInsets metricInsets = windowMetrics.getWindowInsets();
+
+ Insets insets = metricInsets.getInsetsIgnoringVisibility(WindowInsets.Type.navigationBars()
+ | WindowInsets.Type.statusBars()
+ | WindowInsets.Type.displayCutout());
+ update(orientation, insets, windowMetrics.getBounds());
+ }
+
+ @VisibleForTesting
+ public void update(int orientation, Insets insets, Rect bounds) {
+ mOrientation = orientation;
+ mInsets = insets;
+
+ mPositionRect = new Rect(bounds);
+ mPositionRect.left += mInsets.left;
+ mPositionRect.top += mInsets.top;
+ mPositionRect.right -= mInsets.right;
+ mPositionRect.bottom -= mInsets.bottom;
+ }
+
+ /**
+ * @return a rect of available screen space for displaying bubbles in the correct orientation,
+ * accounting for system bars and cutouts.
+ */
+ public Rect getAvailableRect() {
+ return mPositionRect;
+ }
+
+ /**
+ * @return the current orientation.
+ */
+ public int getOrientation() {
+ return mOrientation;
+ }
+
+ /**
+ * @return the relevant insets (status bar, nav bar, cutouts).
+ */
+ public Insets getInsets() {
+ return mInsets;
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleStackView.java b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleStackView.java
index 431719f98ad9..0714c5eb4fa4 100644
--- a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleStackView.java
+++ b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleStackView.java
@@ -35,9 +35,9 @@ import android.content.res.Resources;
import android.content.res.TypedArray;
import android.graphics.ColorMatrix;
import android.graphics.ColorMatrixColorFilter;
+import android.graphics.Insets;
import android.graphics.Outline;
import android.graphics.Paint;
-import android.graphics.Point;
import android.graphics.PointF;
import android.graphics.Rect;
import android.graphics.RectF;
@@ -47,7 +47,6 @@ import android.os.Handler;
import android.provider.Settings;
import android.util.Log;
import android.view.Choreographer;
-import android.view.DisplayCutout;
import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.SurfaceControl;
@@ -57,7 +56,6 @@ import android.view.ViewGroup;
import android.view.ViewOutlineProvider;
import android.view.ViewTreeObserver;
import android.view.WindowInsets;
-import android.view.WindowManager;
import android.view.accessibility.AccessibilityNodeInfo;
import android.view.accessibility.AccessibilityNodeInfo.AccessibilityAction;
import android.view.animation.AccelerateDecelerateInterpolator;
@@ -188,8 +186,6 @@ public class BubbleStackView extends FrameLayout
}
};
- private Point mDisplaySize;
-
private final BubbleData mBubbleData;
private final ValueAnimator mDesaturateAndDarkenAnimator;
@@ -245,8 +241,8 @@ public class BubbleStackView extends FrameLayout
private int mBubblePaddingTop;
private int mBubbleTouchPadding;
private int mExpandedViewPadding;
+ private int mPointerHeight;
private int mCornerRadius;
- private int mStatusBarHeight;
private int mImeOffset;
@Nullable private BubbleViewProvider mExpandedBubble;
private boolean mIsExpanded;
@@ -721,13 +717,11 @@ public class BubbleStackView extends FrameLayout
}
};
- private DismissView mDismissView;
- private int mOrientation = Configuration.ORIENTATION_UNDEFINED;
-
@Nullable
private BubbleOverflow mBubbleOverflow;
private StackEducationView mStackEduView;
private ManageEducationView mManageEduView;
+ private DismissView mDismissView;
private ViewGroup mManageMenu;
private ImageView mManageSettingsIcon;
@@ -735,6 +729,8 @@ public class BubbleStackView extends FrameLayout
private boolean mShowingManage = false;
private PhysicsAnimator.SpringConfig mManageSpringConfig = new PhysicsAnimator.SpringConfig(
SpringForce.STIFFNESS_MEDIUM, SpringForce.DAMPING_RATIO_LOW_BOUNCY);
+ private BubblePositioner mPositioner;
+
@SuppressLint("ClickableViewAccessibility")
public BubbleStackView(Context context, BubbleData data,
@Nullable SurfaceSynchronizer synchronizer,
@@ -742,7 +738,8 @@ public class BubbleStackView extends FrameLayout
Runnable allBubblesAnimatedOutAction,
Consumer<Boolean> onImeVisibilityChanged,
Runnable hideCurrentInputMethodCallback,
- Consumer<Boolean> onBubbleExpandChanged) {
+ Consumer<Boolean> onBubbleExpandChanged,
+ BubblePositioner positioner) {
super(context);
mBubbleData = data;
@@ -753,15 +750,11 @@ public class BubbleStackView extends FrameLayout
mBubbleElevation = res.getDimensionPixelSize(R.dimen.bubble_elevation);
mBubblePaddingTop = res.getDimensionPixelSize(R.dimen.bubble_padding_top);
mBubbleTouchPadding = res.getDimensionPixelSize(R.dimen.bubble_touch_padding);
+ mPointerHeight = res.getDimensionPixelSize(R.dimen.bubble_pointer_height);
- mStatusBarHeight =
- res.getDimensionPixelSize(com.android.internal.R.dimen.status_bar_height);
mImeOffset = res.getDimensionPixelSize(R.dimen.pip_ime_offset);
- mDisplaySize = new Point();
- WindowManager wm = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
- // We use the real size & subtract screen decorations / window insets ourselves when needed
- wm.getDefaultDisplay().getRealSize(mDisplaySize);
+ mPositioner = positioner;
mExpandedViewPadding = res.getDimensionPixelSize(R.dimen.bubble_expanded_view_padding);
int elevation = res.getDimensionPixelSize(R.dimen.bubble_elevation);
@@ -778,11 +771,10 @@ public class BubbleStackView extends FrameLayout
};
mStackAnimationController = new StackAnimationController(
- floatingContentCoordinator, this::getBubbleCount, onBubbleAnimatedOut);
+ floatingContentCoordinator, this::getBubbleCount, onBubbleAnimatedOut, mPositioner);
mExpandedAnimationController = new ExpandedAnimationController(
- mDisplaySize, mExpandedViewPadding, res.getConfiguration().orientation,
- onBubbleAnimatedOut);
+ mPositioner, mExpandedViewPadding, onBubbleAnimatedOut);
mSurfaceSynchronizer = synchronizer != null ? synchronizer : DEFAULT_SURFACE_SYNCHRONIZER;
// Force LTR by default since most of the Bubbles UI is positioned manually by the user, or
@@ -817,10 +809,10 @@ public class BubbleStackView extends FrameLayout
mAnimatingOutSurfaceContainer.addView(mAnimatingOutSurfaceView);
mAnimatingOutSurfaceContainer.setPadding(
- mExpandedViewPadding,
- mExpandedViewPadding,
- mExpandedViewPadding,
- mExpandedViewPadding);
+ mExpandedViewContainer.getPaddingLeft(),
+ mExpandedViewContainer.getPaddingTop(),
+ mExpandedViewContainer.getPaddingRight(),
+ mExpandedViewContainer.getPaddingBottom());
setUpManageMenu();
@@ -871,29 +863,16 @@ public class BubbleStackView extends FrameLayout
mOrientationChangedListener =
(v, left, top, right, bottom, oldLeft, oldTop, oldRight, oldBottom) -> {
- mExpandedAnimationController.updateResources(mOrientation, mDisplaySize);
- mStackAnimationController.updateResources(mOrientation);
+ onDisplaySizeChanged();
+ mExpandedAnimationController.updateResources();
+ mStackAnimationController.updateResources();
mBubbleOverflow.updateResources();
- // Need to update the padding around the view
- WindowInsets insets = getRootWindowInsets();
- int leftPadding = mExpandedViewPadding;
- int rightPadding = mExpandedViewPadding;
- if (insets != null) {
- // Can't have the expanded view overlaying notches
- int cutoutLeft = 0;
- int cutoutRight = 0;
- DisplayCutout cutout = insets.getDisplayCutout();
- if (cutout != null) {
- cutoutLeft = cutout.getSafeInsetLeft();
- cutoutRight = cutout.getSafeInsetRight();
- }
- // Or overlaying nav or status bar
- leftPadding += Math.max(cutoutLeft, insets.getStableInsetLeft());
- rightPadding += Math.max(cutoutRight, insets.getStableInsetRight());
+ if (mRelativeStackPositionBeforeRotation != null) {
+ mStackAnimationController.setStackPosition(
+ mRelativeStackPositionBeforeRotation);
+ mRelativeStackPositionBeforeRotation = null;
}
- mExpandedViewContainer.setPadding(leftPadding, mExpandedViewPadding,
- rightPadding, mExpandedViewPadding);
if (mIsExpanded) {
// Re-draw bubble row and pointer for new orientation.
@@ -903,15 +882,10 @@ public class BubbleStackView extends FrameLayout
mExpandedAnimationController.expandFromStack(() -> {
afterExpandedViewAnimation();
} /* after */);
- mExpandedViewContainer.setTranslationX(0);
+ mExpandedViewContainer.setTranslationX(0f);
mExpandedViewContainer.setTranslationY(getExpandedViewY());
mExpandedViewContainer.setAlpha(1f);
}
- if (mRelativeStackPositionBeforeRotation != null) {
- mStackAnimationController.setStackPosition(
- mRelativeStackPositionBeforeRotation);
- mRelativeStackPositionBeforeRotation = null;
- }
removeOnLayoutChangeListener(mOrientationChangedListener);
};
@@ -1178,26 +1152,16 @@ public class BubbleStackView extends FrameLayout
}
/** Respond to the phone being rotated by repositioning the stack and hiding any flyouts. */
- public void onOrientationChanged(int orientation) {
- mOrientation = orientation;
-
- // Display size is based on the rotation device was in when requested, we should update it
- // We use the real size & subtract screen decorations / window insets ourselves when needed
- WindowManager wm = (WindowManager) getContext().getSystemService(Context.WINDOW_SERVICE);
- wm.getDefaultDisplay().getRealSize(mDisplaySize);
-
- // Some resources change depending on orientation
+ public void onOrientationChanged() {
Resources res = getContext().getResources();
- mStatusBarHeight = res.getDimensionPixelSize(
- com.android.internal.R.dimen.status_bar_height);
mBubblePaddingTop = res.getDimensionPixelSize(R.dimen.bubble_padding_top);
mRelativeStackPositionBeforeRotation = mStackAnimationController.getRelativeStackPosition();
- addOnLayoutChangeListener(mOrientationChangedListener);
- hideFlyoutImmediate();
-
mManageMenu.setVisibility(View.INVISIBLE);
mShowingManage = false;
+
+ addOnLayoutChangeListener(mOrientationChangedListener);
+ hideFlyoutImmediate();
}
/** Tells the views with locale-dependent layout direction to resolve the new direction. */
@@ -1217,11 +1181,7 @@ public class BubbleStackView extends FrameLayout
public void onDisplaySizeChanged() {
updateOverflow();
- WindowManager wm = (WindowManager) getContext().getSystemService(Context.WINDOW_SERVICE);
- wm.getDefaultDisplay().getRealSize(mDisplaySize);
Resources res = getContext().getResources();
- mStatusBarHeight = res.getDimensionPixelSize(
- com.android.internal.R.dimen.status_bar_height);
mBubblePaddingTop = res.getDimensionPixelSize(R.dimen.bubble_padding_top);
mBubbleSize = getResources().getDimensionPixelSize(R.dimen.individual_bubble_size);
for (Bubble b : mBubbleData.getBubbles()) {
@@ -1231,8 +1191,8 @@ public class BubbleStackView extends FrameLayout
}
b.getIconView().setLayoutParams(new LayoutParams(mBubbleSize, mBubbleSize));
}
- mExpandedAnimationController.updateResources(mOrientation, mDisplaySize);
- mStackAnimationController.updateResources(mOrientation);
+ mExpandedAnimationController.updateResources();
+ mStackAnimationController.updateResources();
mDismissView.updateResources();
mMagneticTarget.setMagneticFieldRadiusPx(mBubbleSize * 2);
}
@@ -1682,7 +1642,8 @@ public class BubbleStackView extends FrameLayout
private void animateExpansion() {
cancelDelayedExpandCollapseSwitchAnimations();
-
+ final boolean isLandscape =
+ mPositioner.getOrientation() == Configuration.ORIENTATION_LANDSCAPE;
mIsExpanded = true;
if (mStackEduView != null) {
mStackEduView.hide(true /* fromExpansion */);
@@ -1698,20 +1659,21 @@ public class BubbleStackView extends FrameLayout
}
} /* after */);
- mExpandedViewContainer.setTranslationX(0);
+ mExpandedViewContainer.setTranslationX(0f);
mExpandedViewContainer.setTranslationY(getExpandedViewY());
mExpandedViewContainer.setAlpha(1f);
// X-value of the bubble we're expanding, once it's settled in its row.
- final float bubbleWillBeAtX =
- mExpandedAnimationController.getBubbleLeft(
+ final float bubbleWillBeAt =
+ mExpandedAnimationController.getBubbleXOrYForOrientation(
mBubbleData.getBubbles().indexOf(mExpandedBubble));
// How far horizontally the bubble will be animating. We'll wait a bit longer for bubbles
// that are animating farther, so that the expanded view doesn't move as much.
- final float horizontalDistanceAnimated =
- Math.abs(bubbleWillBeAtX
- - mStackAnimationController.getStackPosition().x);
+ final float relevantStackPosition = isLandscape
+ ? mStackAnimationController.getStackPosition().y
+ : mStackAnimationController.getStackPosition().x;
+ final float distanceAnimated = Math.abs(bubbleWillBeAt - relevantStackPosition);
// Wait for the path animation target to reach its end, and add a small amount of extra time
// if the bubble is moving a lot horizontally.
@@ -1721,13 +1683,26 @@ public class BubbleStackView extends FrameLayout
if (getWidth() > 0) {
startDelay = (long)
(ExpandedAnimationController.EXPAND_COLLAPSE_TARGET_ANIM_DURATION
- + (horizontalDistanceAnimated / getWidth()) * 30);
+ + (distanceAnimated / getWidth()) * 30);
}
// Set the pivot point for the scale, so the expanded view animates out from the bubble.
- mExpandedViewContainerMatrix.setScale(
- 0f, 0f,
- bubbleWillBeAtX + mBubbleSize / 2f, getExpandedViewY());
+ if (isLandscape) {
+ float pivotX;
+ float pivotY = bubbleWillBeAt + mBubbleSize / 2f;
+ if (mStackOnLeftOrWillBe) {
+ pivotX = mPositioner.getAvailableRect().left + mBubbleSize + mExpandedViewPadding;
+ } else {
+ pivotX = mPositioner.getAvailableRect().right - mBubbleSize - mExpandedViewPadding;
+ }
+ mExpandedViewContainerMatrix.setScale(
+ 0f, 0f,
+ pivotX, pivotY);
+ } else {
+ mExpandedViewContainerMatrix.setScale(
+ 0f, 0f,
+ bubbleWillBeAt + mBubbleSize / 2f, getExpandedViewY());
+ }
mExpandedViewContainer.setAnimationMatrix(mExpandedViewContainerMatrix);
if (mExpandedBubble != null && mExpandedBubble.getExpandedView() != null) {
@@ -1747,9 +1722,11 @@ public class BubbleStackView extends FrameLayout
if (mExpandedBubble == null || mExpandedBubble.getIconView() == null) {
return;
}
+ float translation = isLandscape
+ ? mExpandedBubble.getIconView().getTranslationY()
+ : mExpandedBubble.getIconView().getTranslationX();
mExpandedViewContainerMatrix.postTranslate(
- mExpandedBubble.getIconView().getTranslationX()
- - bubbleWillBeAtX,
+ translation - bubbleWillBeAt,
0);
mExpandedViewContainer.setAnimationMatrix(
mExpandedViewContainerMatrix);
@@ -1797,16 +1774,29 @@ public class BubbleStackView extends FrameLayout
// We want to visually collapse into this bubble during the animation.
final View expandingFromBubble = mExpandedBubble.getIconView();
- // X-value the bubble is animating from (back into the stack).
- final float expandingFromBubbleAtX =
- mExpandedAnimationController.getBubbleLeft(
+ // Value the bubble is animating from (back into the stack).
+ final float expandingFromBubbleAt =
+ mExpandedAnimationController.getBubbleXOrYForOrientation(
mBubbleData.getBubbles().indexOf(mExpandedBubble));
-
- // Set the pivot point.
- mExpandedViewContainerMatrix.setScale(
- 1f, 1f,
- expandingFromBubbleAtX + mBubbleSize / 2f,
- getExpandedViewY());
+ final boolean isLandscape =
+ mPositioner.getOrientation() == Configuration.ORIENTATION_LANDSCAPE;
+ if (isLandscape) {
+ float pivotX;
+ float pivotY = expandingFromBubbleAt + mBubbleSize / 2f;
+ if (mStackOnLeftOrWillBe) {
+ pivotX = mPositioner.getAvailableRect().left + mBubbleSize + mExpandedViewPadding;
+ } else {
+ pivotX = mPositioner.getAvailableRect().right - mBubbleSize - mExpandedViewPadding;
+ }
+ mExpandedViewContainerMatrix.setScale(
+ 1f, 1f,
+ pivotX, pivotY);
+ } else {
+ mExpandedViewContainerMatrix.setScale(
+ 1f, 1f,
+ expandingFromBubbleAt + mBubbleSize / 2f,
+ getExpandedViewY());
+ }
PhysicsAnimator.getInstance(mExpandedViewContainerMatrix).cancel();
PhysicsAnimator.getInstance(mExpandedViewContainerMatrix)
@@ -1815,9 +1805,15 @@ public class BubbleStackView extends FrameLayout
.addUpdateListener((target, values) -> {
if (expandingFromBubble != null) {
// Follow the bubble as it translates!
- mExpandedViewContainerMatrix.postTranslate(
- expandingFromBubble.getTranslationX()
- - expandingFromBubbleAtX, 0f);
+ if (isLandscape) {
+ mExpandedViewContainerMatrix.postTranslate(
+ 0f, expandingFromBubble.getTranslationY()
+ - expandingFromBubbleAt);
+ } else {
+ mExpandedViewContainerMatrix.postTranslate(
+ expandingFromBubble.getTranslationX()
+ - expandingFromBubbleAt, 0f);
+ }
}
mExpandedViewContainer.setAnimationMatrix(mExpandedViewContainerMatrix);
@@ -1861,26 +1857,55 @@ public class BubbleStackView extends FrameLayout
// The surface contains a screenshot of the animating out bubble, so we just need to animate
// it out (and then release the GraphicBuffer).
PhysicsAnimator.getInstance(mAnimatingOutSurfaceContainer).cancel();
- PhysicsAnimator.getInstance(mAnimatingOutSurfaceContainer)
+ PhysicsAnimator animator = PhysicsAnimator.getInstance(mAnimatingOutSurfaceContainer)
.spring(DynamicAnimation.SCALE_X, 0f, mScaleOutSpringConfig)
.spring(DynamicAnimation.SCALE_Y, 0f, mScaleOutSpringConfig)
- .spring(DynamicAnimation.TRANSLATION_Y,
- mAnimatingOutSurfaceContainer.getTranslationY() - mBubbleSize * 2,
- mTranslateSpringConfig)
- .withEndActions(this::releaseAnimatingOutBubbleBuffer)
- .start();
+ .withEndActions(this::releaseAnimatingOutBubbleBuffer);
+
+ if (mPositioner.getOrientation() == Configuration.ORIENTATION_LANDSCAPE) {
+ float translationX = mStackAnimationController.isStackOnLeftSide()
+ ? mAnimatingOutSurfaceContainer.getTranslationX() + mBubbleSize * 2
+ : mAnimatingOutSurfaceContainer.getTranslationX();
+ animator.spring(DynamicAnimation.TRANSLATION_X,
+ translationX,
+ mTranslateSpringConfig)
+ .start();
+ } else {
+ animator.spring(DynamicAnimation.TRANSLATION_Y,
+ mAnimatingOutSurfaceContainer.getTranslationY() - mBubbleSize * 2,
+ mTranslateSpringConfig)
+ .start();
+ }
boolean isOverflow = mExpandedBubble != null
&& mExpandedBubble.getKey().equals(BubbleOverflow.KEY);
- float expandingFromBubbleDestinationX =
- mExpandedAnimationController.getBubbleLeft(isOverflow ? getBubbleCount()
+ float expandingFromBubbleDestination =
+ mExpandedAnimationController.getBubbleXOrYForOrientation(isOverflow
+ ? getBubbleCount()
: mBubbleData.getBubbles().indexOf(mExpandedBubble));
mExpandedViewContainer.setAlpha(1f);
mExpandedViewContainer.setVisibility(View.VISIBLE);
- mExpandedViewContainerMatrix.setScale(
- 0f, 0f, expandingFromBubbleDestinationX + mBubbleSize / 2f, getExpandedViewY());
+ if (mPositioner.getOrientation() == Configuration.ORIENTATION_LANDSCAPE) {
+ float pivotX;
+ float pivotY = expandingFromBubbleDestination + mBubbleSize / 2f;
+ if (mStackOnLeftOrWillBe) {
+ pivotX = mPositioner.getAvailableRect().left + mBubbleSize + mExpandedViewPadding;
+ } else {
+ pivotX = mPositioner.getAvailableRect().right - mBubbleSize - mExpandedViewPadding;
+
+ }
+ mExpandedViewContainerMatrix.setScale(
+ 0f, 0f,
+ pivotX, pivotY);
+ } else {
+ mExpandedViewContainerMatrix.setScale(
+ 0f, 0f,
+ expandingFromBubbleDestination + mBubbleSize / 2f,
+ getExpandedViewY());
+ }
+
mExpandedViewContainer.setAnimationMatrix(mExpandedViewContainerMatrix);
mDelayedAnimationHandler.postDelayed(() -> {
@@ -2168,7 +2193,12 @@ public class BubbleStackView extends FrameLayout
* Calculates the y position of the expanded view when it is expanded.
*/
float getExpandedViewY() {
- return getStatusBarHeight() + mBubbleSize + mBubblePaddingTop;
+ final int top = mPositioner.getAvailableRect().top;
+ if (mPositioner.getOrientation() == Configuration.ORIENTATION_LANDSCAPE) {
+ return top + mExpandedViewPadding;
+ } else {
+ return top + mBubbleSize + mBubblePaddingTop;
+ }
}
private boolean shouldShowFlyout(Bubble bubble) {
@@ -2216,9 +2246,10 @@ public class BubbleStackView extends FrameLayout
}
// Stop suppressing the dot now that the flyout has morphed into the dot.
- bubble.getIconView().removeDotSuppressionFlag(
- BadgedImageView.SuppressionFlag.FLYOUT_VISIBLE);
-
+ if (bubble.getIconView() != null) {
+ bubble.getIconView().removeDotSuppressionFlag(
+ BadgedImageView.SuppressionFlag.FLYOUT_VISIBLE);
+ }
// Hide the stack after a delay, if needed.
updateTemporarilyInvisibleAnimation(false /* hideImmediately */);
};
@@ -2323,19 +2354,6 @@ public class BubbleStackView extends FrameLayout
}
}
- private int getStatusBarHeight() {
- if (getRootWindowInsets() != null) {
- WindowInsets insets = getRootWindowInsets();
- return Math.max(
- mStatusBarHeight,
- insets.getDisplayCutout() != null
- ? insets.getDisplayCutout().getSafeInsetTop()
- : 0);
- }
-
- return 0;
- }
-
private void requestUpdate() {
if (mViewUpdatedRequested || mIsExpansionAnimating) {
return;
@@ -2484,7 +2502,7 @@ public class BubbleStackView extends FrameLayout
PhysicsAnimator.getInstance(mAnimatingOutSurfaceContainer).cancel();
mAnimatingOutSurfaceContainer.setScaleX(1f);
mAnimatingOutSurfaceContainer.setScaleY(1f);
- mAnimatingOutSurfaceContainer.setTranslationX(0);
+ mAnimatingOutSurfaceContainer.setTranslationX(mExpandedViewContainer.getPaddingLeft());
mAnimatingOutSurfaceContainer.setTranslationY(0);
final int[] activityViewLocation =
@@ -2542,9 +2560,22 @@ public class BubbleStackView extends FrameLayout
Log.d(TAG, "updateExpandedView: mIsExpanded=" + mIsExpanded);
}
+ // Need to update the padding around the view for any insets
+ Insets insets = mPositioner.getInsets();
+ int leftPadding = insets.left + mExpandedViewPadding;
+ int rightPadding = insets.right + mExpandedViewPadding;
+ if (mPositioner.getOrientation() == Configuration.ORIENTATION_LANDSCAPE) {
+ if (!mStackAnimationController.isStackOnLeftSide()) {
+ rightPadding += mPointerHeight + mBubbleSize;
+ } else {
+ leftPadding += mPointerHeight + mBubbleSize;
+ }
+ }
+ mExpandedViewContainer.setPadding(leftPadding, 0, rightPadding, 0);
mExpandedViewContainer.setVisibility(mIsExpanded ? VISIBLE : GONE);
if (mExpandedBubble != null && mExpandedBubble.getExpandedView() != null) {
mExpandedViewContainer.setTranslationY(getExpandedViewY());
+ mExpandedViewContainer.setTranslationX(0f);
mExpandedBubble.getExpandedView().updateView(
mExpandedViewContainer.getLocationOnScreen());
}
@@ -2587,12 +2618,27 @@ public class BubbleStackView extends FrameLayout
if (index == -1) {
return;
}
- float bubbleLeftFromScreenLeft = mExpandedAnimationController.getBubbleLeft(index);
- float halfBubble = mBubbleSize / 2f;
- float bubbleCenter = bubbleLeftFromScreenLeft + halfBubble;
- // Padding might be adjusted for insets, so get it directly from the view
- bubbleCenter -= mExpandedViewContainer.getPaddingLeft();
- mExpandedBubble.getExpandedView().setPointerPosition(bubbleCenter);
+ float bubblePosition = mExpandedAnimationController.getBubbleXOrYForOrientation(index);
+ if (mPositioner.getOrientation() == Configuration.ORIENTATION_LANDSCAPE) {
+ float x = mStackOnLeftOrWillBe
+ ? mPositioner.getAvailableRect().left
+ : mPositioner.getAvailableRect().right
+ - mExpandedViewContainer.getPaddingRight()
+ - mPointerHeight;
+ float bubbleCenter = bubblePosition - getExpandedViewY() + (mBubbleSize / 2f);
+ mExpandedBubble.getExpandedView().setPointerPosition(
+ x,
+ bubbleCenter,
+ true,
+ mStackOnLeftOrWillBe);
+ } else {
+ float bubbleCenter = bubblePosition + (mBubbleSize / 2f);
+ mExpandedBubble.getExpandedView().setPointerPosition(
+ bubbleCenter,
+ getExpandedViewY(),
+ false,
+ mStackOnLeftOrWillBe);
+ }
}
/**
@@ -2621,7 +2667,7 @@ public class BubbleStackView extends FrameLayout
* @return the normalized x-axis position of the bubble stack rounded to 4 decimal places.
*/
public float getNormalizedXPosition() {
- return new BigDecimal(getStackPosition().x / mDisplaySize.x)
+ return new BigDecimal(getStackPosition().x / mPositioner.getAvailableRect().width())
.setScale(4, RoundingMode.CEILING.HALF_UP)
.floatValue();
}
@@ -2630,7 +2676,7 @@ public class BubbleStackView extends FrameLayout
* @return the normalized y-axis position of the bubble stack rounded to 4 decimal places.
*/
public float getNormalizedYPosition() {
- return new BigDecimal(getStackPosition().y / mDisplaySize.y)
+ return new BigDecimal(getStackPosition().y / mPositioner.getAvailableRect().height())
.setScale(4, RoundingMode.CEILING.HALF_UP)
.floatValue();
}
diff --git a/packages/SystemUI/src/com/android/systemui/bubbles/Bubbles.java b/packages/SystemUI/src/com/android/systemui/bubbles/Bubbles.java
index 39c750de28ac..4882abc51ed6 100644
--- a/packages/SystemUI/src/com/android/systemui/bubbles/Bubbles.java
+++ b/packages/SystemUI/src/com/android/systemui/bubbles/Bubbles.java
@@ -23,6 +23,7 @@ import androidx.annotation.MainThread;
import com.android.systemui.statusbar.ScrimView;
import com.android.systemui.statusbar.notification.collection.NotificationEntry;
import com.android.systemui.statusbar.phone.ScrimController;
+import com.android.wm.shell.ShellTaskOrganizer;
import java.util.List;
@@ -129,5 +130,8 @@ public interface Bubbles {
void setOverflowListener(BubbleData.Listener listener);
/** The task listener for events in bubble tasks. **/
- MultiWindowTaskListener getTaskManager();
+ ShellTaskOrganizer getTaskOrganizer();
+
+ /** Contains information to help position things on the screen. */
+ BubblePositioner getPositioner();
}
diff --git a/packages/SystemUI/src/com/android/systemui/bubbles/MultiWindowTaskListener.java b/packages/SystemUI/src/com/android/systemui/bubbles/MultiWindowTaskListener.java
deleted file mode 100644
index 351a268c6f5d..000000000000
--- a/packages/SystemUI/src/com/android/systemui/bubbles/MultiWindowTaskListener.java
+++ /dev/null
@@ -1,179 +0,0 @@
-/*
- * Copyright (C) 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.systemui.bubbles;
-
-import static com.android.wm.shell.ShellTaskOrganizer.TASK_LISTENER_TYPE_MULTI_WINDOW;
-
-import android.app.ActivityManager.RunningTaskInfo;
-import android.app.ActivityTaskManager;
-import android.os.Handler;
-import android.os.IBinder;
-import android.os.RemoteException;
-import android.util.ArrayMap;
-import android.util.Log;
-import android.view.SurfaceControl;
-import android.window.TaskOrganizer;
-import android.window.WindowContainerToken;
-
-import com.android.wm.shell.ShellTaskOrganizer;
-
-import java.util.ArrayList;
-
-/**
- * Manages tasks that are displayed in multi-window (e.g. bubbles). These are displayed in a
- * {@link TaskView}.
- *
- * This class listens on {@link TaskOrganizer} callbacks for events. Once visible, these tasks will
- * intercept back press events.
- *
- * @see android.app.WindowConfiguration#WINDOWING_MODE_MULTI_WINDOW
- * @see TaskView
- */
-// TODO: Place in com.android.wm.shell vs. com.android.wm.shell.bubbles on shell migration.
-public class MultiWindowTaskListener implements ShellTaskOrganizer.TaskListener {
- private static final String TAG = MultiWindowTaskListener.class.getSimpleName();
-
- private static final boolean DEBUG = false;
-
- //TODO(b/170153209): Have shell listener allow per task registration and remove this.
- public interface Listener {
- void onTaskAppeared(RunningTaskInfo taskInfo, SurfaceControl leash);
- void onTaskVanished(RunningTaskInfo taskInfo);
- void onTaskInfoChanged(RunningTaskInfo taskInfo);
- void onBackPressedOnTaskRoot(RunningTaskInfo taskInfo);
- }
-
- private static class TaskData {
- final RunningTaskInfo taskInfo;
- final Listener listener;
-
- TaskData(RunningTaskInfo info, Listener l) {
- taskInfo = info;
- listener = l;
- }
- }
-
- private final Handler mHandler;
- private final ShellTaskOrganizer mTaskOrganizer;
- private final ArrayMap<WindowContainerToken, TaskData> mTasks = new ArrayMap<>();
-
- private ArrayMap<IBinder, Listener> mLaunchCookieToListener = new ArrayMap<>();
-
- /**
- * Create a listener for tasks in multi-window mode.
- */
- public MultiWindowTaskListener(Handler handler, ShellTaskOrganizer organizer) {
- mHandler = handler;
- mTaskOrganizer = organizer;
- mTaskOrganizer.addListener(this, TASK_LISTENER_TYPE_MULTI_WINDOW);
- }
-
- /**
- * @return the task organizer that is listened to.
- */
- public TaskOrganizer getTaskOrganizer() {
- return mTaskOrganizer;
- }
-
- public void setPendingLaunchCookieListener(IBinder cookie, Listener listener) {
- mLaunchCookieToListener.put(cookie, listener);
- }
-
- /**
- * Removes a task listener previously registered when starting a new activity.
- */
- public void removeListener(Listener listener) {
- if (DEBUG) {
- Log.d(TAG, "removeListener: listener=" + listener);
- }
- for (int i = 0; i < mTasks.size(); i++) {
- if (mTasks.valueAt(i).listener == listener) {
- mTasks.removeAt(i);
- }
- }
- }
-
- @Override
- public void onTaskAppeared(RunningTaskInfo taskInfo, SurfaceControl leash) {
- if (DEBUG) {
- Log.d(TAG, "onTaskAppeared: taskInfo=" + taskInfo);
- }
-
- // We only care about task we launch which should all have a tracking launch cookie.
- final ArrayList<IBinder> launchCookies = taskInfo.launchCookies;
- if (launchCookies.isEmpty()) return;
-
- // See if this task has one of our launch cookies.
- Listener listener = null;
- for (int i = launchCookies.size() - 1; i >= 0; --i) {
- final IBinder cookie = launchCookies.get(i);
- listener = mLaunchCookieToListener.get(cookie);
- if (listener != null) {
- mLaunchCookieToListener.remove(cookie);
- break;
- }
- }
-
- // This is either not a task we launched or we have handled it previously.
- if (listener == null) return;
-
- mTaskOrganizer.setInterceptBackPressedOnTaskRoot(taskInfo.token, true);
-
- final TaskData data = new TaskData(taskInfo, listener);
- mTasks.put(taskInfo.token, data);
- mHandler.post(() -> data.listener.onTaskAppeared(taskInfo, leash));
- }
-
- @Override
- public void onTaskVanished(RunningTaskInfo taskInfo) {
- final TaskData data = mTasks.remove(taskInfo.token);
- if (data == null) {
- return;
- }
-
- if (DEBUG) {
- Log.d(TAG, "onTaskVanished: taskInfo=" + taskInfo + " listener=" + data.listener);
- }
- mHandler.post(() -> data.listener.onTaskVanished(taskInfo));
- }
-
- @Override
- public void onTaskInfoChanged(RunningTaskInfo taskInfo) {
- final TaskData data = mTasks.get(taskInfo.token);
- if (data == null) {
- return;
- }
-
- if (DEBUG) {
- Log.d(TAG, "onTaskInfoChanged: taskInfo=" + taskInfo + " listener=" + data.listener);
- }
- mHandler.post(() -> data.listener.onTaskInfoChanged(taskInfo));
- }
-
- @Override
- public void onBackPressedOnTaskRoot(RunningTaskInfo taskInfo) {
- final TaskData data = mTasks.get(taskInfo.token);
- if (data == null) {
- return;
- }
-
- if (DEBUG) {
- Log.d(TAG, "onTaskInfoChanged: taskInfo=" + taskInfo + " listener=" + data.listener);
- }
- mHandler.post(() -> data.listener.onBackPressedOnTaskRoot(taskInfo));
- }
-}
diff --git a/packages/SystemUI/src/com/android/systemui/bubbles/TaskView.java b/packages/SystemUI/src/com/android/systemui/bubbles/TaskView.java
index b78e6773eb76..85616d1513f5 100644
--- a/packages/SystemUI/src/com/android/systemui/bubbles/TaskView.java
+++ b/packages/SystemUI/src/com/android/systemui/bubbles/TaskView.java
@@ -30,20 +30,26 @@ import android.content.pm.LauncherApps;
import android.content.pm.ShortcutInfo;
import android.graphics.Rect;
import android.os.Binder;
+import android.os.Handler;
import android.view.SurfaceControl;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.window.WindowContainerToken;
import android.window.WindowContainerTransaction;
+import com.android.wm.shell.ShellTaskOrganizer;
+
import dalvik.system.CloseGuard;
+import java.io.PrintWriter;
+import java.util.concurrent.Executor;
+
/**
* View that can display a task.
*/
// TODO: Place in com.android.wm.shell vs. com.android.wm.shell.bubbles on shell migration.
public class TaskView extends SurfaceView implements SurfaceHolder.Callback,
- MultiWindowTaskListener.Listener {
+ ShellTaskOrganizer.TaskListener {
public interface Listener {
/** Called when the container is ready for launching activities. */
@@ -67,7 +73,7 @@ public class TaskView extends SurfaceView implements SurfaceHolder.Callback,
private final CloseGuard mGuard = CloseGuard.get();
- private final MultiWindowTaskListener mMultiWindowTaskListener;
+ private final ShellTaskOrganizer mTaskOrganizer;
private ActivityManager.RunningTaskInfo mTaskInfo;
private WindowContainerToken mTaskToken;
@@ -76,14 +82,16 @@ public class TaskView extends SurfaceView implements SurfaceHolder.Callback,
private boolean mSurfaceCreated;
private boolean mIsInitialized;
private Listener mListener;
+ private final Executor mExecutor;
private final Rect mTmpRect = new Rect();
private final Rect mTmpRootRect = new Rect();
- public TaskView(Context context, MultiWindowTaskListener taskListener) {
+ public TaskView(Context context, ShellTaskOrganizer organizer, Executor executor) {
super(context, null, 0, 0, true /* disableBackgroundLayer */);
- mMultiWindowTaskListener = taskListener;
+ mExecutor = executor;
+ mTaskOrganizer = organizer;
setUseAlpha();
getHolder().addCallback(this);
mGuard.open("release");
@@ -142,7 +150,7 @@ public class TaskView extends SurfaceView implements SurfaceHolder.Callback,
private void prepareActivityOptions(ActivityOptions options) {
final Binder launchCookie = new Binder();
- mMultiWindowTaskListener.setPendingLaunchCookieListener(launchCookie, this);
+ mTaskOrganizer.setPendingLaunchCookieListener(launchCookie, this);
options.setLaunchCookie(launchCookie);
options.setLaunchWindowingMode(WINDOWING_MODE_MULTI_WINDOW);
options.setTaskAlwaysOnTop(true);
@@ -165,7 +173,7 @@ public class TaskView extends SurfaceView implements SurfaceHolder.Callback,
WindowContainerTransaction wct = new WindowContainerTransaction();
wct.setBounds(mTaskToken, mTmpRect);
// TODO(b/151449487): Enable synchronization
- mMultiWindowTaskListener.getTaskOrganizer().applyTransaction(wct);
+ mTaskOrganizer.applyTransaction(wct);
}
/**
@@ -189,7 +197,7 @@ public class TaskView extends SurfaceView implements SurfaceHolder.Callback,
private void performRelease() {
getHolder().removeCallback(this);
- mMultiWindowTaskListener.removeListener(this);
+ mTaskOrganizer.removeListener(this);
resetTaskInfo();
mGuard.close();
if (mListener != null && mIsInitialized) {
@@ -207,7 +215,7 @@ public class TaskView extends SurfaceView implements SurfaceHolder.Callback,
private void updateTaskVisibility() {
WindowContainerTransaction wct = new WindowContainerTransaction();
wct.setHidden(mTaskToken, !mSurfaceCreated /* hidden */);
- mMultiWindowTaskListener.getTaskOrganizer().applyTransaction(wct);
+ mTaskOrganizer.applyTransaction(wct);
// TODO(b/151449487): Only call callback once we enable synchronization
if (mListener != null) {
mListener.onTaskVisibilityChanged(mTaskInfo.taskId, mSurfaceCreated);
@@ -217,33 +225,37 @@ public class TaskView extends SurfaceView implements SurfaceHolder.Callback,
@Override
public void onTaskAppeared(ActivityManager.RunningTaskInfo taskInfo,
SurfaceControl leash) {
- mTaskInfo = taskInfo;
- mTaskToken = taskInfo.token;
- mTaskLeash = leash;
-
- if (mSurfaceCreated) {
- // Surface is ready, so just reparent the task to this surface control
- mTransaction.reparent(mTaskLeash, getSurfaceControl())
- .show(mTaskLeash)
- .apply();
- } else {
- // The surface has already been destroyed before the task has appeared, so go ahead and
- // hide the task entirely
- updateTaskVisibility();
- }
+ mExecutor.execute(() -> {
+ mTaskInfo = taskInfo;
+ mTaskToken = taskInfo.token;
+ mTaskLeash = leash;
+
+ if (mSurfaceCreated) {
+ // Surface is ready, so just reparent the task to this surface control
+ mTransaction.reparent(mTaskLeash, getSurfaceControl())
+ .show(mTaskLeash)
+ .apply();
+ } else {
+ // The surface has already been destroyed before the task has appeared,
+ // so go ahead and hide the task entirely
+ updateTaskVisibility();
+ }
- // TODO: Synchronize show with the resize
- onLocationChanged();
- setResizeBackgroundColor(taskInfo.taskDescription.getBackgroundColor());
+ // TODO: Synchronize show with the resize
+ onLocationChanged();
+ setResizeBackgroundColor(taskInfo.taskDescription.getBackgroundColor());
- if (mListener != null) {
- mListener.onTaskCreated(taskInfo.taskId, taskInfo.baseActivity);
- }
+ if (mListener != null) {
+ mListener.onTaskCreated(taskInfo.taskId, taskInfo.baseActivity);
+ }
+ });
}
@Override
public void onTaskVanished(ActivityManager.RunningTaskInfo taskInfo) {
- if (mTaskToken != null && mTaskToken.equals(taskInfo.token)) {
+ mExecutor.execute(() -> {
+ if (mTaskToken == null || !mTaskToken.equals(taskInfo.token)) return;
+
if (mListener != null) {
mListener.onTaskRemovalStarted(taskInfo.taskId);
}
@@ -251,22 +263,37 @@ public class TaskView extends SurfaceView implements SurfaceHolder.Callback,
// Unparent the task when this surface is destroyed
mTransaction.reparent(mTaskLeash, null).apply();
resetTaskInfo();
- }
+ });
}
@Override
public void onTaskInfoChanged(ActivityManager.RunningTaskInfo taskInfo) {
- mTaskInfo.taskDescription = taskInfo.taskDescription;
- setResizeBackgroundColor(taskInfo.taskDescription.getBackgroundColor());
+ mExecutor.execute(() -> {
+ mTaskInfo.taskDescription = taskInfo.taskDescription;
+ setResizeBackgroundColor(taskInfo.taskDescription.getBackgroundColor());
+ });
}
@Override
public void onBackPressedOnTaskRoot(ActivityManager.RunningTaskInfo taskInfo) {
- if (mTaskToken != null && mTaskToken.equals(taskInfo.token)) {
+ mExecutor.execute(() -> {
+ if (mTaskToken == null || !mTaskToken.equals(taskInfo.token)) return;
if (mListener != null) {
mListener.onBackPressedOnTaskRoot(taskInfo.taskId);
}
- }
+ });
+ }
+
+ @Override
+ public void dump(@androidx.annotation.NonNull PrintWriter pw, String prefix) {
+ final String innerPrefix = prefix + " ";
+ final String childPrefix = innerPrefix + " ";
+ pw.println(prefix + this);
+ }
+
+ @Override
+ public String toString() {
+ return "TaskView" + ":" + (mTaskInfo != null ? mTaskInfo.taskId : "null");
}
@Override
diff --git a/packages/SystemUI/src/com/android/systemui/bubbles/animation/ExpandedAnimationController.java b/packages/SystemUI/src/com/android/systemui/bubbles/animation/ExpandedAnimationController.java
index 7fdc01961aa5..5a70401abb4a 100644
--- a/packages/SystemUI/src/com/android/systemui/bubbles/animation/ExpandedAnimationController.java
+++ b/packages/SystemUI/src/com/android/systemui/bubbles/animation/ExpandedAnimationController.java
@@ -19,11 +19,9 @@ package com.android.systemui.bubbles.animation;
import android.content.res.Configuration;
import android.content.res.Resources;
import android.graphics.Path;
-import android.graphics.Point;
import android.graphics.PointF;
-import android.view.DisplayCutout;
+import android.graphics.Rect;
import android.view.View;
-import android.view.WindowInsets;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
@@ -32,6 +30,7 @@ import androidx.dynamicanimation.animation.SpringForce;
import com.android.systemui.Interpolators;
import com.android.systemui.R;
+import com.android.systemui.bubbles.BubblePositioner;
import com.android.wm.shell.animation.PhysicsAnimator;
import com.android.wm.shell.common.magnetictarget.MagnetizedObject;
@@ -83,16 +82,8 @@ public class ExpandedAnimationController
private float mBubblePaddingTop;
/** Size of each bubble. */
private float mBubbleSizePx;
- /** Space between bubbles in row above expanded view. */
- private float mSpaceBetweenBubbles;
- /** Height of the status bar. */
- private float mStatusBarHeight;
- /** Size of display. */
- private Point mDisplaySize;
/** Max number of bubbles shown in row above expanded view. */
private int mBubblesMaxRendered;
- /** What the current screen orientation is. */
- private int mScreenOrientation;
private boolean mAnimatingExpand = false;
@@ -104,7 +95,8 @@ public class ExpandedAnimationController
private boolean mPreparingToCollapse = false;
private boolean mAnimatingCollapse = false;
- private @Nullable Runnable mAfterExpand;
+ @Nullable
+ private Runnable mAfterExpand;
private Runnable mAfterCollapse;
private PointF mCollapsePoint;
@@ -138,9 +130,12 @@ public class ExpandedAnimationController
*/
private Runnable mOnBubbleAnimatedOutAction;
- public ExpandedAnimationController(Point displaySize, int expandedViewPadding,
- int orientation, Runnable onBubbleAnimatedOutAction) {
- updateResources(orientation, displaySize);
+ private BubblePositioner mPositioner;
+
+ public ExpandedAnimationController(BubblePositioner positioner, int expandedViewPadding,
+ Runnable onBubbleAnimatedOutAction) {
+ mPositioner = positioner;
+ updateResources();
mExpandedViewPadding = expandedViewPadding;
mOnBubbleAnimatedOutAction = onBubbleAnimatedOutAction;
}
@@ -152,7 +147,8 @@ public class ExpandedAnimationController
private boolean mBubbleDraggedOutEnough = false;
/** End action to run when the lead bubble's expansion animation completes. */
- @Nullable private Runnable mLeadBubbleEndAction;
+ @Nullable
+ private Runnable mLeadBubbleEndAction;
/**
* Animates expanding the bubbles into a row along the top of the screen, optionally running an
@@ -200,28 +196,17 @@ public class ExpandedAnimationController
/**
* Update effective screen width based on current orientation.
- * @param orientation Landscape or portrait.
- * @param displaySize Updated display size.
*/
- public void updateResources(int orientation, Point displaySize) {
- mScreenOrientation = orientation;
- mDisplaySize = displaySize;
+ public void updateResources() {
if (mLayout == null) {
return;
}
Resources res = mLayout.getContext().getResources();
mBubblePaddingTop = res.getDimensionPixelSize(R.dimen.bubble_padding_top);
- mStatusBarHeight = res.getDimensionPixelSize(
- com.android.internal.R.dimen.status_bar_height);
mStackOffsetPx = res.getDimensionPixelSize(R.dimen.bubble_stack_offset);
mBubblePaddingTop = res.getDimensionPixelSize(R.dimen.bubble_padding_top);
mBubbleSizePx = res.getDimensionPixelSize(R.dimen.individual_bubble_size);
mBubblesMaxRendered = res.getInteger(R.integer.bubbles_max_rendered);
-
- // Includes overflow button.
- float totalGapWidth = getWidthForDisplayingBubbles() - (mExpandedViewPadding * 2)
- - (mBubblesMaxRendered + 1) * mBubbleSizePx;
- mSpaceBetweenBubbles = totalGapWidth / mBubblesMaxRendered;
}
/**
@@ -270,9 +255,18 @@ public class ExpandedAnimationController
// If we're expanding, first draw a line from the bubble's current position to the
// top of the screen.
path.lineTo(bubble.getTranslationX(), expandedY);
-
// Then, draw a line across the screen to the bubble's resting position.
- path.lineTo(getBubbleLeft(index), expandedY);
+ if (mPositioner.getOrientation() == Configuration.ORIENTATION_LANDSCAPE) {
+ Rect availableRect = mPositioner.getAvailableRect();
+ boolean onLeft = mCollapsePoint != null
+ && mCollapsePoint.x < (availableRect.width() / 2f);
+ float translationX = onLeft
+ ? availableRect.left + mExpandedViewPadding
+ : availableRect.right - mBubbleSizePx - mExpandedViewPadding;
+ path.lineTo(translationX, getBubbleXOrYForOrientation(index));
+ } else {
+ path.lineTo(getBubbleXOrYForOrientation(index), expandedY);
+ }
} else {
final float stackedX = mCollapsePoint.x;
@@ -411,7 +405,8 @@ public class ExpandedAnimationController
updateBubblePositions();
}
- @Nullable public View getDraggedOutBubble() {
+ @Nullable
+ public View getDraggedOutBubble() {
return mMagnetizedBubbleDraggingOut == null
? null
: mMagnetizedBubbleDraggingOut.getUnderlyingObject();
@@ -430,7 +425,7 @@ public class ExpandedAnimationController
final int index = mLayout.indexOfChild(bubbleView);
animationForChildAtIndex(index)
- .position(getBubbleLeft(index), getExpandedY())
+ .position(getBubbleXOrYForOrientation(index), getExpandedY())
.withPositionStartVelocities(velX, velY)
.start(() -> bubbleView.setTranslationZ(0f) /* after */);
@@ -457,15 +452,7 @@ public class ExpandedAnimationController
/** The Y value of the row of expanded bubbles. */
public float getExpandedY() {
- if (mLayout == null || mLayout.getRootWindowInsets() == null) {
- return 0;
- }
- final WindowInsets insets = mLayout.getRootWindowInsets();
- return mBubblePaddingTop + Math.max(
- mStatusBarHeight,
- insets.getDisplayCutout() != null
- ? insets.getDisplayCutout().getSafeInsetTop()
- : 0);
+ return mPositioner.getAvailableRect().top + mBubblePaddingTop;
}
/** Description of current animation controller state. */
@@ -479,7 +466,7 @@ public class ExpandedAnimationController
@Override
void onActiveControllerForLayout(PhysicsAnimationLayout layout) {
- updateResources(mScreenOrientation, mDisplaySize);
+ updateResources();
// Ensure that all child views are at 1x scale, and visible, in case they were animating
// in.
@@ -524,7 +511,7 @@ public class ExpandedAnimationController
} else if (mAnimatingCollapse) {
startOrUpdatePathAnimation(false /* expanding */);
} else {
- child.setTranslationX(getBubbleLeft(index));
+ child.setTranslationX(getBubbleXOrYForOrientation(index));
// If we're preparing to collapse, don't start animations since the collapse animation
// will take over and animate the new bubble into the correct (stacked) position.
@@ -593,76 +580,56 @@ public class ExpandedAnimationController
return;
}
- animationForChild(bubble)
- .translationX(getBubbleLeft(i))
- .start();
- }
- }
-
- /**
- * @param index Bubble index in row.
- * @return Bubble left x from left edge of screen.
- */
- public float getBubbleLeft(int index) {
- final float bubbleFromRowLeft = index * (mBubbleSizePx + mSpaceBetweenBubbles);
- return getRowLeft() + bubbleFromRowLeft;
- }
-
- /**
- * When expanded, the bubbles are centered in the screen. In portrait, all available space is
- * used. In landscape we have too much space so the value is restricted. This method accounts
- * for window decorations (nav bar, cutouts).
- *
- * @return the desired width to display the expanded bubbles in.
- */
- public float getWidthForDisplayingBubbles() {
- final float availableWidth = getAvailableScreenWidth(true /* includeStableInsets */);
- if (mScreenOrientation == Configuration.ORIENTATION_LANDSCAPE) {
- // display size y in landscape will be the smaller dimension of the screen
- return Math.max(mDisplaySize.y, availableWidth * CENTER_BUBBLES_LANDSCAPE_PERCENT);
- } else {
- return availableWidth;
+ if (mPositioner.getOrientation() == Configuration.ORIENTATION_LANDSCAPE) {
+ Rect availableRect = mPositioner.getAvailableRect();
+ boolean onLeft = mCollapsePoint != null
+ && mCollapsePoint.x < (availableRect.width() / 2f);
+ animationForChild(bubble)
+ .translationX(onLeft
+ ? availableRect.left + mExpandedViewPadding
+ : availableRect.right - mBubbleSizePx - mExpandedViewPadding)
+ .translationY(getBubbleXOrYForOrientation(i))
+ .start();
+ } else {
+ animationForChild(bubble)
+ .translationX(getBubbleXOrYForOrientation(i))
+ .translationY(getExpandedY())
+ .start();
+ }
}
}
/**
- * Determines the available screen width without the cutout.
+ * When bubbles are expanded in portrait, they display at the top of the screen in a horizontal
+ * row. When in landscape, they show at the left or right side in a vertical row. This method
+ * accounts for screen orientation and will return an x or y value for the position of the
+ * bubble in the row.
*
- * @param subtractStableInsets Whether or not stable insets should also be removed from the
- * returned width.
- * @return the total screen width available accounting for cutouts and insets,
- * iff {@param includeStableInsets} is true.
+ * @param index Bubble index in row.
+ * @return the y position of the bubble if {@link Configuration#ORIENTATION_LANDSCAPE} and the
+ * x position if {@link Configuration#ORIENTATION_PORTRAIT}.
*/
- private float getAvailableScreenWidth(boolean subtractStableInsets) {
- float availableSize = mDisplaySize.x;
- WindowInsets insets = mLayout != null ? mLayout.getRootWindowInsets() : null;
- if (insets != null) {
- int cutoutLeft = 0;
- int cutoutRight = 0;
- DisplayCutout cutout = insets.getDisplayCutout();
- if (cutout != null) {
- cutoutLeft = cutout.getSafeInsetLeft();
- cutoutRight = cutout.getSafeInsetRight();
- }
- final int stableLeft = subtractStableInsets ? insets.getStableInsetLeft() : 0;
- final int stableRight = subtractStableInsets ? insets.getStableInsetRight() : 0;
- availableSize -= Math.max(stableLeft, cutoutLeft);
- availableSize -= Math.max(stableRight, cutoutRight);
- }
- return availableSize;
- }
-
- private float getRowLeft() {
+ public float getBubbleXOrYForOrientation(int index) {
if (mLayout == null) {
return 0;
}
- float rowWidth = (mLayout.getChildCount() * mBubbleSizePx)
- + ((mLayout.getChildCount() - 1) * mSpaceBetweenBubbles);
-
- // This display size we're using includes the size of the insets, we want the true
- // center of the display minus the notch here, which means we should include the
- // stable insets (e.g. status bar, nav bar) in this calculation.
- final float trueCenter = getAvailableScreenWidth(false /* subtractStableInsets */) / 2f;
- return trueCenter - (rowWidth / 2f);
+ Rect availableRect = mPositioner.getAvailableRect();
+ final boolean isLandscape =
+ mPositioner.getOrientation() == Configuration.ORIENTATION_LANDSCAPE;
+ final float availableSpace = isLandscape
+ ? availableRect.height()
+ : availableRect.width();
+ final float spaceForMaxBubbles = (mExpandedViewPadding * 2)
+ + (mBubblesMaxRendered + 1) * mBubbleSizePx;
+ final float spaceBetweenBubbles =
+ (availableSpace - spaceForMaxBubbles) / mBubblesMaxRendered;
+ final float expandedStackSize = (mLayout.getChildCount() * mBubbleSizePx)
+ + ((mLayout.getChildCount() - 1) * spaceBetweenBubbles);
+ final float centerPosition = isLandscape
+ ? availableRect.centerY()
+ : availableRect.centerX();
+ final float rowStart = centerPosition - (expandedStackSize / 2f);
+ final float positionInBar = index * (mBubbleSizePx + spaceBetweenBubbles);
+ return rowStart + positionInBar;
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/bubbles/animation/StackAnimationController.java b/packages/SystemUI/src/com/android/systemui/bubbles/animation/StackAnimationController.java
index 12051241f049..31e1ca839e5d 100644
--- a/packages/SystemUI/src/com/android/systemui/bubbles/animation/StackAnimationController.java
+++ b/packages/SystemUI/src/com/android/systemui/bubbles/animation/StackAnimationController.java
@@ -24,7 +24,6 @@ import android.graphics.RectF;
import android.provider.Settings;
import android.util.Log;
import android.view.View;
-import android.view.WindowInsets;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
@@ -35,6 +34,7 @@ import androidx.dynamicanimation.animation.SpringAnimation;
import androidx.dynamicanimation.animation.SpringForce;
import com.android.systemui.R;
+import com.android.systemui.bubbles.BubblePositioner;
import com.android.systemui.bubbles.BubbleStackView;
import com.android.wm.shell.animation.PhysicsAnimator;
import com.android.wm.shell.common.FloatingContentCoordinator;
@@ -59,12 +59,6 @@ public class StackAnimationController extends
private static final String TAG = "Bubbs.StackCtrl";
- /** Scale factor to use initially for new bubbles being animated in. */
- private static final float ANIMATE_IN_STARTING_SCALE = 1.15f;
-
- /** Translation factor (multiplied by stack offset) to use for bubbles being animated in/out. */
- private static final int ANIMATE_TRANSLATION_FACTOR = 4;
-
/** Values to use for animating bubbles in. */
private static final float ANIMATE_IN_STIFFNESS = 1000f;
private static final int ANIMATE_IN_START_DELAY = 25;
@@ -198,10 +192,8 @@ public class StackAnimationController extends
private int mBubblePaddingTop;
/** How far offscreen the stack rests. */
private int mBubbleOffscreen;
- /** How far down the screen the stack starts, when there is no pre-existing location. */
- private int mStackStartingVerticalOffset;
- /** Height of the status bar. */
- private float mStatusBarHeight;
+ /** Contains display size, orientation, and inset information. */
+ private BubblePositioner mPositioner;
/** FloatingContentCoordinator instance for resolving floating content conflicts. */
private FloatingContentCoordinator mFloatingContentCoordinator;
@@ -266,10 +258,12 @@ public class StackAnimationController extends
public StackAnimationController(
FloatingContentCoordinator floatingContentCoordinator,
IntSupplier bubbleCountSupplier,
- Runnable onBubbleAnimatedOutAction) {
+ Runnable onBubbleAnimatedOutAction,
+ BubblePositioner positioner) {
mFloatingContentCoordinator = floatingContentCoordinator;
mBubbleCountSupplier = bubbleCountSupplier;
mOnBubbleAnimatedOutAction = onBubbleAnimatedOutAction;
+ mPositioner = positioner;
}
/**
@@ -583,45 +577,12 @@ public class StackAnimationController extends
* be animated or dragged beyond them.
*/
public RectF getAllowableStackPositionRegion() {
- final WindowInsets insets = mLayout.getRootWindowInsets();
- final RectF allowableRegion = new RectF();
- if (insets != null) {
- allowableRegion.left =
- -mBubbleOffscreen
- + Math.max(
- insets.getSystemWindowInsetLeft(),
- insets.getDisplayCutout() != null
- ? insets.getDisplayCutout().getSafeInsetLeft()
- : 0);
- allowableRegion.right =
- mLayout.getWidth()
- - mBubbleSize
- + mBubbleOffscreen
- - Math.max(
- insets.getSystemWindowInsetRight(),
- insets.getDisplayCutout() != null
- ? insets.getDisplayCutout().getSafeInsetRight()
- : 0);
-
- allowableRegion.top =
- mBubblePaddingTop
- + Math.max(
- mStatusBarHeight,
- insets.getDisplayCutout() != null
- ? insets.getDisplayCutout().getSafeInsetTop()
- : 0);
- allowableRegion.bottom =
- mLayout.getHeight()
- - mBubbleSize
- - mBubblePaddingTop
- - (mImeHeight != UNSET ? mImeHeight + mBubblePaddingTop : 0f)
- - Math.max(
- insets.getStableInsetBottom(),
- insets.getDisplayCutout() != null
- ? insets.getDisplayCutout().getSafeInsetBottom()
- : 0);
- }
-
+ final RectF allowableRegion = new RectF(mPositioner.getAvailableRect());
+ allowableRegion.left -= mBubbleOffscreen;
+ allowableRegion.top += mBubblePaddingTop;
+ allowableRegion.right += mBubbleOffscreen - mBubbleSize;
+ allowableRegion.bottom -= mBubblePaddingTop + mBubbleSize
+ + (mImeHeight != UNSET ? mImeHeight + mBubblePaddingTop : 0f);
return allowableRegion;
}
@@ -824,22 +785,15 @@ public class StackAnimationController extends
mBubbleBitmapSize = res.getDimensionPixelSize(R.dimen.bubble_bitmap_size);
mBubblePaddingTop = res.getDimensionPixelSize(R.dimen.bubble_padding_top);
mBubbleOffscreen = res.getDimensionPixelSize(R.dimen.bubble_stack_offscreen);
- mStackStartingVerticalOffset =
- res.getDimensionPixelSize(R.dimen.bubble_stack_starting_offset_y);
- mStatusBarHeight =
- res.getDimensionPixelSize(com.android.internal.R.dimen.status_bar_height);
}
/**
- * Update effective screen width based on current orientation.
- * @param orientation Landscape or portrait.
+ * Update resources.
*/
- public void updateResources(int orientation) {
+ public void updateResources() {
if (mLayout != null) {
Resources res = mLayout.getContext().getResources();
mBubblePaddingTop = res.getDimensionPixelSize(R.dimen.bubble_padding_top);
- mStatusBarHeight = res.getDimensionPixelSize(
- com.android.internal.R.dimen.status_bar_height);
}
}
@@ -976,19 +930,19 @@ public class StackAnimationController extends
return;
}
- final float xOffset =
- getOffsetForChainedPropertyAnimation(DynamicAnimation.TRANSLATION_X);
+ final float yOffset =
+ getOffsetForChainedPropertyAnimation(DynamicAnimation.TRANSLATION_Y);
// Position the new bubble in the correct position, scaled down completely.
- child.setTranslationX(mStackPosition.x + xOffset * index);
- child.setTranslationY(mStackPosition.y);
+ child.setTranslationX(mStackPosition.x);
+ child.setTranslationY(mStackPosition.y + yOffset * index);
child.setScaleX(0f);
child.setScaleY(0f);
// Push the subsequent views out of the way, if there are subsequent views.
if (index + 1 < mLayout.getChildCount()) {
animationForChildAtIndex(index + 1)
- .translationX(mStackPosition.x + xOffset * (index + 1))
+ .translationY(mStackPosition.y + yOffset * (index + 1))
.withStiffness(SpringForce.STIFFNESS_LOW)
.start();
}
diff --git a/packages/SystemUI/src/com/android/systemui/dagger/DependencyProvider.java b/packages/SystemUI/src/com/android/systemui/dagger/DependencyProvider.java
index cb90b6114396..3aa462657637 100644
--- a/packages/SystemUI/src/com/android/systemui/dagger/DependencyProvider.java
+++ b/packages/SystemUI/src/com/android/systemui/dagger/DependencyProvider.java
@@ -38,7 +38,6 @@ import android.view.accessibility.AccessibilityManager;
import com.android.internal.logging.MetricsLogger;
import com.android.internal.logging.UiEventLogger;
-import com.android.internal.logging.UiEventLoggerImpl;
import com.android.internal.util.NotificationMessagingUtil;
import com.android.internal.widget.LockPatternUtils;
import com.android.keyguard.ViewMediatorCallback;
@@ -340,13 +339,6 @@ public class DependencyProvider {
return Choreographer.getInstance();
}
- /** Provides an instance of {@link com.android.internal.logging.UiEventLogger} */
- @Provides
- @SysUISingleton
- static UiEventLogger provideUiEventLogger() {
- return new UiEventLoggerImpl();
- }
-
/** */
@Provides
@SysUISingleton
diff --git a/packages/SystemUI/src/com/android/systemui/dagger/GlobalModule.java b/packages/SystemUI/src/com/android/systemui/dagger/GlobalModule.java
index c5dc8cccfdf4..554d9cbb454f 100644
--- a/packages/SystemUI/src/com/android/systemui/dagger/GlobalModule.java
+++ b/packages/SystemUI/src/com/android/systemui/dagger/GlobalModule.java
@@ -16,9 +16,20 @@
package com.android.systemui.dagger;
+import android.content.Context;
+import android.util.DisplayMetrics;
+
+import com.android.internal.logging.UiEventLogger;
+import com.android.internal.logging.UiEventLoggerImpl;
import com.android.systemui.util.concurrency.GlobalConcurrencyModule;
+import com.android.wm.shell.WindowManagerShellWrapper;
+import com.android.wm.shell.animation.FlingAnimationUtils;
+import com.android.wm.shell.common.FloatingContentCoordinator;
+
+import javax.inject.Singleton;
import dagger.Module;
+import dagger.Provides;
/**
* Supplies globally scoped instances that should be available in all versions of SystemUI
@@ -39,4 +50,38 @@ import dagger.Module;
FrameworkServicesModule.class,
GlobalConcurrencyModule.class})
public class GlobalModule {
+
+ // TODO(b/161980186): Currently only used by Bubbles, can move back to WMShellBaseModule once
+ // Bubbles has migrated over
+ @Singleton
+ @Provides
+ static FloatingContentCoordinator provideFloatingContentCoordinator() {
+ return new FloatingContentCoordinator();
+ }
+
+ // TODO(b/161980186): Currently only used by Bubbles, can move back to WMShellBaseModule once
+ // Bubbles has migrated over
+ @Singleton
+ @Provides
+ static WindowManagerShellWrapper provideWindowManagerShellWrapper() {
+ return new WindowManagerShellWrapper();
+ }
+
+ // TODO(b/162923491): This should not be a singleton at all, the display metrics can change and
+ // callers should be creating a new builder on demand
+ @Singleton
+ @Provides
+ static FlingAnimationUtils.Builder provideFlingAnimationUtilsBuilder(
+ Context context) {
+ DisplayMetrics displayMetrics = new DisplayMetrics();
+ context.getDisplay().getMetrics(displayMetrics);
+ return new FlingAnimationUtils.Builder(displayMetrics);
+ }
+
+ /** Provides an instance of {@link com.android.internal.logging.UiEventLogger} */
+ @Provides
+ @Singleton
+ static UiEventLogger provideUiEventLogger() {
+ return new UiEventLoggerImpl();
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/dagger/GlobalRootComponent.java b/packages/SystemUI/src/com/android/systemui/dagger/GlobalRootComponent.java
index 00fdf55b28e0..d648c949ffc5 100644
--- a/packages/SystemUI/src/com/android/systemui/dagger/GlobalRootComponent.java
+++ b/packages/SystemUI/src/com/android/systemui/dagger/GlobalRootComponent.java
@@ -52,7 +52,7 @@ public interface GlobalRootComponent {
WMComponent.Builder getWMComponentBuilder();
/**
- * Builder for a SysuiComponent.
+ * Builder for a SysUIComponent.
*/
SysUIComponent.Builder getSysUIComponent();
diff --git a/packages/SystemUI/src/com/android/systemui/dagger/SysUIComponent.java b/packages/SystemUI/src/com/android/systemui/dagger/SysUIComponent.java
index 4bea0674e8bf..b098579e74c3 100644
--- a/packages/SystemUI/src/com/android/systemui/dagger/SysUIComponent.java
+++ b/packages/SystemUI/src/com/android/systemui/dagger/SysUIComponent.java
@@ -22,8 +22,15 @@ import com.android.systemui.InitController;
import com.android.systemui.SystemUIAppComponentFactory;
import com.android.systemui.dump.DumpManager;
import com.android.systemui.keyguard.KeyguardSliceProvider;
+import com.android.systemui.shared.system.InputConsumerController;
import com.android.systemui.statusbar.policy.ConfigurationController;
import com.android.systemui.util.InjectionInflationController;
+import com.android.wm.shell.ShellTaskOrganizer;
+import com.android.wm.shell.onehanded.OneHanded;
+import com.android.wm.shell.pip.Pip;
+import com.android.wm.shell.splitscreen.SplitScreen;
+
+import java.util.Optional;
import dagger.BindsInstance;
import dagger.Subcomponent;
@@ -43,15 +50,35 @@ public interface SysUIComponent {
/**
* Builder for a SysUIComponent.
*/
+ @SysUISingleton
@Subcomponent.Builder
interface Builder {
@BindsInstance
- Builder setStubAPIClass(WMComponent.StubAPIClass stubAPIClass);
+ Builder setPip(Optional<Pip> p);
+
+ @BindsInstance
+ Builder setSplitScreen(Optional<SplitScreen> s);
+
+ @BindsInstance
+ Builder setOneHanded(Optional<OneHanded> o);
+
+ @BindsInstance
+ Builder setInputConsumerController(InputConsumerController i);
+
+ @BindsInstance
+ Builder setShellTaskOrganizer(ShellTaskOrganizer s);
SysUIComponent build();
}
/**
+ * Initializes all the SysUI components.
+ */
+ default void init() {
+ // Do nothing
+ }
+
+ /**
* Provides a BootCompleteCache.
*/
@SysUISingleton
diff --git a/packages/SystemUI/src/com/android/systemui/dagger/SystemUIDefaultModule.java b/packages/SystemUI/src/com/android/systemui/dagger/SystemUIDefaultModule.java
index 7d5683f48769..7ca8e63bfae1 100644
--- a/packages/SystemUI/src/com/android/systemui/dagger/SystemUIDefaultModule.java
+++ b/packages/SystemUI/src/com/android/systemui/dagger/SystemUIDefaultModule.java
@@ -62,7 +62,6 @@ import com.android.systemui.statusbar.policy.ConfigurationController;
import com.android.systemui.statusbar.policy.DeviceProvisionedController;
import com.android.systemui.statusbar.policy.DeviceProvisionedControllerImpl;
import com.android.systemui.statusbar.policy.HeadsUpManager;
-import com.android.systemui.wmshell.WMShellModule;
import javax.inject.Named;
@@ -76,8 +75,7 @@ import dagger.Provides;
*/
@Module(includes = {
MediaModule.class,
- QSModule.class,
- WMShellModule.class
+ QSModule.class
})
public abstract class SystemUIDefaultModule {
diff --git a/packages/SystemUI/src/com/android/systemui/dagger/SystemUIModule.java b/packages/SystemUI/src/com/android/systemui/dagger/SystemUIModule.java
index 63d9a831b33f..a982ec5c0194 100644
--- a/packages/SystemUI/src/com/android/systemui/dagger/SystemUIModule.java
+++ b/packages/SystemUI/src/com/android/systemui/dagger/SystemUIModule.java
@@ -21,6 +21,7 @@ import com.android.systemui.BootCompleteCache;
import com.android.systemui.BootCompleteCacheImpl;
import com.android.systemui.appops.dagger.AppOpsModule;
import com.android.systemui.assist.AssistModule;
+import com.android.systemui.bubbles.Bubbles;
import com.android.systemui.controls.dagger.ControlsModule;
import com.android.systemui.demomode.dagger.DemoModeModule;
import com.android.systemui.doze.dagger.DozeComponent;
@@ -125,6 +126,9 @@ public abstract class SystemUIModule {
@BindsOptionalOf
abstract StatusBar optionalStatusBar();
+ @BindsOptionalOf
+ abstract Bubbles optionalBubbles();
+
@SysUISingleton
@Binds
abstract SystemClock bindSystemClock(SystemClockImpl systemClock);
diff --git a/packages/SystemUI/src/com/android/systemui/dagger/WMComponent.java b/packages/SystemUI/src/com/android/systemui/dagger/WMComponent.java
index ad90eff3c969..e3bd1b2b7db2 100644
--- a/packages/SystemUI/src/com/android/systemui/dagger/WMComponent.java
+++ b/packages/SystemUI/src/com/android/systemui/dagger/WMComponent.java
@@ -16,7 +16,15 @@
package com.android.systemui.dagger;
-import javax.inject.Inject;
+import com.android.systemui.shared.system.InputConsumerController;
+import com.android.systemui.wmshell.WMShellModule;
+import com.android.wm.shell.ShellTaskOrganizer;
+import com.android.wm.shell.common.DisplayImeController;
+import com.android.wm.shell.onehanded.OneHanded;
+import com.android.wm.shell.pip.Pip;
+import com.android.wm.shell.splitscreen.SplitScreen;
+
+import java.util.Optional;
import dagger.Subcomponent;
@@ -24,7 +32,7 @@ import dagger.Subcomponent;
* Dagger Subcomponent for WindowManager.
*/
@WMSingleton
-@Subcomponent(modules = {})
+@Subcomponent(modules = {WMShellModule.class})
public interface WMComponent {
/**
@@ -35,18 +43,36 @@ public interface WMComponent {
WMComponent build();
}
-
/**
- * Example class used for passing an API to SysUI from WMShell.
- *
- * TODO: Remove this once real WM classes are ready to go.
- **/
- @WMSingleton
- class StubAPIClass {
- @Inject
- StubAPIClass() {}
+ * Initializes all the WMShell components before starting any of the SystemUI components.
+ */
+ default void init() {
+ // This is to prevent circular init problem by separating registration step out of its
+ // constructor. And make sure the initialization of DisplayImeController won't depend on
+ // specific feature anymore.
+ getDisplayImeController().startMonitorDisplays();
+ getShellTaskOrganizer().registerOrganizer();
}
- /** Create a StubAPIClass. */
- StubAPIClass createStubAPIClass();
+ // Required components to be initialized at start up
+ @WMSingleton
+ ShellTaskOrganizer getShellTaskOrganizer();
+
+ @WMSingleton
+ DisplayImeController getDisplayImeController();
+
+ @WMSingleton
+ InputConsumerController getInputConsumerController();
+
+ // TODO(b/162923491): We currently pass the instances through to SysUI, but that may change
+ // depending on the threading mechanism we go with
+
+ @WMSingleton
+ Optional<OneHanded> getOneHanded();
+
+ @WMSingleton
+ Optional<Pip> getPip();
+
+ @WMSingleton
+ Optional<SplitScreen> getSplitScreen();
}
diff --git a/packages/SystemUI/src/com/android/keyguard/dagger/RootView.java b/packages/SystemUI/src/com/android/systemui/dagger/qualifiers/RootView.java
index 5ebff097604b..e6c46c07fff8 100644
--- a/packages/SystemUI/src/com/android/keyguard/dagger/RootView.java
+++ b/packages/SystemUI/src/com/android/systemui/dagger/qualifiers/RootView.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2019 The Android Open Source Project
+ * 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.
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package com.android.keyguard.dagger;
+package com.android.systemui.dagger.qualifiers;
import static java.lang.annotation.RetentionPolicy.RUNTIME;
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardSliceProvider.java b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardSliceProvider.java
index 5f726cd1e1f9..37bcb163d6f3 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardSliceProvider.java
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardSliceProvider.java
@@ -316,7 +316,8 @@ public class KeyguardSliceProvider extends SliceProvider implements
}
mDatePattern = getContext().getString(R.string.system_ui_aod_date_pattern);
mPendingIntent = PendingIntent.getActivity(getContext(), 0,
- new Intent(getContext(), KeyguardSliceProvider.class), 0);
+ new Intent(getContext(), KeyguardSliceProvider.class),
+ PendingIntent.FLAG_IMMUTABLE);
try {
//TODO(b/168778439): Remove this whole try catch. This is for debugging in dogfood.
mMediaManager.addCallback(this);
diff --git a/packages/SystemUI/src/com/android/systemui/media/SeekBarViewModel.kt b/packages/SystemUI/src/com/android/systemui/media/SeekBarViewModel.kt
index 9e326aaec3c1..c8244589ce44 100644
--- a/packages/SystemUI/src/com/android/systemui/media/SeekBarViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/media/SeekBarViewModel.kt
@@ -91,9 +91,9 @@ class SeekBarViewModel @Inject constructor(@Background private val bgExecutor: R
}
private var playbackState: PlaybackState? = null
private var callback = object : MediaController.Callback() {
- override fun onPlaybackStateChanged(state: PlaybackState) {
+ override fun onPlaybackStateChanged(state: PlaybackState?) {
playbackState = state
- if (PlaybackState.STATE_NONE.equals(playbackState)) {
+ if (playbackState == null || PlaybackState.STATE_NONE.equals(playbackState)) {
clearController()
} else {
checkIfPollingNeeded()
diff --git a/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputAdapter.java b/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputAdapter.java
index d1630ebe8dc8..d26f7ab6d78c 100644
--- a/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputAdapter.java
+++ b/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputAdapter.java
@@ -109,34 +109,45 @@ public class MediaOutputAdapter extends MediaOutputBaseAdapter {
super.onBind(device, topMargin, bottomMargin);
final boolean currentlyConnected = isCurrentlyConnected(device);
if (currentlyConnected) {
- mConnectedItem = mFrameLayout;
+ mConnectedItem = mContainerLayout;
+ }
+ mBottomDivider.setVisibility(View.GONE);
+ mCheckBox.setVisibility(View.GONE);
+ if (currentlyConnected && mController.isActiveRemoteDevice(device)) {
+ // Init active device layout
+ mDivider.setVisibility(View.VISIBLE);
+ mDivider.setTransitionAlpha(1);
+ mAddIcon.setVisibility(View.VISIBLE);
+ mAddIcon.setTransitionAlpha(1);
+ mAddIcon.setOnClickListener(v -> onEndItemClick());
+ } else {
+ // Init non-active device layout
+ mDivider.setVisibility(View.GONE);
+ mAddIcon.setVisibility(View.GONE);
}
if (mController.isTransferring()) {
if (device.getState() == MediaDeviceState.STATE_CONNECTING
&& !mController.hasAdjustVolumeUserRestriction()) {
- setTwoLineLayout(device, null /* title */, true /* bFocused */,
- false /* showSeekBar*/, true /* showProgressBar */,
- false /* showSubtitle */);
+ setTwoLineLayout(device, true /* bFocused */, false /* showSeekBar*/,
+ true /* showProgressBar */, false /* showSubtitle */);
} else {
setSingleLineLayout(getItemTitle(device), false /* bFocused */);
}
} else {
// Set different layout for each device
if (device.getState() == MediaDeviceState.STATE_CONNECTING_FAILED) {
- setTwoLineLayout(device, null /* title */, false /* bFocused */,
- false /* showSeekBar*/, false /* showProgressBar */,
+ setTwoLineLayout(device, false /* bFocused */,
+ false /* showSeekBar */, false /* showProgressBar */,
true /* showSubtitle */);
mSubTitleText.setText(R.string.media_output_dialog_connect_failed);
- mFrameLayout.setOnClickListener(v -> onItemClick(v, device));
- } else if (!mController.hasAdjustVolumeUserRestriction()
- && currentlyConnected) {
- setTwoLineLayout(device, null /* title */, true /* bFocused */,
- true /* showSeekBar*/, false /* showProgressBar */,
- false /* showSubtitle */);
+ mContainerLayout.setOnClickListener(v -> onItemClick(v, device));
+ } else if (!mController.hasAdjustVolumeUserRestriction() && currentlyConnected) {
+ setTwoLineLayout(device, true /* bFocused */, true /* showSeekBar */,
+ false /* showProgressBar */, false /* showSubtitle */);
initSeekbar(device);
} else {
setSingleLineLayout(getItemTitle(device), false /* bFocused */);
- mFrameLayout.setOnClickListener(v -> onItemClick(v, device));
+ mContainerLayout.setOnClickListener(v -> onItemClick(v, device));
}
}
}
@@ -145,13 +156,17 @@ public class MediaOutputAdapter extends MediaOutputBaseAdapter {
void onBind(int customizedItem, boolean topMargin, boolean bottomMargin) {
super.onBind(customizedItem, topMargin, bottomMargin);
if (customizedItem == CUSTOMIZED_ITEM_PAIR_NEW) {
+ mCheckBox.setVisibility(View.GONE);
+ mDivider.setVisibility(View.GONE);
+ mAddIcon.setVisibility(View.GONE);
+ mBottomDivider.setVisibility(View.GONE);
setSingleLineLayout(mContext.getText(R.string.media_output_dialog_pairing_new),
false /* bFocused */);
final Drawable d = mContext.getDrawable(R.drawable.ic_add);
d.setColorFilter(new PorterDuffColorFilter(
Utils.getColorAccentDefaultColor(mContext), PorterDuff.Mode.SRC_IN));
mTitleIcon.setImageDrawable(d);
- mFrameLayout.setOnClickListener(v -> onItemClick(CUSTOMIZED_ITEM_PAIR_NEW));
+ mContainerLayout.setOnClickListener(v -> onItemClick(CUSTOMIZED_ITEM_PAIR_NEW));
}
}
@@ -173,5 +188,9 @@ public class MediaOutputAdapter extends MediaOutputBaseAdapter {
mController.launchBluetoothPairing();
}
}
+
+ private void onEndItemClick() {
+ mController.launchMediaOutputGroupDialog();
+ }
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputBaseAdapter.java b/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputBaseAdapter.java
index 2d3e77db1ea3..536b7598ce22 100644
--- a/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputBaseAdapter.java
+++ b/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputBaseAdapter.java
@@ -24,8 +24,9 @@ import android.text.TextUtils;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
-import android.widget.FrameLayout;
+import android.widget.CheckBox;
import android.widget.ImageView;
+import android.widget.LinearLayout;
import android.widget.ProgressBar;
import android.widget.RelativeLayout;
import android.widget.SeekBar;
@@ -44,19 +45,17 @@ import com.android.systemui.R;
public abstract class MediaOutputBaseAdapter extends
RecyclerView.Adapter<MediaOutputBaseAdapter.MediaDeviceBaseViewHolder> {
- private static final String FONT_SELECTED_TITLE = "sans-serif-medium";
- private static final String FONT_TITLE = "sans-serif";
-
static final int CUSTOMIZED_ITEM_PAIR_NEW = 1;
+ static final int CUSTOMIZED_ITEM_GROUP = 2;
final MediaOutputController mController;
- private boolean mIsDragging;
private int mMargin;
private boolean mIsAnimating;
Context mContext;
View mHolderView;
+ boolean mIsDragging;
public MediaOutputBaseAdapter(MediaOutputController controller) {
mController = controller;
@@ -99,27 +98,33 @@ public abstract class MediaOutputBaseAdapter extends
private static final int ANIM_DURATION = 200;
- final FrameLayout mFrameLayout;
+ final LinearLayout mContainerLayout;
final TextView mTitleText;
final TextView mTwoLineTitleText;
final TextView mSubTitleText;
final ImageView mTitleIcon;
- final ImageView mEndIcon;
+ final ImageView mAddIcon;
final ProgressBar mProgressBar;
final SeekBar mSeekBar;
final RelativeLayout mTwoLineLayout;
+ final View mDivider;
+ final View mBottomDivider;
+ final CheckBox mCheckBox;
MediaDeviceBaseViewHolder(View view) {
super(view);
- mFrameLayout = view.requireViewById(R.id.device_container);
+ mContainerLayout = view.requireViewById(R.id.device_container);
mTitleText = view.requireViewById(R.id.title);
mSubTitleText = view.requireViewById(R.id.subtitle);
mTwoLineLayout = view.requireViewById(R.id.two_line_layout);
mTwoLineTitleText = view.requireViewById(R.id.two_line_title);
mTitleIcon = view.requireViewById(R.id.title_icon);
- mEndIcon = view.requireViewById(R.id.end_icon);
mProgressBar = view.requireViewById(R.id.volume_indeterminate_progress);
mSeekBar = view.requireViewById(R.id.volume_seekbar);
+ mDivider = view.requireViewById(R.id.end_divider);
+ mBottomDivider = view.requireViewById(R.id.bottom_divider);
+ mAddIcon = view.requireViewById(R.id.add_icon);
+ mCheckBox = view.requireViewById(R.id.check_box);
}
void onBind(MediaDevice device, boolean topMargin, boolean bottomMargin) {
@@ -132,11 +137,11 @@ public abstract class MediaOutputBaseAdapter extends
}
private void setMargin(boolean topMargin, boolean bottomMargin) {
- ViewGroup.MarginLayoutParams params = (ViewGroup.MarginLayoutParams) mFrameLayout
+ ViewGroup.MarginLayoutParams params = (ViewGroup.MarginLayoutParams) mContainerLayout
.getLayoutParams();
params.topMargin = topMargin ? mMargin : 0;
params.bottomMargin = bottomMargin ? mMargin : 0;
- mFrameLayout.setLayoutParams(params);
+ mContainerLayout.setLayoutParams(params);
}
void setSingleLineLayout(CharSequence title, boolean bFocused) {
@@ -146,13 +151,26 @@ public abstract class MediaOutputBaseAdapter extends
mTitleText.setTranslationY(0);
mTitleText.setText(title);
if (bFocused) {
- mTitleText.setTypeface(Typeface.create(FONT_SELECTED_TITLE, Typeface.NORMAL));
+ mTitleText.setTypeface(Typeface.create(mContext.getString(
+ com.android.internal.R.string.config_headlineFontFamilyMedium),
+ Typeface.NORMAL));
} else {
- mTitleText.setTypeface(Typeface.create(FONT_TITLE, Typeface.NORMAL));
+ mTitleText.setTypeface(Typeface.create(mContext.getString(
+ com.android.internal.R.string.config_headlineFontFamily), Typeface.NORMAL));
}
}
- void setTwoLineLayout(MediaDevice device, CharSequence title, boolean bFocused,
+ void setTwoLineLayout(MediaDevice device, boolean bFocused, boolean showSeekBar,
+ boolean showProgressBar, boolean showSubtitle) {
+ setTwoLineLayout(device, null, bFocused, showSeekBar, showProgressBar, showSubtitle);
+ }
+
+ void setTwoLineLayout(CharSequence title, boolean bFocused, boolean showSeekBar,
+ boolean showProgressBar, boolean showSubtitle) {
+ setTwoLineLayout(null, title, bFocused, showSeekBar, showProgressBar, showSubtitle);
+ }
+
+ private void setTwoLineLayout(MediaDevice device, CharSequence title, boolean bFocused,
boolean showSeekBar, boolean showProgressBar, boolean showSubtitle) {
mTitleText.setVisibility(View.GONE);
mTwoLineLayout.setVisibility(View.VISIBLE);
@@ -168,18 +186,21 @@ public abstract class MediaOutputBaseAdapter extends
}
if (bFocused) {
- mTwoLineTitleText.setTypeface(Typeface.create(FONT_SELECTED_TITLE,
+ mTwoLineTitleText.setTypeface(Typeface.create(mContext.getString(
+ com.android.internal.R.string.config_headlineFontFamilyMedium),
Typeface.NORMAL));
} else {
- mTwoLineTitleText.setTypeface(Typeface.create(FONT_TITLE, Typeface.NORMAL));
+ mTwoLineTitleText.setTypeface(Typeface.create(mContext.getString(
+ com.android.internal.R.string.config_headlineFontFamily), Typeface.NORMAL));
}
}
void initSeekbar(MediaDevice device) {
mSeekBar.setMax(device.getMaxVolume());
mSeekBar.setMin(0);
- if (mSeekBar.getProgress() != device.getCurrentVolume()) {
- mSeekBar.setProgress(device.getCurrentVolume());
+ final int currentVolume = device.getCurrentVolume();
+ if (mSeekBar.getProgress() != currentVolume) {
+ mSeekBar.setProgress(currentVolume);
}
mSeekBar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
@Override
@@ -213,7 +234,9 @@ public abstract class MediaOutputBaseAdapter extends
}
mIsAnimating = true;
// Animation for title text
- toTitleText.setTypeface(Typeface.create(FONT_SELECTED_TITLE, Typeface.NORMAL));
+ toTitleText.setTypeface(Typeface.create(mContext.getString(
+ com.android.internal.R.string.config_headlineFontFamilyMedium),
+ Typeface.NORMAL));
toTitleText.animate()
.setDuration(ANIM_DURATION)
.translationY(-delta)
@@ -234,7 +257,9 @@ public abstract class MediaOutputBaseAdapter extends
public void onAnimationEnd(Animator animation) {
final TextView fromTitleText = from.requireViewById(
R.id.two_line_title);
- fromTitleText.setTypeface(Typeface.create(FONT_TITLE, Typeface.NORMAL));
+ fromTitleText.setTypeface(Typeface.create(mContext.getString(
+ com.android.internal.R.string.config_headlineFontFamily),
+ Typeface.NORMAL));
fromTitleText.animate()
.setDuration(ANIM_DURATION)
.translationY(delta)
diff --git a/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputBaseDialog.java b/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputBaseDialog.java
index caef536961f1..78939dffb4fb 100644
--- a/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputBaseDialog.java
+++ b/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputBaseDialog.java
@@ -119,6 +119,8 @@ public abstract class MediaOutputBaseDialog extends SystemUIDialog implements
// Init device list
mDevicesRecyclerView.setLayoutManager(mLayoutManager);
mDevicesRecyclerView.setAdapter(mAdapter);
+ // Init header icon
+ mHeaderIcon.setOnClickListener(v -> onHeaderIconClick());
// Init bottom buttons
mDoneButton.setOnClickListener(v -> dismiss());
mStopButton.setOnClickListener(v -> {
@@ -218,4 +220,7 @@ public abstract class MediaOutputBaseDialog extends SystemUIDialog implements
dismiss();
}
}
+
+ void onHeaderIconClick() {
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputController.java b/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputController.java
index b1f1bda25961..b9fa87252125 100644
--- a/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputController.java
+++ b/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputController.java
@@ -71,6 +71,8 @@ public class MediaOutputController implements LocalMediaManager.DeviceCallback{
private final MediaSessionManager mMediaSessionManager;
private final ShadeController mShadeController;
private final ActivityStarter mActivityStarter;
+ private final List<MediaDevice> mGroupMediaDevices = new CopyOnWriteArrayList<>();
+ private final boolean mAboveStatusbar;
@VisibleForTesting
final List<MediaDevice> mMediaDevices = new CopyOnWriteArrayList<>();
@@ -82,13 +84,14 @@ public class MediaOutputController implements LocalMediaManager.DeviceCallback{
@Inject
public MediaOutputController(@NonNull Context context, String packageName,
- MediaSessionManager mediaSessionManager, LocalBluetoothManager
+ boolean aboveStatusbar, MediaSessionManager mediaSessionManager, LocalBluetoothManager
lbm, ShadeController shadeController, ActivityStarter starter) {
mContext = context;
mPackageName = packageName;
mMediaSessionManager = mediaSessionManager;
mShadeController = shadeController;
mActivityStarter = starter;
+ mAboveStatusbar = aboveStatusbar;
InfoMediaManager imm = new InfoMediaManager(mContext, packageName, null, lbm);
mLocalMediaManager = new LocalMediaManager(mContext, lbm, imm, packageName);
}
@@ -271,6 +274,42 @@ public class MediaOutputController implements LocalMediaManager.DeviceCallback{
mMediaDevices.addAll(targetMediaDevices);
}
+ List<MediaDevice> getGroupMediaDevices() {
+ final List<MediaDevice> selectedDevices = getSelectedMediaDevice();
+ final List<MediaDevice> selectableDevices = getSelectableMediaDevice();
+ if (mGroupMediaDevices.isEmpty()) {
+ mGroupMediaDevices.addAll(selectedDevices);
+ mGroupMediaDevices.addAll(selectableDevices);
+ return mGroupMediaDevices;
+ }
+ // To keep the same list order
+ final Collection<MediaDevice> sourceDevices = new ArrayList<>();
+ final Collection<MediaDevice> targetMediaDevices = new ArrayList<>();
+ sourceDevices.addAll(selectedDevices);
+ sourceDevices.addAll(selectableDevices);
+ for (MediaDevice originalDevice : mGroupMediaDevices) {
+ for (MediaDevice newDevice : sourceDevices) {
+ if (TextUtils.equals(originalDevice.getId(), newDevice.getId())) {
+ targetMediaDevices.add(newDevice);
+ sourceDevices.remove(newDevice);
+ break;
+ }
+ }
+ }
+ // Add new devices at the end of list if necessary
+ if (!sourceDevices.isEmpty()) {
+ targetMediaDevices.addAll(sourceDevices);
+ }
+ mGroupMediaDevices.clear();
+ mGroupMediaDevices.addAll(targetMediaDevices);
+
+ return mGroupMediaDevices;
+ }
+
+ void resetGroupMediaDevices() {
+ mGroupMediaDevices.clear();
+ }
+
void connectDevice(MediaDevice device) {
ThreadUtils.postOnBackgroundThread(() -> {
mLocalMediaManager.connectDevice(device);
@@ -309,15 +348,6 @@ public class MediaOutputController implements LocalMediaManager.DeviceCallback{
return mLocalMediaManager.getDeselectableMediaDevice();
}
- boolean isDeviceIncluded(Collection<MediaDevice> deviceCollection, MediaDevice targetDevice) {
- for (MediaDevice device : deviceCollection) {
- if (TextUtils.equals(device.getId(), targetDevice.getId())) {
- return true;
- }
- }
- return false;
- }
-
void adjustSessionVolume(String sessionId, int volume) {
mLocalMediaManager.adjustSessionVolume(sessionId, volume);
}
@@ -407,6 +437,16 @@ public class MediaOutputController implements LocalMediaManager.DeviceCallback{
mActivityStarter.dismissKeyguardThenExecute(postKeyguardAction, null, true);
}
+ void launchMediaOutputDialog() {
+ mCallback.dismissDialog();
+ new MediaOutputDialog(mContext, mAboveStatusbar, this);
+ }
+
+ void launchMediaOutputGroupDialog() {
+ mCallback.dismissDialog();
+ new MediaOutputGroupDialog(mContext, mAboveStatusbar, this);
+ }
+
boolean isActiveRemoteDevice(@NonNull MediaDevice device) {
final List<String> features = device.getFeatures();
return (features.contains(MediaRoute2Info.FEATURE_REMOTE_PLAYBACK)
diff --git a/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputDialogFactory.kt b/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputDialogFactory.kt
index 4cdca4cbcf1e..e912b7d1b08f 100644
--- a/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputDialogFactory.kt
+++ b/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputDialogFactory.kt
@@ -40,9 +40,8 @@ class MediaOutputDialogFactory @Inject constructor(
/** Creates a [MediaOutputDialog] for the given package. */
fun create(packageName: String, aboveStatusBar: Boolean) {
mediaOutputDialog?.dismiss()
-
- mediaOutputDialog = MediaOutputController(context, packageName, mediaSessionManager, lbm,
- shadeController, starter).run {
+ mediaOutputDialog = MediaOutputController(context, packageName, aboveStatusBar,
+ mediaSessionManager, lbm, shadeController, starter).run {
MediaOutputDialog(context, aboveStatusBar, this) }
}
diff --git a/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputGroupAdapter.java b/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputGroupAdapter.java
new file mode 100644
index 000000000000..ceb4495bd8e8
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputGroupAdapter.java
@@ -0,0 +1,220 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.media.dialog;
+
+import android.content.res.ColorStateList;
+import android.graphics.Bitmap;
+import android.graphics.Canvas;
+import android.graphics.PorterDuff;
+import android.graphics.PorterDuffColorFilter;
+import android.graphics.drawable.Drawable;
+import android.text.TextUtils;
+import android.util.Log;
+import android.util.TypedValue;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.SeekBar;
+
+import androidx.annotation.NonNull;
+
+import com.android.settingslib.bluetooth.BluetoothUtils;
+import com.android.settingslib.media.MediaDevice;
+import com.android.systemui.R;
+
+import java.util.List;
+
+/**
+ * Adapter for media output dynamic group dialog.
+ */
+public class MediaOutputGroupAdapter extends MediaOutputBaseAdapter {
+
+ private static final String TAG = "MediaOutputGroupAdapter";
+ private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
+
+ private final List<MediaDevice> mGroupMediaDevices;
+
+ public MediaOutputGroupAdapter(MediaOutputController controller) {
+ super(controller);
+ mGroupMediaDevices = controller.getGroupMediaDevices();
+ }
+
+ @Override
+ public MediaDeviceBaseViewHolder onCreateViewHolder(@NonNull ViewGroup viewGroup,
+ int viewType) {
+ super.onCreateViewHolder(viewGroup, viewType);
+
+ return new GroupViewHolder(mHolderView);
+ }
+
+ @Override
+ public void onBindViewHolder(@NonNull MediaDeviceBaseViewHolder viewHolder, int position) {
+ // Add "Group"
+ if (position == 0) {
+ viewHolder.onBind(CUSTOMIZED_ITEM_GROUP, true /* topMargin */,
+ false /* bottomMargin */);
+ return;
+ }
+ // Add available devices
+ final int newPosition = position - 1;
+ final int size = mGroupMediaDevices.size();
+ if (newPosition < size) {
+ viewHolder.onBind(mGroupMediaDevices.get(newPosition), false /* topMargin */,
+ newPosition == (size - 1) /* bottomMargin */);
+ return;
+ }
+ if (DEBUG) {
+ Log.d(TAG, "Incorrect position: " + position);
+ }
+ }
+
+ @Override
+ public int getItemCount() {
+ // Require extra item for group volume operation
+ return mGroupMediaDevices.size() + 1;
+ }
+
+ @Override
+ CharSequence getItemTitle(MediaDevice device) {
+ return super.getItemTitle(device);
+ }
+
+ class GroupViewHolder extends MediaDeviceBaseViewHolder {
+
+ GroupViewHolder(View view) {
+ super(view);
+ }
+
+ @Override
+ void onBind(MediaDevice device, boolean topMargin, boolean bottomMargin) {
+ super.onBind(device, topMargin, bottomMargin);
+ mDivider.setVisibility(View.GONE);
+ mAddIcon.setVisibility(View.GONE);
+ mBottomDivider.setVisibility(View.GONE);
+ mCheckBox.setVisibility(View.VISIBLE);
+ mCheckBox.setOnCheckedChangeListener((buttonView, isChecked) -> {
+ onCheckBoxClicked(isChecked, device);
+ });
+ setTwoLineLayout(device, false /* bFocused */, true /* showSeekBar */,
+ false /* showProgressBar */, false /* showSubtitle*/);
+ initSeekbar(device);
+ final List<MediaDevice> selectedDevices = mController.getSelectedMediaDevice();
+ if (isDeviceIncluded(mController.getSelectableMediaDevice(), device)) {
+ mCheckBox.setButtonDrawable(R.drawable.ic_check_box);
+ mCheckBox.setChecked(false);
+ mCheckBox.setEnabled(true);
+ } else if (isDeviceIncluded(selectedDevices, device)) {
+ if (selectedDevices.size() == 1 || !isDeviceIncluded(
+ mController.getDeselectableMediaDevice(), device)) {
+ mCheckBox.setButtonDrawable(getDisabledCheckboxDrawable());
+ mCheckBox.setChecked(true);
+ mCheckBox.setEnabled(false);
+ } else {
+ mCheckBox.setButtonDrawable(R.drawable.ic_check_box);
+ mCheckBox.setChecked(true);
+ mCheckBox.setEnabled(true);
+ }
+ }
+ }
+
+ @Override
+ void onBind(int customizedItem, boolean topMargin, boolean bottomMargin) {
+ super.onBind(customizedItem, topMargin, bottomMargin);
+ if (customizedItem == CUSTOMIZED_ITEM_GROUP) {
+ setTwoLineLayout(mContext.getText(R.string.media_output_dialog_group),
+ true /* bFocused */, true /* showSeekBar */, false /* showProgressBar */,
+ false /* showSubtitle*/);
+ mTitleIcon.setImageDrawable(getSpeakerDrawable());
+ mBottomDivider.setVisibility(View.VISIBLE);
+ mCheckBox.setVisibility(View.GONE);
+ mDivider.setVisibility(View.GONE);
+ mAddIcon.setVisibility(View.GONE);
+ initSessionSeekbar();
+ }
+ }
+
+ private void onCheckBoxClicked(boolean isChecked, MediaDevice device) {
+ if (isChecked && isDeviceIncluded(mController.getSelectableMediaDevice(), device)) {
+ mController.addDeviceToPlayMedia(device);
+ } else if (!isChecked && isDeviceIncluded(mController.getDeselectableMediaDevice(),
+ device)) {
+ mController.removeDeviceFromPlayMedia(device);
+ }
+ }
+
+ private void initSessionSeekbar() {
+ mSeekBar.setMax(mController.getSessionVolumeMax());
+ mSeekBar.setMin(0);
+ final int currentVolume = mController.getSessionVolume();
+ if (mSeekBar.getProgress() != currentVolume) {
+ mSeekBar.setProgress(currentVolume);
+ }
+ mSeekBar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
+ @Override
+ public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
+ if (!fromUser) {
+ return;
+ }
+ mController.adjustSessionVolume(progress);
+ }
+
+ @Override
+ public void onStartTrackingTouch(SeekBar seekBar) {
+ mIsDragging = true;
+ }
+
+ @Override
+ public void onStopTrackingTouch(SeekBar seekBar) {
+ mIsDragging = false;
+ }
+ });
+ }
+
+ private Drawable getDisabledCheckboxDrawable() {
+ final Drawable drawable = mContext.getDrawable(R.drawable.ic_check_box_blue_24dp)
+ .mutate();
+ final Bitmap checkbox = Bitmap.createBitmap(drawable.getIntrinsicWidth(),
+ drawable.getIntrinsicHeight(), Bitmap.Config.ARGB_8888);
+ final Canvas canvas = new Canvas(checkbox);
+ TypedValue value = new TypedValue();
+ mContext.getTheme().resolveAttribute(android.R.attr.disabledAlpha, value, true);
+ drawable.setAlpha((int) (value.getFloat() * 255));
+ drawable.setBounds(0, 0, canvas.getWidth(), canvas.getHeight());
+ drawable.draw(canvas);
+
+ return drawable;
+ }
+
+ private Drawable getSpeakerDrawable() {
+ final Drawable drawable = mContext.getDrawable(R.drawable.ic_speaker_group_black_24dp)
+ .mutate();
+ final ColorStateList list = mContext.getResources().getColorStateList(
+ R.color.advanced_icon_color, mContext.getTheme());
+ drawable.setColorFilter(new PorterDuffColorFilter(list.getDefaultColor(),
+ PorterDuff.Mode.SRC_IN));
+ return BluetoothUtils.buildAdvancedDrawable(mContext, drawable);
+ }
+
+ private boolean isDeviceIncluded(List<MediaDevice> deviceList, MediaDevice targetDevice) {
+ for (MediaDevice device : deviceList) {
+ if (TextUtils.equals(device.getId(), targetDevice.getId())) {
+ return true;
+ }
+ }
+ return false;
+ }
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputGroupDialog.java b/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputGroupDialog.java
new file mode 100644
index 000000000000..407930492fbe
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputGroupDialog.java
@@ -0,0 +1,88 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.media.dialog;
+
+import android.content.Context;
+import android.os.Bundle;
+import android.view.View;
+import android.view.WindowManager;
+
+import androidx.core.graphics.drawable.IconCompat;
+
+import com.android.systemui.R;
+
+/**
+ * Dialog for media output group.
+ */
+public class MediaOutputGroupDialog extends MediaOutputBaseDialog {
+
+ MediaOutputGroupDialog(Context context, boolean aboveStatusbar, MediaOutputController
+ mediaOutputController) {
+ super(context, mediaOutputController);
+ mMediaOutputController.resetGroupMediaDevices();
+ mAdapter = new MediaOutputGroupAdapter(mMediaOutputController);
+ if (!aboveStatusbar) {
+ getWindow().setType(WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY);
+ }
+ show();
+ }
+
+ @Override
+ public void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ }
+
+ @Override
+ int getHeaderIconRes() {
+ return R.drawable.ic_arrow_back;
+ }
+
+ @Override
+ IconCompat getHeaderIcon() {
+ return null;
+ }
+
+ @Override
+ int getHeaderIconSize() {
+ return mContext.getResources().getDimensionPixelSize(
+ R.dimen.media_output_dialog_header_back_icon_size);
+ }
+
+ @Override
+ CharSequence getHeaderText() {
+ return mContext.getString(R.string.media_output_dialog_add_output);
+ }
+
+ @Override
+ CharSequence getHeaderSubtitle() {
+ final int size = mMediaOutputController.getSelectedMediaDevice().size();
+ if (size == 1) {
+ return mContext.getText(R.string.media_output_dialog_single_device);
+ }
+ return mContext.getString(R.string.media_output_dialog_multiple_devices, size);
+ }
+
+ @Override
+ int getStopButtonVisibility() {
+ return View.VISIBLE;
+ }
+
+ @Override
+ void onHeaderIconClick() {
+ mMediaOutputController.launchMediaOutputDialog();
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/people/PeopleSpaceActivity.java b/packages/SystemUI/src/com/android/systemui/people/PeopleSpaceActivity.java
index eeb93bb7d766..6a78c64638aa 100644
--- a/packages/SystemUI/src/com/android/systemui/people/PeopleSpaceActivity.java
+++ b/packages/SystemUI/src/com/android/systemui/people/PeopleSpaceActivity.java
@@ -23,22 +23,15 @@ import android.content.Context;
import android.content.pm.LauncherApps;
import android.content.pm.PackageManager;
import android.content.pm.ShortcutInfo;
-import android.icu.text.MeasureFormat;
-import android.icu.util.Measure;
-import android.icu.util.MeasureUnit;
import android.os.Bundle;
import android.os.ServiceManager;
import android.os.UserHandle;
-import android.service.notification.ConversationChannelWrapper;
import android.util.Log;
import android.view.ViewGroup;
import com.android.systemui.R;
-import java.time.Duration;
import java.util.List;
-import java.util.Locale;
-import java.util.stream.Collectors;
/**
* Shows the user their tiles for their priority People (go/live-status).
@@ -52,7 +45,6 @@ public class PeopleSpaceActivity extends Activity {
private INotificationManager mNotificationManager;
private PackageManager mPackageManager;
private LauncherApps mLauncherApps;
- private List<ConversationChannelWrapper> mConversations;
private Context mContext;
@Override
@@ -77,15 +69,13 @@ public class PeopleSpaceActivity extends Activity {
*/
private void setTileViewsWithPriorityConversations() {
try {
- List<ConversationChannelWrapper> conversations =
- mNotificationManager.getConversations(
- true /* priority only */).getList();
- mConversations = conversations.stream().filter(
- c -> shouldKeepConversation(c)).collect(Collectors.toList());
- for (ConversationChannelWrapper conversation : mConversations) {
+ List<ShortcutInfo> shortcutInfos =
+ PeopleSpaceUtils.getShortcutInfos(
+ mContext, mNotificationManager, mPeopleManager);
+ for (ShortcutInfo conversation : shortcutInfos) {
PeopleSpaceTileView tileView = new PeopleSpaceTileView(mContext,
mPeopleSpaceLayout,
- conversation.getShortcutInfo().getId());
+ conversation.getId());
setTileView(tileView, conversation);
}
} catch (Exception e) {
@@ -95,11 +85,10 @@ public class PeopleSpaceActivity extends Activity {
/** Sets {@code tileView} with the data in {@code conversation}. */
private void setTileView(PeopleSpaceTileView tileView,
- ConversationChannelWrapper conversation) {
+ ShortcutInfo shortcutInfo) {
try {
- ShortcutInfo shortcutInfo = conversation.getShortcutInfo();
int userId = UserHandle.getUserHandleForUid(
- conversation.getUid()).getIdentifier();
+ shortcutInfo.getUserId()).getIdentifier();
String pkg = shortcutInfo.getPackage();
long lastInteraction = mPeopleManager.getLastInteraction(
@@ -107,7 +96,7 @@ public class PeopleSpaceActivity extends Activity {
shortcutInfo.getId());
String status = lastInteraction != 0l ? mContext.getString(
R.string.last_interaction_status,
- getLastInteractionString(
+ PeopleSpaceUtils.getLastInteractionString(
lastInteraction)) : mContext.getString(R.string.basic_status);
tileView.setStatus(status);
@@ -120,46 +109,6 @@ public class PeopleSpaceActivity extends Activity {
}
}
- /** Returns a readable representation of {@code lastInteraction}. */
- private String getLastInteractionString(long lastInteraction) {
- long now = System.currentTimeMillis();
- Duration durationSinceLastInteraction = Duration.ofMillis(
- now - lastInteraction);
- MeasureFormat formatter = MeasureFormat.getInstance(Locale.getDefault(),
- MeasureFormat.FormatWidth.WIDE);
- if (durationSinceLastInteraction.toDays() >= 1) {
- return
- formatter
- .formatMeasures(new Measure(durationSinceLastInteraction.toDays(),
- MeasureUnit.DAY));
- } else if (durationSinceLastInteraction.toHours() >= 1) {
- return formatter.formatMeasures(new Measure(durationSinceLastInteraction.toHours(),
- MeasureUnit.HOUR));
- } else if (durationSinceLastInteraction.toMinutes() >= 1) {
- return formatter.formatMeasures(new Measure(durationSinceLastInteraction.toMinutes(),
- MeasureUnit.MINUTE));
- } else {
- return formatter.formatMeasures(
- new Measure(durationSinceLastInteraction.toMillis() / 1000,
- MeasureUnit.SECOND));
- }
- }
-
- /**
- * Returns whether the {@code conversation} should be kept for display in the People Space.
- *
- * <p>A valid {@code conversation} must:
- * <ul>
- * <li>Have a non-null {@link ShortcutInfo}
- * <li>Have an associated label in the {@link ShortcutInfo}
- * </ul>
- * </li>
- */
- private boolean shouldKeepConversation(ConversationChannelWrapper conversation) {
- ShortcutInfo shortcutInfo = conversation.getShortcutInfo();
- return shortcutInfo != null && shortcutInfo.getLabel().length() != 0;
- }
-
@Override
protected void onResume() {
super.onResume();
diff --git a/packages/SystemUI/src/com/android/systemui/people/PeopleSpaceUtils.java b/packages/SystemUI/src/com/android/systemui/people/PeopleSpaceUtils.java
new file mode 100644
index 000000000000..9d46b321c52c
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/people/PeopleSpaceUtils.java
@@ -0,0 +1,128 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.people;
+
+import android.app.INotificationManager;
+import android.app.people.ConversationChannel;
+import android.app.people.IPeopleManager;
+import android.content.Context;
+import android.content.pm.ShortcutInfo;
+import android.graphics.Bitmap;
+import android.graphics.Canvas;
+import android.graphics.drawable.BitmapDrawable;
+import android.graphics.drawable.Drawable;
+import android.icu.text.MeasureFormat;
+import android.icu.util.Measure;
+import android.icu.util.MeasureUnit;
+import android.provider.Settings;
+import android.service.notification.ConversationChannelWrapper;
+
+import java.time.Duration;
+import java.util.List;
+import java.util.Locale;
+import java.util.stream.Collectors;
+
+/** Utils class for People Space. */
+public class PeopleSpaceUtils {
+ private static final String TAG = "PeopleSpaceUtils";
+
+ /** Turns on debugging information about People Space. */
+ public static final boolean DEBUG = true;
+
+ /** Returns a list of {@link ShortcutInfo} corresponding to user's conversations. */
+ public static List<ShortcutInfo> getShortcutInfos(
+ Context context,
+ INotificationManager notificationManager,
+ IPeopleManager peopleManager
+ ) throws Exception {
+ boolean showAllConversations = Settings.Global.getInt(context.getContentResolver(),
+ Settings.Global.PEOPLE_SPACE_CONVERSATION_TYPE) == 0;
+ List<ConversationChannelWrapper> conversations =
+ notificationManager.getConversations(
+ !showAllConversations /* priority only */).getList();
+ List<ShortcutInfo> shortcutInfos = conversations.stream().filter(
+ c -> shouldKeepConversation(c)).map(
+ c -> c.getShortcutInfo()).collect(Collectors.toList());
+ if (showAllConversations) {
+ List<ConversationChannel> recentConversations =
+ peopleManager.getRecentConversations().getList();
+ List<ShortcutInfo> recentShortcuts = recentConversations.stream().map(
+ c -> c.getShortcutInfo()).collect(Collectors.toList());
+ shortcutInfos.addAll(recentShortcuts);
+ }
+ return shortcutInfos;
+ }
+
+ /** Converts {@code drawable} to a {@link Bitmap}. */
+ public static Bitmap convertDrawableToBitmap(Drawable drawable) {
+ if (drawable instanceof BitmapDrawable) {
+ return ((BitmapDrawable) drawable).getBitmap();
+ }
+ // We use max below because the drawable might have no intrinsic width/height (e.g. if the
+ // drawable is a solid color).
+ Bitmap bitmap =
+ Bitmap.createBitmap(
+ Math.max(drawable.getIntrinsicWidth(), 1),
+ Math.max(drawable.getIntrinsicHeight(), 1),
+ Bitmap.Config.ARGB_8888);
+ Canvas canvas = new Canvas(bitmap);
+ drawable.setBounds(0, 0, canvas.getWidth(), canvas.getHeight());
+ drawable.draw(canvas);
+ return bitmap;
+ }
+
+ /** Returns a readable representation of {@code lastInteraction}. */
+ public static String getLastInteractionString(long lastInteraction) {
+ long now = System.currentTimeMillis();
+ Duration durationSinceLastInteraction = Duration.ofMillis(
+ now - lastInteraction);
+ MeasureFormat formatter = MeasureFormat.getInstance(Locale.getDefault(),
+ MeasureFormat.FormatWidth.WIDE);
+ if (durationSinceLastInteraction.toDays() >= 1) {
+ return
+ formatter
+ .formatMeasures(new Measure(durationSinceLastInteraction.toDays(),
+ MeasureUnit.DAY));
+ } else if (durationSinceLastInteraction.toHours() >= 1) {
+ return formatter.formatMeasures(new Measure(durationSinceLastInteraction.toHours(),
+ MeasureUnit.HOUR));
+ } else if (durationSinceLastInteraction.toMinutes() >= 1) {
+ return formatter.formatMeasures(new Measure(durationSinceLastInteraction.toMinutes(),
+ MeasureUnit.MINUTE));
+ } else {
+ return formatter.formatMeasures(
+ new Measure(durationSinceLastInteraction.toMillis() / 1000,
+ MeasureUnit.SECOND));
+ }
+ }
+
+ /**
+ * Returns whether the {@code conversation} should be kept for display in the People Space.
+ *
+ * <p>A valid {@code conversation} must:
+ * <ul>
+ * <li>Have a non-null {@link ShortcutInfo}
+ * <li>Have an associated label in the {@link ShortcutInfo}
+ * </ul>
+ * </li>
+ */
+ public static boolean shouldKeepConversation(ConversationChannelWrapper conversation) {
+ ShortcutInfo shortcutInfo = conversation.getShortcutInfo();
+ return shortcutInfo != null && shortcutInfo.getLabel().length() != 0;
+ }
+
+}
diff --git a/packages/SystemUI/src/com/android/systemui/people/widget/PeopleSpaceWidgetProvider.java b/packages/SystemUI/src/com/android/systemui/people/widget/PeopleSpaceWidgetProvider.java
new file mode 100644
index 000000000000..85801f9e7206
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/people/widget/PeopleSpaceWidgetProvider.java
@@ -0,0 +1,53 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.people.widget;
+
+import android.appwidget.AppWidgetManager;
+import android.appwidget.AppWidgetProvider;
+import android.content.Context;
+import android.content.Intent;
+import android.util.Log;
+import android.widget.RemoteViews;
+
+import com.android.systemui.R;
+import com.android.systemui.people.PeopleSpaceUtils;
+
+/** People Space Widget Provider class. */
+public class PeopleSpaceWidgetProvider extends AppWidgetProvider {
+ private static final String TAG = "PeopleSpaceWidgetPvd";
+ private static final boolean DEBUG = PeopleSpaceUtils.DEBUG;
+
+ /** Called when widget updates. */
+ public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) {
+ super.onUpdate(context, appWidgetManager, appWidgetIds);
+
+ if (DEBUG) Log.d(TAG, "onUpdate called");
+ // Perform this loop procedure for each App Widget that belongs to this provider
+ for (int appWidgetId : appWidgetIds) {
+ RemoteViews views =
+ new RemoteViews(context.getPackageName(), R.layout.people_space_widget);
+
+ Intent intent = new Intent(context, PeopleSpaceWidgetService.class);
+ intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, appWidgetId);
+ views.setRemoteAdapter(R.id.widget_list_view, intent);
+
+ // Tell the AppWidgetManager to perform an update on the current app widget
+ appWidgetManager.notifyAppWidgetViewDataChanged(appWidgetId, R.id.widget_list_view);
+ appWidgetManager.updateAppWidget(appWidgetId, views);
+ }
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/people/widget/PeopleSpaceWidgetRemoteViewsFactory.java b/packages/SystemUI/src/com/android/systemui/people/widget/PeopleSpaceWidgetRemoteViewsFactory.java
new file mode 100644
index 000000000000..093925a2664a
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/people/widget/PeopleSpaceWidgetRemoteViewsFactory.java
@@ -0,0 +1,158 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.people.widget;
+
+import android.app.INotificationManager;
+import android.app.people.IPeopleManager;
+import android.content.Context;
+import android.content.Intent;
+import android.content.pm.LauncherApps;
+import android.content.pm.PackageManager;
+import android.content.pm.ShortcutInfo;
+import android.os.ServiceManager;
+import android.os.UserHandle;
+import android.util.Log;
+import android.widget.RemoteViews;
+import android.widget.RemoteViewsService;
+
+import com.android.systemui.R;
+import com.android.systemui.people.PeopleSpaceTileView;
+import com.android.systemui.people.PeopleSpaceUtils;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/** People Space Widget RemoteViewsFactory class. */
+public class PeopleSpaceWidgetRemoteViewsFactory implements RemoteViewsService.RemoteViewsFactory {
+ private static final String TAG = "PeopleSpaceWRVFactory";
+ private static final boolean DEBUG = PeopleSpaceUtils.DEBUG;
+
+ private IPeopleManager mPeopleManager;
+ private INotificationManager mNotificationManager;
+ private PackageManager mPackageManager;
+ private LauncherApps mLauncherApps;
+ private List<ShortcutInfo> mShortcutInfos = new ArrayList<>();
+ private Context mContext;
+
+ public PeopleSpaceWidgetRemoteViewsFactory(Context context, Intent intent) {
+ this.mContext = context;
+ }
+
+ @Override
+ public void onCreate() {
+ if (DEBUG) Log.d(TAG, "onCreate called");
+ mNotificationManager =
+ INotificationManager.Stub.asInterface(
+ ServiceManager.getService(Context.NOTIFICATION_SERVICE));
+ mPackageManager = mContext.getPackageManager();
+ mPeopleManager = IPeopleManager.Stub.asInterface(
+ ServiceManager.getService(Context.PEOPLE_SERVICE));
+ mLauncherApps = mContext.getSystemService(LauncherApps.class);
+ setTileViewsWithPriorityConversations();
+ }
+
+ /**
+ * Retrieves all priority conversations and sets a {@link PeopleSpaceTileView}s for each
+ * priority conversation.
+ */
+ private void setTileViewsWithPriorityConversations() {
+ try {
+ mShortcutInfos =
+ PeopleSpaceUtils.getShortcutInfos(
+ mContext, mNotificationManager, mPeopleManager);
+ } catch (Exception e) {
+ Log.e(TAG, "Couldn't retrieve conversations", e);
+ }
+ }
+
+ @Override
+ public void onDataSetChanged() {
+ if (DEBUG) Log.d(TAG, "onDataSetChanged called");
+ setTileViewsWithPriorityConversations();
+ }
+
+ @Override
+ public void onDestroy() {
+ mShortcutInfos.clear();
+ }
+
+ @Override
+ public int getCount() {
+ return mShortcutInfos.size();
+ }
+
+ @Override
+ public RemoteViews getViewAt(int i) {
+ if (DEBUG) Log.d(TAG, "getViewAt called, index: " + i);
+
+ RemoteViews personView =
+ new RemoteViews(mContext.getPackageName(), R.layout.people_space_widget_item);
+ try {
+ ShortcutInfo shortcutInfo = mShortcutInfos.get(i);
+ int userId = UserHandle.getUserHandleForUid(
+ shortcutInfo.getUserId()).getIdentifier();
+ String pkg = shortcutInfo.getPackage();
+ long lastInteraction = mPeopleManager.getLastInteraction(
+ pkg, userId,
+ shortcutInfo.getId());
+
+ String status = lastInteraction != 0L ? mContext.getString(
+ R.string.last_interaction_status,
+ PeopleSpaceUtils.getLastInteractionString(
+ lastInteraction)) : mContext.getString(R.string.basic_status);
+
+ personView.setTextViewText(R.id.status, status);
+ personView.setTextViewText(R.id.name, shortcutInfo.getLabel().toString());
+
+ personView.setImageViewBitmap(
+ R.id.package_icon,
+ PeopleSpaceUtils.convertDrawableToBitmap(
+ mPackageManager.getApplicationIcon(pkg)
+ )
+ );
+ personView.setImageViewBitmap(
+ R.id.person_icon,
+ PeopleSpaceUtils.convertDrawableToBitmap(
+ mLauncherApps.getShortcutIconDrawable(shortcutInfo, 0)
+ )
+ );
+ } catch (Exception e) {
+ Log.e(TAG, "Couldn't retrieve shortcut information", e);
+ }
+ return personView;
+ }
+
+ @Override
+ public RemoteViews getLoadingView() {
+ return null;
+ }
+
+ @Override
+ public int getViewTypeCount() {
+ return 1;
+ }
+
+ @Override
+ public long getItemId(int i) {
+ return i;
+ }
+
+ @Override
+ public boolean hasStableIds() {
+ return true;
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/people/widget/PeopleSpaceWidgetService.java b/packages/SystemUI/src/com/android/systemui/people/widget/PeopleSpaceWidgetService.java
new file mode 100644
index 000000000000..c0e43473d069
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/people/widget/PeopleSpaceWidgetService.java
@@ -0,0 +1,34 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.people.widget;
+import android.content.Intent;
+import android.util.Log;
+import android.widget.RemoteViewsService;
+
+import com.android.systemui.people.PeopleSpaceUtils;
+
+/** People Space Widget Service class. */
+public class PeopleSpaceWidgetService extends RemoteViewsService {
+ private static final String TAG = "PeopleSpaceWidgetSvc";
+ private static final boolean DEBUG = PeopleSpaceUtils.DEBUG;
+
+ @Override
+ public RemoteViewsFactory onGetViewFactory(Intent intent) {
+ if (DEBUG) Log.d(TAG, "onGetViewFactory called");
+ return new PeopleSpaceWidgetRemoteViewsFactory(this.getApplicationContext(), intent);
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/privacy/PrivacyItemController.kt b/packages/SystemUI/src/com/android/systemui/privacy/PrivacyItemController.kt
index f56e6cdf5cb7..dc5ba693a658 100644
--- a/packages/SystemUI/src/com/android/systemui/privacy/PrivacyItemController.kt
+++ b/packages/SystemUI/src/com/android/systemui/privacy/PrivacyItemController.kt
@@ -69,8 +69,10 @@ class PrivacyItemController @Inject constructor(
private const val ALL_INDICATORS =
SystemUiDeviceConfigFlags.PROPERTY_PERMISSIONS_HUB_ENABLED
private const val MIC_CAMERA = SystemUiDeviceConfigFlags.PROPERTY_MIC_CAMERA_ENABLED
+ private const val LOCATION = SystemUiDeviceConfigFlags.PROPERTY_LOCATION_INDICATORS_ENABLED
private const val DEFAULT_ALL_INDICATORS = false
private const val DEFAULT_MIC_CAMERA = true
+ private const val DEFAULT_LOCATION = false
}
@VisibleForTesting
@@ -88,6 +90,11 @@ class PrivacyItemController @Inject constructor(
return true
}
+ private fun isLocationEnabled(): Boolean {
+ return deviceConfigProxy.getBoolean(DeviceConfig.NAMESPACE_PRIVACY,
+ LOCATION, DEFAULT_LOCATION)
+ }
+
private var currentUserIds = emptyList<Int>()
private var listening = false
private val callbacks = mutableListOf<WeakReference<Callback>>()
@@ -107,13 +114,15 @@ class PrivacyItemController @Inject constructor(
private set
var micCameraAvailable = isMicCameraEnabled()
private set
+ var locationAvailable = isLocationEnabled()
private val devicePropertiesChangedListener =
object : DeviceConfig.OnPropertiesChangedListener {
override fun onPropertiesChanged(properties: DeviceConfig.Properties) {
if (DeviceConfig.NAMESPACE_PRIVACY.equals(properties.getNamespace()) &&
(properties.keyset.contains(ALL_INDICATORS) ||
- properties.keyset.contains(MIC_CAMERA))) {
+ properties.keyset.contains(MIC_CAMERA) ||
+ properties.keyset.contains(LOCATION))) {
// Running on the ui executor so can iterate on callbacks
if (properties.keyset.contains(ALL_INDICATORS)) {
@@ -126,6 +135,10 @@ class PrivacyItemController @Inject constructor(
// micCameraAvailable = properties.getBoolean(MIC_CAMERA, DEFAULT_MIC_CAMERA)
// callbacks.forEach { it.get()?.onFlagMicCameraChanged(micCameraAvailable) }
// }
+ if (properties.keyset.contains(LOCATION)) {
+ locationAvailable = properties.getBoolean(LOCATION, DEFAULT_LOCATION)
+ callbacks.forEach { it.get()?.onFlagLocationChanged(locationAvailable) }
+ }
internalUiExecutor.updateListeningState()
}
}
@@ -139,7 +152,8 @@ class PrivacyItemController @Inject constructor(
active: Boolean
) {
// Check if we care about this code right now
- if (!allIndicatorsAvailable && code in OPS_LOCATION) {
+ if (!allIndicatorsAvailable &&
+ (code in OPS_LOCATION && !locationAvailable)) {
return
}
val userId = UserHandle.getUserId(uid)
@@ -195,7 +209,8 @@ class PrivacyItemController @Inject constructor(
* main thread.
*/
private fun setListeningState() {
- val listen = !callbacks.isEmpty() and (allIndicatorsAvailable || micCameraAvailable)
+ val listen = !callbacks.isEmpty() and
+ (allIndicatorsAvailable || micCameraAvailable || locationAvailable)
if (listening == listen) return
listening = listen
if (listening) {
@@ -258,7 +273,9 @@ class PrivacyItemController @Inject constructor(
AppOpsManager.OP_RECORD_AUDIO -> PrivacyType.TYPE_MICROPHONE
else -> return null
}
- if (type == PrivacyType.TYPE_LOCATION && !allIndicatorsAvailable) return null
+ if (type == PrivacyType.TYPE_LOCATION && (!allIndicatorsAvailable && !locationAvailable)) {
+ return null
+ }
val app = PrivacyApplication(appOpItem.packageName, appOpItem.uid)
return PrivacyItem(type, app)
}
@@ -271,6 +288,9 @@ class PrivacyItemController @Inject constructor(
@JvmDefault
fun onFlagMicCameraChanged(flag: Boolean) {}
+
+ @JvmDefault
+ fun onFlagLocationChanged(flag: Boolean) {}
}
private class NotifyChangesToCallback(
diff --git a/packages/SystemUI/src/com/android/systemui/qs/DoubleLineTileLayout.kt b/packages/SystemUI/src/com/android/systemui/qs/DoubleLineTileLayout.kt
index dc157a8dd257..81076475c5ce 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/DoubleLineTileLayout.kt
+++ b/packages/SystemUI/src/com/android/systemui/qs/DoubleLineTileLayout.kt
@@ -33,7 +33,7 @@ class DoubleLineTileLayout(
private const val NUM_LINES = 2
}
- protected val mRecords = ArrayList<QSPanel.TileRecord>()
+ protected val mRecords = ArrayList<QSPanelControllerBase.TileRecord>()
private var _listening = false
private var smallTileSize = 0
private val twoLineHeight
@@ -50,17 +50,17 @@ class DoubleLineTileLayout(
updateResources()
}
- override fun addTile(tile: QSPanel.TileRecord) {
+ override fun addTile(tile: QSPanelControllerBase.TileRecord) {
mRecords.add(tile)
tile.tile.setListening(this, _listening)
addTileView(tile)
}
- protected fun addTileView(tile: QSPanel.TileRecord) {
+ protected fun addTileView(tile: QSPanelControllerBase.TileRecord) {
addView(tile.tileView)
}
- override fun removeTile(tile: QSPanel.TileRecord) {
+ override fun removeTile(tile: QSPanelControllerBase.TileRecord) {
mRecords.remove(tile)
tile.tile.setListening(this, false)
removeView(tile.tileView)
@@ -72,7 +72,7 @@ class DoubleLineTileLayout(
super.removeAllViews()
}
- override fun getOffsetTop(tile: QSPanel.TileRecord?) = top
+ override fun getOffsetTop(tile: QSPanelControllerBase.TileRecord?) = top
override fun updateResources(): Boolean {
with(mContext.resources) {
diff --git a/packages/SystemUI/src/com/android/systemui/qs/PagedTileLayout.java b/packages/SystemUI/src/com/android/systemui/qs/PagedTileLayout.java
index 04f379ef35ea..3062a77bcbe1 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/PagedTileLayout.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/PagedTileLayout.java
@@ -26,7 +26,7 @@ import com.android.internal.logging.UiEventLogger;
import com.android.systemui.R;
import com.android.systemui.plugins.qs.QSTile;
import com.android.systemui.qs.QSPanel.QSTileLayout;
-import com.android.systemui.qs.QSPanel.TileRecord;
+import com.android.systemui.qs.QSPanelControllerBase.TileRecord;
import java.util.ArrayList;
import java.util.Set;
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSAnimator.java b/packages/SystemUI/src/com/android/systemui/qs/QSAnimator.java
index 9dcc924f161e..4d4195063227 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSAnimator.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSAnimator.java
@@ -28,12 +28,17 @@ import com.android.systemui.qs.QSHost.Callback;
import com.android.systemui.qs.QSPanel.QSTileLayout;
import com.android.systemui.qs.TouchAnimator.Builder;
import com.android.systemui.qs.TouchAnimator.Listener;
+import com.android.systemui.qs.dagger.QSScope;
import com.android.systemui.tuner.TunerService;
import com.android.systemui.tuner.TunerService.Tunable;
import java.util.ArrayList;
import java.util.Collection;
+import javax.inject.Inject;
+
+/** */
+@QSScope
public class QSAnimator implements Callback, PageListener, Listener, OnLayoutChangeListener,
OnAttachStateChangeListener, Tunable {
@@ -53,6 +58,9 @@ public class QSAnimator implements Callback, PageListener, Listener, OnLayoutCha
private final ArrayList<View> mQuickQsViews = new ArrayList<>();
private final QuickQSPanel mQuickQsPanel;
private final QSPanel mQsPanel;
+ private final QSPanelController mQsPanelController;
+ private final QuickQSPanelController mQuickQSPanelController;
+ private final QSSecurityFooter mSecurityFooter;
private final QS mQs;
private PagedTileLayout mPagedLayout;
@@ -78,10 +86,19 @@ public class QSAnimator implements Callback, PageListener, Listener, OnLayoutCha
private QSTileHost mHost;
private boolean mShowCollapsedOnKeyguard;
- public QSAnimator(QS qs, QuickQSPanel quickPanel, QSPanel panel) {
+ @Inject
+ public QSAnimator(QS qs, QuickQSPanel quickPanel, QSPanel panel,
+ QSPanelController qsPanelController, QuickQSPanelController quickQSPanelController,
+ QSTileHost qsTileHost,
+ QSSecurityFooter securityFooter) {
mQs = qs;
mQuickQsPanel = quickPanel;
mQsPanel = panel;
+ mQsPanelController = qsPanelController;
+ mQuickQSPanelController = quickQSPanelController;
+ mSecurityFooter = securityFooter;
+ mHost = qsTileHost;
+ mHost.addCallback(this);
mQsPanel.addOnAttachStateChangeListener(this);
qs.getView().addOnLayoutChangeListener(this);
if (mQsPanel.isAttachedToWindow()) {
@@ -134,12 +151,6 @@ public class QSAnimator implements Callback, PageListener, Listener, OnLayoutCha
&& !mShowCollapsedOnKeyguard ? View.INVISIBLE : View.VISIBLE);
}
- public void setHost(QSTileHost qsh) {
- mHost = qsh;
- qsh.addCallback(this);
- updateAnimators();
- }
-
@Override
public void onViewAttachedToWindow(View v) {
Dependency.get(TunerService.class).addTunable(this, ALLOW_FANCY_ANIMATION,
@@ -148,9 +159,7 @@ public class QSAnimator implements Callback, PageListener, Listener, OnLayoutCha
@Override
public void onViewDetachedFromWindow(View v) {
- if (mHost != null) {
- mHost.removeCallback(this);
- }
+ mHost.removeCallback(this);
Dependency.get(TunerService.class).removeTunable(this);
}
@@ -185,8 +194,7 @@ public class QSAnimator implements Callback, PageListener, Listener, OnLayoutCha
TouchAnimator.Builder translationXBuilder = new Builder();
TouchAnimator.Builder translationYBuilder = new Builder();
- if (mQsPanel.getHost() == null) return;
- Collection<QSTile> tiles = mQsPanel.getHost().getTiles();
+ Collection<QSTile> tiles = mHost.getTiles();
int count = 0;
int[] loc1 = new int[2];
int[] loc2 = new int[2];
@@ -206,7 +214,7 @@ public class QSAnimator implements Callback, PageListener, Listener, OnLayoutCha
firstPageBuilder.addFloat(tileLayout, "translationY", heightDiff, 0);
for (QSTile tile : tiles) {
- QSTileView tileView = mQsPanel.getTileView(tile);
+ QSTileView tileView = mQsPanelController.getTileView(tile);
if (tileView == null) {
Log.e(TAG, "tileView is null " + tile.getTileSpec());
continue;
@@ -217,7 +225,7 @@ public class QSAnimator implements Callback, PageListener, Listener, OnLayoutCha
// This case: less tiles to animate in small displays.
if (count < mQuickQsPanel.getTileLayout().getNumVisibleTiles() && mAllowFancy) {
// Quick tiles.
- QSTileView quickTileView = mQuickQsPanel.getTileView(tile);
+ QSTileView quickTileView = mQuickQSPanelController.getTileView(tile);
if (quickTileView == null) continue;
lastX = loc1[0];
@@ -302,16 +310,12 @@ public class QSAnimator implements Callback, PageListener, Listener, OnLayoutCha
// Fade in the security footer and the divider as we reach the final position
builder = new Builder().setStartDelay(EXPANDED_TILE_DELAY);
- if (mQsPanel.getSecurityFooter() != null) {
- builder.addFloat(mQsPanel.getSecurityFooter().getView(), "alpha", 0, 1);
- }
+ builder.addFloat(mSecurityFooter.getView(), "alpha", 0, 1);
if (mQsPanel.getDivider() != null) {
builder.addFloat(mQsPanel.getDivider(), "alpha", 0, 1);
}
mAllPagesDelayedAnimator = builder.build();
- if (mQsPanel.getSecurityFooter() != null) {
- mAllViews.add(mQsPanel.getSecurityFooter().getView());
- }
+ mAllViews.add(mSecurityFooter.getView());
if (mQsPanel.getDivider() != null) {
mAllViews.add(mQsPanel.getDivider());
}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSContainerImplController.java b/packages/SystemUI/src/com/android/systemui/qs/QSContainerImplController.java
index 1e239b1e9ec9..acead987a06a 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSContainerImplController.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSContainerImplController.java
@@ -16,19 +16,21 @@
package com.android.systemui.qs;
-import com.android.systemui.R;
+import com.android.systemui.qs.dagger.QSScope;
import com.android.systemui.util.ViewController;
import javax.inject.Inject;
-class QSContainerImplController extends ViewController<QSContainerImpl> {
+/** */
+@QSScope
+public class QSContainerImplController extends ViewController<QSContainerImpl> {
private final QuickStatusBarHeaderController mQuickStatusBarHeaderController;
- private QSContainerImplController(QSContainerImpl view,
- QuickStatusBarHeaderController.Builder quickStatusBarHeaderControllerBuilder) {
+ @Inject
+ QSContainerImplController(QSContainerImpl view,
+ QuickStatusBarHeaderController quickStatusBarHeaderController) {
super(view);
- mQuickStatusBarHeaderController = quickStatusBarHeaderControllerBuilder
- .setQuickStatusBarHeader(mView.findViewById(R.id.header)).build();
+ mQuickStatusBarHeaderController = quickStatusBarHeaderController;
}
@Override
@@ -49,23 +51,7 @@ class QSContainerImplController extends ViewController<QSContainerImpl> {
protected void onViewDetached() {
}
- static class Builder {
- private final QuickStatusBarHeaderController.Builder mQuickStatusBarHeaderControllerBuilder;
- private QSContainerImpl mView;
-
- @Inject
- Builder(
- QuickStatusBarHeaderController.Builder quickStatusBarHeaderControllerBuilder) {
- mQuickStatusBarHeaderControllerBuilder = quickStatusBarHeaderControllerBuilder;
- }
-
- public Builder setQSContainerImpl(QSContainerImpl view) {
- mView = view;
- return this;
- }
-
- public QSContainerImplController build() {
- return new QSContainerImplController(mView, mQuickStatusBarHeaderControllerBuilder);
- }
+ public QSContainerImpl getView() {
+ return mView;
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSDetail.java b/packages/SystemUI/src/com/android/systemui/qs/QSDetail.java
index 2be8a9704e1c..cfcceb2b2951 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSDetail.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSDetail.java
@@ -76,7 +76,7 @@ public class QSDetail extends LinearLayout {
private int mOpenY;
private boolean mAnimatingOpen;
private boolean mSwitchState;
- private View mFooter;
+ private QSFooter mFooter;
public QSDetail(Context context, @Nullable AttributeSet attrs) {
super(context, attrs);
@@ -120,7 +120,8 @@ public class QSDetail extends LinearLayout {
mDetailDoneButton.setOnClickListener(doneListener);
}
- public void setQsPanel(QSPanel panel, QuickStatusBarHeader header, View footer) {
+ /** */
+ public void setQsPanel(QSPanel panel, QuickStatusBarHeader header, QSFooter footer) {
mQsPanel = panel;
mHeader = header;
mFooter = footer;
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSFooterImpl.java b/packages/SystemUI/src/com/android/systemui/qs/QSFooterView.java
index 84563a078447..8b9dae14c809 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSFooterImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSFooterView.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2017 The Android Open Source Project
+ * 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.
@@ -11,19 +11,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.
*/
package com.android.systemui.qs;
import static android.app.StatusBarManager.DISABLE2_QUICK_SETTINGS;
-import static com.android.systemui.util.InjectionInflationController.VIEW_CONTEXT;
-
-import android.content.ClipData;
-import android.content.ClipboardManager;
import android.content.Context;
-import android.content.Intent;
import android.content.res.Configuration;
import android.database.ContentObserver;
import android.graphics.PorterDuff.Mode;
@@ -36,50 +31,27 @@ import android.os.Handler;
import android.os.UserHandle;
import android.os.UserManager;
import android.provider.Settings;
-import android.text.TextUtils;
import android.util.AttributeSet;
import android.view.View;
-import android.view.View.OnClickListener;
import android.view.accessibility.AccessibilityNodeInfo;
import android.widget.FrameLayout;
import android.widget.ImageView;
import android.widget.TextView;
-import android.widget.Toast;
import androidx.annotation.Nullable;
import androidx.annotation.VisibleForTesting;
-import com.android.internal.logging.MetricsLogger;
-import com.android.internal.logging.nano.MetricsProto;
-import com.android.keyguard.KeyguardUpdateMonitor;
import com.android.settingslib.Utils;
import com.android.settingslib.development.DevelopmentSettingsEnabler;
import com.android.settingslib.drawable.UserIconDrawable;
-import com.android.systemui.Dependency;
import com.android.systemui.R;
import com.android.systemui.R.dimen;
-import com.android.systemui.plugins.ActivityStarter;
import com.android.systemui.qs.TouchAnimator.Builder;
-import com.android.systemui.settings.UserTracker;
import com.android.systemui.statusbar.phone.MultiUserSwitch;
import com.android.systemui.statusbar.phone.SettingsButton;
-import com.android.systemui.statusbar.policy.DeviceProvisionedController;
-import com.android.systemui.statusbar.policy.UserInfoController;
-import com.android.systemui.statusbar.policy.UserInfoController.OnUserInfoChangedListener;
-import com.android.systemui.tuner.TunerService;
-
-import javax.inject.Inject;
-import javax.inject.Named;
-
-public class QSFooterImpl extends FrameLayout implements QSFooter,
- OnClickListener, OnUserInfoChangedListener {
- private static final String TAG = "QSFooterImpl";
-
- private final ActivityStarter mActivityStarter;
- private final UserInfoController mUserInfoController;
- private final DeviceProvisionedController mDeviceProvisionedController;
- private final UserTracker mUserTracker;
+/** */
+public class QSFooterView extends FrameLayout {
private SettingsButton mSettingsButton;
protected View mSettingsContainer;
private PageIndicator mPageIndicator;
@@ -87,7 +59,6 @@ public class QSFooterImpl extends FrameLayout implements QSFooter,
private boolean mShouldShowBuildText;
private boolean mQsDisabled;
- private QSPanel mQsPanel;
private QuickQSPanel mQuickQsPanel;
private boolean mExpanded;
@@ -117,39 +88,19 @@ public class QSFooterImpl extends FrameLayout implements QSFooter,
}
};
- @Inject
- public QSFooterImpl(@Named(VIEW_CONTEXT) Context context, AttributeSet attrs,
- ActivityStarter activityStarter, UserInfoController userInfoController,
- DeviceProvisionedController deviceProvisionedController, UserTracker userTracker) {
+ public QSFooterView(Context context, AttributeSet attrs) {
super(context, attrs);
- mActivityStarter = activityStarter;
- mUserInfoController = userInfoController;
- mDeviceProvisionedController = deviceProvisionedController;
- mUserTracker = userTracker;
- }
-
- @VisibleForTesting
- public QSFooterImpl(Context context, AttributeSet attrs) {
- this(context, attrs,
- Dependency.get(ActivityStarter.class),
- Dependency.get(UserInfoController.class),
- Dependency.get(DeviceProvisionedController.class),
- Dependency.get(UserTracker.class));
}
@Override
protected void onFinishInflate() {
super.onFinishInflate();
mEdit = findViewById(android.R.id.edit);
- mEdit.setOnClickListener(view ->
- mActivityStarter.postQSRunnableDismissingKeyguard(() ->
- mQsPanel.showEdit(view)));
mPageIndicator = findViewById(R.id.footer_page_indicator);
mSettingsButton = findViewById(R.id.settings_button);
mSettingsContainer = findViewById(R.id.settings_button_container);
- mSettingsButton.setOnClickListener(this);
mMultiUserSwitch = findViewById(R.id.multi_user_switch);
mMultiUserAvatar = mMultiUserSwitch.findViewById(R.id.multi_user_avatar);
@@ -157,19 +108,6 @@ public class QSFooterImpl extends FrameLayout implements QSFooter,
mActionsContainer = findViewById(R.id.qs_footer_actions_container);
mEditContainer = findViewById(R.id.qs_footer_actions_edit_container);
mBuildText = findViewById(R.id.build);
- mBuildText.setOnLongClickListener(view -> {
- CharSequence buildText = mBuildText.getText();
- if (!TextUtils.isEmpty(buildText)) {
- ClipboardManager service =
- mUserTracker.getUserContext().getSystemService(ClipboardManager.class);
- String label = mContext.getString(R.string.build_number_clip_data_label);
- service.setPrimaryClip(ClipData.newPlainText(label, buildText));
- Toast.makeText(mContext, R.string.build_number_copy_toast, Toast.LENGTH_SHORT)
- .show();
- return true;
- }
- return false;
- });
// RenderThread is doing more harm than good when touching the header (to expand quick
// settings), so disable it for this view
@@ -180,7 +118,6 @@ public class QSFooterImpl extends FrameLayout implements QSFooter,
addOnLayoutChangeListener((v, left, top, right, bottom, oldLeft, oldTop, oldRight,
oldBottom) -> updateAnimator(right - left));
setImportantForAccessibility(IMPORTANT_FOR_ACCESSIBILITY_YES);
- updateEverything();
setBuildText();
}
@@ -249,24 +186,22 @@ public class QSFooterImpl extends FrameLayout implements QSFooter,
.build();
}
- @Override
- public void setKeyguardShowing(boolean keyguardShowing) {
+ /** */
+ public void setKeyguardShowing() {
setExpansion(mExpansionAmount);
}
- @Override
public void setExpandClickListener(OnClickListener onClickListener) {
mExpandClickListener = onClickListener;
}
- @Override
- public void setExpanded(boolean expanded) {
+ void setExpanded(boolean expanded, boolean isTunerEnabled) {
if (mExpanded == expanded) return;
mExpanded = expanded;
- updateEverything();
+ updateEverything(isTunerEnabled);
}
- @Override
+ /** */
public void setExpansion(float headerExpansionFraction) {
mExpansionAmount = headerExpansionFraction;
if (mSettingsCogAnimator != null) mSettingsCogAnimator.setPosition(headerExpansionFraction);
@@ -287,18 +222,16 @@ public class QSFooterImpl extends FrameLayout implements QSFooter,
@Override
@VisibleForTesting
public void onDetachedFromWindow() {
- setListening(false);
mContext.getContentResolver().unregisterContentObserver(mDeveloperSettingsObserver);
super.onDetachedFromWindow();
}
- @Override
+ /** */
public void setListening(boolean listening) {
if (listening == mListening) {
return;
}
mListening = listening;
- updateListeners();
}
@Override
@@ -318,17 +251,16 @@ public class QSFooterImpl extends FrameLayout implements QSFooter,
info.addAction(AccessibilityNodeInfo.AccessibilityAction.ACTION_EXPAND);
}
- @Override
- public void disable(int state1, int state2, boolean animate) {
+ void disable(int state2, boolean isTunerEnabled) {
final boolean disabled = (state2 & DISABLE2_QUICK_SETTINGS) != 0;
if (disabled == mQsDisabled) return;
mQsDisabled = disabled;
- updateEverything();
+ updateEverything(isTunerEnabled);
}
- public void updateEverything() {
+ void updateEverything(boolean isTunerEnabled) {
post(() -> {
- updateVisibilities();
+ updateVisibilities(isTunerEnabled);
updateClickabilities();
setClickable(false);
});
@@ -341,11 +273,10 @@ public class QSFooterImpl extends FrameLayout implements QSFooter,
mBuildText.setLongClickable(mBuildText.getVisibility() == View.VISIBLE);
}
- private void updateVisibilities() {
+ private void updateVisibilities(boolean isTunerEnabled) {
mSettingsContainer.setVisibility(mQsDisabled ? View.GONE : View.VISIBLE);
mSettingsContainer.findViewById(R.id.tuner_icon).setVisibility(
- TunerService.isTunerEnabled(mContext, mUserTracker.getUserHandle()) ? View.VISIBLE
- : View.INVISIBLE);
+ isTunerEnabled ? View.VISIBLE : View.INVISIBLE);
final boolean isDemo = UserManager.isDeviceInDemoMode(mContext);
mMultiUserSwitch.setVisibility(showUserSwitcher() ? View.VISIBLE : View.INVISIBLE);
mEditContainer.setVisibility(isDemo || !mExpanded ? View.INVISIBLE : View.VISIBLE);
@@ -358,78 +289,22 @@ public class QSFooterImpl extends FrameLayout implements QSFooter,
return mExpanded && mMultiUserSwitch.isMultiUserEnabled();
}
- private void updateListeners() {
- if (mListening) {
- mUserInfoController.addCallback(this);
- } else {
- mUserInfoController.removeCallback(this);
- }
- }
-
- @Override
+ /** */
public void setQSPanel(final QSPanel qsPanel) {
- mQsPanel = qsPanel;
- if (mQsPanel != null) {
+ if (qsPanel != null) {
mMultiUserSwitch.setQsPanel(qsPanel);
- mQsPanel.setFooterPageIndicator(mPageIndicator);
+ qsPanel.setFooterPageIndicator(mPageIndicator);
}
}
- @Override
public void setQQSPanel(@Nullable QuickQSPanel panel) {
mQuickQsPanel = panel;
}
- @Override
- public void onClick(View v) {
- // Don't do anything until view are unhidden
- if (!mExpanded) {
- return;
- }
-
- if (v == mSettingsButton) {
- if (!mDeviceProvisionedController.isCurrentUserSetup()) {
- // If user isn't setup just unlock the device and dump them back at SUW.
- mActivityStarter.postQSRunnableDismissingKeyguard(() -> {
- });
- return;
- }
- MetricsLogger.action(mContext,
- mExpanded ? MetricsProto.MetricsEvent.ACTION_QS_EXPANDED_SETTINGS_LAUNCH
- : MetricsProto.MetricsEvent.ACTION_QS_COLLAPSED_SETTINGS_LAUNCH);
- if (mSettingsButton.isTunerClick()) {
- mActivityStarter.postQSRunnableDismissingKeyguard(() -> {
- if (TunerService.isTunerEnabled(mContext, mUserTracker.getUserHandle())) {
- TunerService.showResetRequest(mContext, mUserTracker.getUserHandle(),
- () -> {
- // Relaunch settings so that the tuner disappears.
- startSettingsActivity();
- });
- } else {
- Toast.makeText(getContext(), R.string.tuner_toast,
- Toast.LENGTH_LONG).show();
- TunerService.setTunerEnabled(mContext, mUserTracker.getUserHandle(), true);
- }
- startSettingsActivity();
-
- });
- } else {
- startSettingsActivity();
- }
- }
- }
-
- private void startSettingsActivity() {
- mActivityStarter.startActivity(new Intent(android.provider.Settings.ACTION_SETTINGS),
- true /* dismissShade */);
- }
- @Override
- public void onUserInfoChanged(String name, Drawable picture, String userAccount) {
- if (picture != null &&
- UserManager.get(mContext).isGuestUser(KeyguardUpdateMonitor.getCurrentUser()) &&
- !(picture instanceof UserIconDrawable)) {
- picture = picture.getConstantState().newDrawable(mContext.getResources()).mutate();
+ void onUserInfoChanged(Drawable picture, boolean isGuestUser) {
+ if (picture != null && isGuestUser && !(picture instanceof UserIconDrawable)) {
+ picture = picture.getConstantState().newDrawable(getResources()).mutate();
picture.setColorFilter(
Utils.getColorAttrDefaultColor(mContext, android.R.attr.colorForeground),
Mode.SRC_IN);
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSFooterViewController.java b/packages/SystemUI/src/com/android/systemui/qs/QSFooterViewController.java
new file mode 100644
index 000000000000..e3af04bdc31e
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSFooterViewController.java
@@ -0,0 +1,241 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.qs;
+
+import android.content.ClipData;
+import android.content.ClipboardManager;
+import android.content.Intent;
+import android.graphics.drawable.Drawable;
+import android.os.UserManager;
+import android.text.TextUtils;
+import android.view.View;
+import android.widget.TextView;
+import android.widget.Toast;
+
+import androidx.annotation.Nullable;
+
+import com.android.internal.logging.MetricsLogger;
+import com.android.internal.logging.nano.MetricsProto;
+import com.android.keyguard.KeyguardUpdateMonitor;
+import com.android.systemui.R;
+import com.android.systemui.plugins.ActivityStarter;
+import com.android.systemui.qs.dagger.QSScope;
+import com.android.systemui.settings.UserTracker;
+import com.android.systemui.statusbar.phone.SettingsButton;
+import com.android.systemui.statusbar.policy.DeviceProvisionedController;
+import com.android.systemui.statusbar.policy.UserInfoController;
+import com.android.systemui.tuner.TunerService;
+import com.android.systemui.util.ViewController;
+
+import javax.inject.Inject;
+
+/**
+ * Controller for {@link QSFooterView}.
+ */
+@QSScope
+public class QSFooterViewController extends ViewController<QSFooterView> implements QSFooter {
+
+ private final UserManager mUserManager;
+ private final UserInfoController mUserInfoController;
+ private final ActivityStarter mActivityStarter;
+ private final DeviceProvisionedController mDeviceProvisionedController;
+ private final UserTracker mUserTracker;
+ private final QSPanelController mQsPanelController;
+ private final TunerService mTunerService;
+ private final MetricsLogger mMetricsLogger;
+ private final SettingsButton mSettingsButton;
+ private final TextView mBuildText;
+ private final View mEdit;
+
+ private final UserInfoController.OnUserInfoChangedListener mOnUserInfoChangedListener =
+ new UserInfoController.OnUserInfoChangedListener() {
+ @Override
+ public void onUserInfoChanged(String name, Drawable picture, String userAccount) {
+ boolean isGuestUser = mUserManager.isGuestUser(KeyguardUpdateMonitor.getCurrentUser());
+ mView.onUserInfoChanged(picture, isGuestUser);
+ }
+ };
+
+ private final View.OnClickListener mSettingsOnClickListener = new View.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ // Don't do anything until view are unhidden
+ if (!mExpanded) {
+ return;
+ }
+
+ if (v == mSettingsButton) {
+ if (!mDeviceProvisionedController.isCurrentUserSetup()) {
+ // If user isn't setup just unlock the device and dump them back at SUW.
+ mActivityStarter.postQSRunnableDismissingKeyguard(() -> {
+ });
+ return;
+ }
+ mMetricsLogger.action(
+ mExpanded ? MetricsProto.MetricsEvent.ACTION_QS_EXPANDED_SETTINGS_LAUNCH
+ : MetricsProto.MetricsEvent.ACTION_QS_COLLAPSED_SETTINGS_LAUNCH);
+ if (mSettingsButton.isTunerClick()) {
+ mActivityStarter.postQSRunnableDismissingKeyguard(() -> {
+ if (isTunerEnabled()) {
+ mTunerService.showResetRequest(
+ mUserTracker.getUserHandle(),
+ () -> {
+ // Relaunch settings so that the tuner disappears.
+ startSettingsActivity();
+ });
+ } else {
+ Toast.makeText(getContext(), R.string.tuner_toast,
+ Toast.LENGTH_LONG).show();
+ mTunerService.setTunerEnabled(mUserTracker.getUserHandle(), true);
+ }
+ startSettingsActivity();
+
+ });
+ } else {
+ startSettingsActivity();
+ }
+ }
+ }
+ };
+
+ private boolean mListening;
+ private boolean mExpanded;
+
+ @Inject
+ QSFooterViewController(QSFooterView view, UserManager userManager,
+ UserInfoController userInfoController, ActivityStarter activityStarter,
+ DeviceProvisionedController deviceProvisionedController, UserTracker userTracker,
+ QSPanelController qsPanelController, TunerService tunerService,
+ MetricsLogger metricsLogger) {
+ super(view);
+ mUserManager = userManager;
+ mUserInfoController = userInfoController;
+ mActivityStarter = activityStarter;
+ mDeviceProvisionedController = deviceProvisionedController;
+ mUserTracker = userTracker;
+ mQsPanelController = qsPanelController;
+ mTunerService = tunerService;
+ mMetricsLogger = metricsLogger;
+
+ mSettingsButton = mView.findViewById(R.id.settings_button);
+ mBuildText = mView.findViewById(R.id.build);
+ mEdit = mView.findViewById(android.R.id.edit);
+ }
+
+
+ @Override
+ protected void onViewAttached() {
+ mSettingsButton.setOnClickListener(mSettingsOnClickListener);
+ mBuildText.setOnLongClickListener(view -> {
+ CharSequence buildText = mBuildText.getText();
+ if (!TextUtils.isEmpty(buildText)) {
+ ClipboardManager service =
+ mUserTracker.getUserContext().getSystemService(ClipboardManager.class);
+ String label = getResources().getString(R.string.build_number_clip_data_label);
+ service.setPrimaryClip(ClipData.newPlainText(label, buildText));
+ Toast.makeText(getContext(), R.string.build_number_copy_toast, Toast.LENGTH_SHORT)
+ .show();
+ return true;
+ }
+ return false;
+ });
+
+ mEdit.setOnClickListener(view ->
+ mActivityStarter.postQSRunnableDismissingKeyguard(() ->
+ mQsPanelController.showEdit(view)));
+
+ mView.updateEverything(isTunerEnabled());
+ }
+
+ @Override
+ protected void onViewDetached() {
+ setListening(false);
+ }
+
+
+ @Override
+ public void setQSPanel(@Nullable QSPanel panel) {
+ mView.setQSPanel(panel);
+ }
+
+ @Override
+ public void setVisibility(int visibility) {
+ mView.setVisibility(visibility);
+ }
+
+ @Override
+ public void setExpanded(boolean expanded) {
+ mExpanded = expanded;
+ mView.setExpanded(expanded, isTunerEnabled());
+ }
+
+
+ @Override
+ public int getHeight() {
+ return mView.getHeight();
+ }
+
+ @Override
+ public void setExpansion(float expansion) {
+ mView.setExpansion(expansion);
+ }
+
+ @Override
+ public void setListening(boolean listening) {
+ if (mListening == listening) {
+ return;
+ }
+
+ mListening = listening;
+ if (mListening) {
+ mUserInfoController.addCallback(mOnUserInfoChangedListener);
+ } else {
+ mUserInfoController.removeCallback(mOnUserInfoChangedListener);
+ }
+ }
+
+ @Override
+ public void setKeyguardShowing(boolean keyguardShowing) {
+ mView.setKeyguardShowing();
+ }
+
+ /** */
+ @Override
+ public void setExpandClickListener(View.OnClickListener onClickListener) {
+ mView.setExpandClickListener(onClickListener);
+ }
+
+ @Override
+ public void setQQSPanel(@Nullable QuickQSPanel panel) {
+ mView.setQQSPanel(panel);
+ }
+
+ @Override
+ public void disable(int state1, int state2, boolean animate) {
+ mView.disable(state2, isTunerEnabled());
+ }
+
+
+ private void startSettingsActivity() {
+ mActivityStarter.startActivity(new Intent(android.provider.Settings.ACTION_SETTINGS),
+ true /* dismissShade */);
+ }
+
+ private boolean isTunerEnabled() {
+ return mTunerService.isTunerEnabled(mUserTracker.getUserHandle());
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSFragment.java b/packages/SystemUI/src/com/android/systemui/qs/QSFragment.java
index 3a783653a2d8..1a7d366d84b4 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSFragment.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSFragment.java
@@ -35,11 +35,11 @@ import androidx.annotation.VisibleForTesting;
import com.android.systemui.Interpolators;
import com.android.systemui.R;
-import com.android.systemui.R.id;
import com.android.systemui.media.MediaHost;
import com.android.systemui.plugins.qs.QS;
import com.android.systemui.plugins.statusbar.StatusBarStateController;
import com.android.systemui.qs.customize.QSCustomizer;
+import com.android.systemui.qs.dagger.QSFragmentComponent;
import com.android.systemui.statusbar.CommandQueue;
import com.android.systemui.statusbar.StatusBarState;
import com.android.systemui.statusbar.notification.stack.StackStateAnimator;
@@ -70,7 +70,6 @@ public class QSFragment extends LifecycleFragment implements QS, CommandQueue.Ca
private HeightListener mPanelView;
protected QuickStatusBarHeader mHeader;
private QSCustomizer mQSCustomizer;
- protected QSPanel mQSPanel;
protected NonInterceptingScrollView mQSPanelScrollView;
private QSDetail mQSDetail;
private boolean mListening;
@@ -82,7 +81,7 @@ public class QSFragment extends LifecycleFragment implements QS, CommandQueue.Ca
private final RemoteInputQuickSettingsDisabler mRemoteInputQuickSettingsDisabler;
private final InjectionInflationController mInjectionInflater;
- private final QSContainerImplController.Builder mQSContainerImplControllerBuilder;
+ private final QSFragmentComponent.Factory mQsComponentFactory;
private final QSTileHost mHost;
private boolean mShowCollapsedOnKeyguard;
private boolean mLastKeyguardAndExpanded;
@@ -96,15 +95,17 @@ public class QSFragment extends LifecycleFragment implements QS, CommandQueue.Ca
private int[] mTmpLocation = new int[2];
private int mLastViewHeight;
private float mLastHeaderTranslation;
+ private QSPanelController mQSPanelController;
+ private QuickQSPanelController mQuickQSPanelController;
@Inject
public QSFragment(RemoteInputQuickSettingsDisabler remoteInputQsDisabler,
InjectionInflationController injectionInflater, QSTileHost qsTileHost,
StatusBarStateController statusBarStateController, CommandQueue commandQueue,
- QSContainerImplController.Builder qsContainerImplControllerBuilder) {
+ QSFragmentComponent.Factory qsComponentFactory) {
mRemoteInputQuickSettingsDisabler = remoteInputQsDisabler;
mInjectionInflater = injectionInflater;
- mQSContainerImplControllerBuilder = qsContainerImplControllerBuilder;
+ mQsComponentFactory = qsComponentFactory;
commandQueue.observe(getLifecycle(), this);
mHost = qsTileHost;
mStatusBarStateController = statusBarStateController;
@@ -120,8 +121,13 @@ public class QSFragment extends LifecycleFragment implements QS, CommandQueue.Ca
@Override
public void onViewCreated(View view, @Nullable Bundle savedInstanceState) {
- super.onViewCreated(view, savedInstanceState);
- mQSPanel = view.findViewById(R.id.quick_settings_panel);
+ QSFragmentComponent qsFragmentComponent = mQsComponentFactory.create(this);
+ mQSPanelController = qsFragmentComponent.getQSPanelController();
+ mQuickQSPanelController = qsFragmentComponent.getQuickQSPanelController();
+
+ mQSPanelController.init();
+ mQuickQSPanelController.init();
+
mQSPanelScrollView = view.findViewById(R.id.expanded_qs_scroll_view);
mQSPanelScrollView.addOnLayoutChangeListener(
(v, left, top, right, bottom, oldLeft, oldTop, oldRight, oldBottom) -> {
@@ -135,18 +141,15 @@ public class QSFragment extends LifecycleFragment implements QS, CommandQueue.Ca
});
mQSDetail = view.findViewById(R.id.qs_detail);
mHeader = view.findViewById(R.id.header);
- mQSPanel.setHeaderContainer(view.findViewById(R.id.header_text_container));
- mFooter = view.findViewById(R.id.qs_footer);
- mContainer = view.findViewById(id.quick_settings_container);
+ mQSPanelController.setHeaderContainer(view.findViewById(R.id.header_text_container));
+ mFooter = qsFragmentComponent.getQSFooter();
- mQSContainerImplController = mQSContainerImplControllerBuilder
- .setQSContainerImpl((QSContainerImpl) view)
- .build();
+ mQSContainerImplController = qsFragmentComponent.getQSContainerImplController();
mQSContainerImplController.init();
+ mContainer = mQSContainerImplController.getView();
- mQSDetail.setQsPanel(mQSPanel, mHeader, (View) mFooter);
- mQSAnimator = new QSAnimator(this, mHeader.findViewById(R.id.quick_qs_panel), mQSPanel);
-
+ mQSDetail.setQsPanel(mQSPanelController.getView(), mHeader, mFooter);
+ mQSAnimator = qsFragmentComponent.getQSAnimator();
mQSCustomizer = view.findViewById(R.id.qs_customize);
mQSCustomizer.setQs(this);
@@ -156,7 +159,7 @@ public class QSFragment extends LifecycleFragment implements QS, CommandQueue.Ca
setEditLocation(view);
mQSCustomizer.restoreInstanceState(savedInstanceState);
if (mQsExpanded) {
- mQSPanel.getTileLayout().restoreInstanceState(savedInstanceState);
+ mQSPanelController.getTileLayout().restoreInstanceState(savedInstanceState);
}
}
setHost(mHost);
@@ -188,7 +191,7 @@ public class QSFragment extends LifecycleFragment implements QS, CommandQueue.Ca
outState.putBoolean(EXTRA_LISTENING, mListening);
mQSCustomizer.saveInstanceState(outState);
if (mQsExpanded) {
- mQSPanel.getTileLayout().saveInstanceState(outState);
+ mQSPanelController.getTileLayout().saveInstanceState(outState);
}
}
@@ -249,14 +252,10 @@ public class QSFragment extends LifecycleFragment implements QS, CommandQueue.Ca
}
public void setHost(QSTileHost qsh) {
- mQSPanel.setHost(qsh, mQSCustomizer);
- mHeader.setQSPanel(mQSPanel);
- mFooter.setQSPanel(mQSPanel);
+ mQSPanelController.setCustomizer(mQSCustomizer);
+ mHeader.setQSPanel(mQSPanelController.getView());
+ mFooter.setQSPanel(mQSPanelController.getView());
mQSDetail.setHost(qsh);
-
- if (mQSAnimator != null) {
- mQSAnimator.setHost(qsh);
- }
}
@Override
@@ -278,7 +277,7 @@ public class QSFragment extends LifecycleFragment implements QS, CommandQueue.Ca
private void updateQsState() {
final boolean expandVisually = mQsExpanded || mStackScrollerOverscrolling
|| mHeaderAnimating;
- mQSPanel.setExpanded(mQsExpanded);
+ mQSPanelController.setExpanded(mQsExpanded);
mQSDetail.setExpanded(mQsExpanded);
boolean keyguardShowing = isKeyguardShowing();
mHeader.setVisibility((mQsExpanded || !keyguardShowing || mHeaderAnimating
@@ -294,7 +293,8 @@ public class QSFragment extends LifecycleFragment implements QS, CommandQueue.Ca
: View.INVISIBLE);
mFooter.setExpanded((keyguardShowing && !mHeaderAnimating && !mShowCollapsedOnKeyguard)
|| (mQsExpanded && !mStackScrollerOverscrolling));
- mQSPanel.setVisibility(!mQsDisabled && expandVisually ? View.VISIBLE : View.INVISIBLE);
+ mQSPanelController.setVisibility(
+ !mQsDisabled && expandVisually ? View.VISIBLE : View.INVISIBLE);
}
private boolean isKeyguardShowing() {
@@ -317,8 +317,12 @@ public class QSFragment extends LifecycleFragment implements QS, CommandQueue.Ca
}
}
+ public QSPanelController getQSPanelController() {
+ return mQSPanelController;
+ }
+
public QSPanel getQsPanel() {
- return mQSPanel;
+ return mQSPanelController.getView();
}
public QSCustomizer getCustomizer() {
@@ -327,7 +331,7 @@ public class QSFragment extends LifecycleFragment implements QS, CommandQueue.Ca
@Override
public boolean isShowingDetail() {
- return mQSPanel.isShowingCustomize() || mQSDetail.isShowingDetail();
+ return mQSPanelController.isShowingCustomize() || mQSDetail.isShowingDetail();
}
@Override
@@ -339,7 +343,7 @@ public class QSFragment extends LifecycleFragment implements QS, CommandQueue.Ca
public void setExpanded(boolean expanded) {
if (DEBUG) Log.d(TAG, "setExpanded " + expanded);
mQsExpanded = expanded;
- mQSPanel.setListening(mListening, mQsExpanded);
+ mQSPanelController.setListening(mListening, mQsExpanded);
updateQsState();
}
@@ -368,7 +372,7 @@ public class QSFragment extends LifecycleFragment implements QS, CommandQueue.Ca
mListening = listening;
mQSContainerImplController.setListening(listening);
mFooter.setListening(listening);
- mQSPanel.setListening(mListening, mQsExpanded);
+ mQSPanelController.setListening(mListening, mQsExpanded);
}
@Override
@@ -406,11 +410,15 @@ public class QSFragment extends LifecycleFragment implements QS, CommandQueue.Ca
float panelTranslationY = translationScaleY * heightDiff;
// Let the views animate their contents correctly by giving them the necessary context.
- mHeader.setExpansion(onKeyguardAndExpanded, expansion,
- panelTranslationY);
+ mHeader.setExpansion(onKeyguardAndExpanded, expansion, panelTranslationY);
+ if (expansion < 1 && expansion > 0.99) {
+ if (mQuickQSPanelController.switchTileLayout(false)) {
+ mHeader.updateResources();
+ }
+ }
mFooter.setExpansion(onKeyguardAndExpanded ? 1 : expansion);
- mQSPanel.getQsTileRevealController().setExpansion(expansion);
- mQSPanel.getTileLayout().setExpansion(expansion);
+ mQSPanelController.getQsTileRevealController().setExpansion(expansion);
+ mQSPanelController.getTileLayout().setExpansion(expansion);
mQSPanelScrollView.setTranslationY(translationScaleY * heightDiff);
if (fullyCollapsed) {
mQSPanelScrollView.setScrollY(0);
@@ -448,7 +456,8 @@ public class QSFragment extends LifecycleFragment implements QS, CommandQueue.Ca
float expandedMediaPosition = absoluteBottomPosition - mQSPanelScrollView.getScrollY()
+ mQSPanelScrollView.getScrollRange();
// The expanded media host should never move below the laid out position
- pinToBottom(expandedMediaPosition, mQSPanel.getMediaHost(), true /* expanded */);
+ pinToBottom(
+ expandedMediaPosition, mQSPanelController.getMediaHost(), true /* expanded */);
// The expanded media host should never move above the laid out position
pinToBottom(absoluteBottomPosition, mHeader.getHeaderQsPanel().getMediaHost(),
false /* expanded */);
@@ -538,7 +547,7 @@ public class QSFragment extends LifecycleFragment implements QS, CommandQueue.Ca
@Override
public void closeDetail() {
- mQSPanel.closeDetail();
+ mQSPanelController.closeDetail();
}
public void notifyCustomizeChanged() {
@@ -553,8 +562,8 @@ public class QSFragment extends LifecycleFragment implements QS, CommandQueue.Ca
}
/**
- * The height this view wants to be. This is different from {@link #getMeasuredHeight} such that
- * during closing the detail panel, this already returns the smaller height.
+ * The height this view wants to be. This is different from {@link View#getMeasuredHeight} such
+ * that during closing the detail panel, this already returns the smaller height.
*/
@Override
public int getDesiredHeight() {
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java b/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java
index efe46096239f..1b17a2a277f2 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java
@@ -22,11 +22,9 @@ import static com.android.systemui.util.Utils.useQsMediaPlayer;
import android.annotation.NonNull;
import android.annotation.Nullable;
-import android.content.ComponentName;
import android.content.Context;
import android.content.res.Configuration;
import android.content.res.Resources;
-import android.metrics.LogMaker;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
@@ -43,41 +41,30 @@ import com.android.internal.logging.UiEventLogger;
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
import com.android.internal.widget.RemeasuringLinearLayout;
import com.android.systemui.Dependency;
-import com.android.systemui.Dumpable;
import com.android.systemui.R;
-import com.android.systemui.broadcast.BroadcastDispatcher;
-import com.android.systemui.dump.DumpManager;
import com.android.systemui.media.MediaHierarchyManager;
import com.android.systemui.media.MediaHost;
import com.android.systemui.plugins.qs.DetailAdapter;
import com.android.systemui.plugins.qs.QSTile;
-import com.android.systemui.plugins.qs.QSTileView;
-import com.android.systemui.qs.QSHost.Callback;
import com.android.systemui.qs.customize.QSCustomizer;
-import com.android.systemui.qs.external.CustomTile;
import com.android.systemui.qs.logging.QSLogger;
-import com.android.systemui.settings.BrightnessController;
import com.android.systemui.settings.ToggleSliderView;
-import com.android.systemui.settings.UserTracker;
import com.android.systemui.statusbar.policy.BrightnessMirrorController;
import com.android.systemui.statusbar.policy.BrightnessMirrorController.BrightnessMirrorListener;
import com.android.systemui.tuner.TunerService;
import com.android.systemui.tuner.TunerService.Tunable;
import com.android.systemui.util.animation.DisappearParameters;
-import java.io.FileDescriptor;
-import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.Collection;
+import java.util.List;
import java.util.function.Consumer;
-import java.util.stream.Collectors;
import javax.inject.Inject;
import javax.inject.Named;
/** View that represents the quick settings tile panel (when expanded/pulled down). **/
-public class QSPanel extends LinearLayout implements Tunable, Callback, BrightnessMirrorListener,
- Dumpable {
+public class QSPanel extends LinearLayout implements Tunable, BrightnessMirrorListener {
public static final String QS_SHOW_BRIGHTNESS = "qs_show_brightness";
public static final String QS_SHOW_HEADER = "qs_show_header";
@@ -85,20 +72,15 @@ public class QSPanel extends LinearLayout implements Tunable, Callback, Brightne
private static final String TAG = "QSPanel";
protected final Context mContext;
- protected final ArrayList<TileRecord> mRecords = new ArrayList<>();
- private final BroadcastDispatcher mBroadcastDispatcher;
protected final MediaHost mMediaHost;
/**
* The index where the content starts that needs to be moved between parents
*/
private final int mMovableContentStartIndex;
- private String mCachedSpecs = "";
@Nullable
protected View mBrightnessView;
- @Nullable
- private BrightnessController mBrightnessController;
private final H mHandler = new H();
private final MetricsLogger mMetricsLogger = Dependency.get(MetricsLogger.class);
@@ -112,14 +94,14 @@ public class QSPanel extends LinearLayout implements Tunable, Callback, Brightne
protected boolean mListening;
private QSDetail.Callback mCallback;
- private final DumpManager mDumpManager;
private final QSLogger mQSLogger;
protected final UiEventLogger mUiEventLogger;
protected QSTileHost mHost;
- private final UserTracker mUserTracker;
+ private final List<OnConfigurationChangedListener> mOnConfigurationChangedListeners =
+ new ArrayList<>();
@Nullable
- protected QSSecurityFooter mSecurityFooter;
+ protected View mSecurityFooter;
@Nullable
protected View mFooter;
@@ -156,12 +138,9 @@ public class QSPanel extends LinearLayout implements Tunable, Callback, Brightne
public QSPanel(
@Named(VIEW_CONTEXT) Context context,
AttributeSet attrs,
- DumpManager dumpManager,
- BroadcastDispatcher broadcastDispatcher,
QSLogger qsLogger,
@Named(QS_PANEL) MediaHost mediaHost,
- UiEventLogger uiEventLogger,
- UserTracker userTracker
+ UiEventLogger uiEventLogger
) {
super(context, attrs);
mUsingMediaPlayer = useQsMediaPlayer(context);
@@ -174,16 +153,14 @@ public class QSPanel extends LinearLayout implements Tunable, Callback, Brightne
});
mContext = context;
mQSLogger = qsLogger;
- mDumpManager = dumpManager;
- mBroadcastDispatcher = broadcastDispatcher;
mUiEventLogger = uiEventLogger;
- mUserTracker = userTracker;
setOrientation(VERTICAL);
addViewsAboveTiles();
mMovableContentStartIndex = getChildCount();
mRegularTileLayout = createRegularTileLayout();
+ mTileLayout = mRegularTileLayout;
if (mUsingMediaPlayer) {
mHorizontalLinearLayout = new RemeasuringLinearLayout(mContext);
@@ -209,35 +186,27 @@ public class QSPanel extends LinearLayout implements Tunable, Callback, Brightne
initMediaHostState();
}
- addSecurityFooter();
if (mRegularTileLayout instanceof PagedTileLayout) {
mQsTileRevealController = new QSTileRevealController(mContext, this,
(PagedTileLayout) mRegularTileLayout);
}
- mQSLogger.logAllTilesChangeListening(mListening, getDumpableTag(), mCachedSpecs);
- updateResources();
+ mQSLogger.logAllTilesChangeListening(mListening, getDumpableTag(), "");
}
protected void onMediaVisibilityChanged(Boolean visible) {
- switchTileLayout();
if (mMediaVisibilityChangedListener != null) {
mMediaVisibilityChangedListener.accept(visible);
}
}
- protected void addSecurityFooter() {
- mSecurityFooter = new QSSecurityFooter(this, mContext, mUserTracker);
- }
-
protected void addViewsAboveTiles() {
mBrightnessView = LayoutInflater.from(mContext).inflate(
R.layout.quick_settings_brightness_dialog, this, false);
addView(mBrightnessView);
- mBrightnessController = new BrightnessController(getContext(),
- findViewById(R.id.brightness_slider), mBroadcastDispatcher);
}
- protected QSTileLayout createRegularTileLayout() {
+ /** */
+ public QSTileLayout createRegularTileLayout() {
if (mRegularTileLayout == null) {
mRegularTileLayout = (QSTileLayout) LayoutInflater.from(mContext).inflate(
R.layout.qs_paged_tile_layout, this, false);
@@ -337,37 +306,10 @@ public class QSPanel extends LinearLayout implements Tunable, Callback, Brightne
}
@Override
- protected void onAttachedToWindow() {
- super.onAttachedToWindow();
- final TunerService tunerService = Dependency.get(TunerService.class);
- tunerService.addTunable(this, QS_SHOW_BRIGHTNESS);
-
- if (mHost != null) {
- setTiles(mHost.getTiles());
- }
- if (mBrightnessMirrorController != null) {
- mBrightnessMirrorController.addCallback(this);
- }
- mDumpManager.registerDumpable(getDumpableTag(), this);
- }
-
- @Override
protected void onDetachedFromWindow() {
- Dependency.get(TunerService.class).removeTunable(this);
- if (mHost != null) {
- mHost.removeCallback(this);
- }
if (mTileLayout != null) {
mTileLayout.setListening(false);
}
- for (TileRecord record : mRecords) {
- record.tile.removeCallbacks();
- }
- mRecords.clear();
- if (mBrightnessMirrorController != null) {
- mBrightnessMirrorController.removeCallback(this);
- }
- mDumpManager.unregisterDumpable(getDumpableTag());
super.onDetachedFromWindow();
}
@@ -376,11 +318,6 @@ public class QSPanel extends LinearLayout implements Tunable, Callback, Brightne
}
@Override
- public void onTilesChanged() {
- setTiles(mHost.getTiles());
- }
-
- @Override
public void onTuningChanged(String key, String newValue) {
if (QS_SHOW_BRIGHTNESS.equals(key) && mBrightnessView != null) {
updateViewVisibilityForTuningValue(mBrightnessView, newValue);
@@ -391,8 +328,8 @@ public class QSPanel extends LinearLayout implements Tunable, Callback, Brightne
view.setVisibility(TunerService.parseIntegerSwitch(newValue, true) ? VISIBLE : GONE);
}
- public void openDetails(String subPanel) {
- QSTile tile = getTile(subPanel);
+ /** */
+ public void openDetails(QSTile tile) {
// If there's no tile with that name (as defined in QSFactoryImpl or other QSFactory),
// QSFactory will not be able to create a tile and getTile will return null
if (tile != null) {
@@ -400,15 +337,6 @@ public class QSPanel extends LinearLayout implements Tunable, Callback, Brightne
}
}
- private QSTile getTile(String subPanel) {
- for (int i = 0; i < mRecords.size(); i++) {
- if (subPanel.equals(mRecords.get(i).tile.getTileSpec())) {
- return mRecords.get(i).tile;
- }
- }
- return mHost.createTile(subPanel);
- }
-
public void setBrightnessMirror(BrightnessMirrorController c) {
if (mBrightnessMirrorController != null) {
mBrightnessMirrorController.removeCallback(this);
@@ -434,17 +362,8 @@ public class QSPanel extends LinearLayout implements Tunable, Callback, Brightne
mCallback = callback;
}
- public void setHost(QSTileHost host, QSCustomizer customizer) {
- mHost = host;
- mHost.addCallback(this);
- setTiles(mHost.getTiles());
- if (mSecurityFooter != null) {
- mSecurityFooter.setHostEnvironment(host);
- }
+ void setCustomizer(QSCustomizer customizer) {
mCustomizePanel = customizer;
- if (mCustomizePanel != null) {
- mCustomizePanel.setHost(mHost);
- }
}
/**
@@ -483,9 +402,6 @@ public class QSPanel extends LinearLayout implements Tunable, Callback, Brightne
updatePageIndicator();
- if (mListening) {
- refreshAllTiles();
- }
if (mTileLayout != null) {
mTileLayout.updateResources();
}
@@ -506,20 +422,21 @@ public class QSPanel extends LinearLayout implements Tunable, Callback, Brightne
res.getDimensionPixelSize(R.dimen.qs_panel_padding_bottom));
}
+ void addOnConfigurationChangedListener(OnConfigurationChangedListener listener) {
+ mOnConfigurationChangedListeners.add(listener);
+ }
+
+ void removeOnConfigurationChangedListener(OnConfigurationChangedListener listener) {
+ mOnConfigurationChangedListeners.remove(listener);
+ }
+
@Override
protected void onConfigurationChanged(Configuration newConfig) {
super.onConfigurationChanged(newConfig);
- if (mSecurityFooter != null) {
- mSecurityFooter.onConfigurationChanged();
- }
- updateResources();
+ mOnConfigurationChangedListeners.forEach(
+ listener -> listener.onConfigurationChange(newConfig));
updateBrightnessMirror();
-
- if (newConfig.orientation != mLastOrientation) {
- mLastOrientation = newConfig.orientation;
- switchTileLayout();
- }
}
@Override
@@ -527,14 +444,9 @@ public class QSPanel extends LinearLayout implements Tunable, Callback, Brightne
super.onFinishInflate();
mFooter = findViewById(R.id.qs_footer);
mDivider = findViewById(R.id.divider);
- switchTileLayout(true /* force */);
- }
-
- boolean switchTileLayout() {
- return switchTileLayout(false /* force */);
}
- private boolean switchTileLayout(boolean force) {
+ boolean switchTileLayout(boolean force, List<QSPanelControllerBase.TileRecord> records) {
/** Whether or not the QuickQSPanel currently contains a media player. */
boolean horizontal = shouldUseHorizontalLayout();
if (mDivider != null) {
@@ -562,13 +474,12 @@ public class QSPanel extends LinearLayout implements Tunable, Callback, Brightne
reAttachMediaHost();
if (mTileLayout != null) {
mTileLayout.setListening(false);
- for (TileRecord record : mRecords) {
+ for (QSPanelControllerBase.TileRecord record : records) {
mTileLayout.removeTile(record);
record.tile.removeCallback(record.callback);
}
}
mTileLayout = newLayout;
- if (mHost != null) setTiles(mHost.getTiles());
newLayout.setListening(mListening);
if (needsDynamicRowsAndColumns()) {
newLayout.setMinRows(horizontal ? 2 : 1);
@@ -617,20 +528,20 @@ public class QSPanel extends LinearLayout implements Tunable, Callback, Brightne
index++;
if (mSecurityFooter != null) {
- View view = mSecurityFooter.getView();
- LinearLayout.LayoutParams layoutParams = (LayoutParams) view.getLayoutParams();
+ LinearLayout.LayoutParams layoutParams =
+ (LayoutParams) mSecurityFooter.getLayoutParams();
if (mUsingHorizontalLayout && mHeaderContainer != null) {
// Adding the security view to the header, that enables us to avoid scrolling
layoutParams.width = 0;
layoutParams.weight = 1.6f;
- switchToParent(view, mHeaderContainer, 1 /* always in second place */);
+ switchToParent(mSecurityFooter, mHeaderContainer, 1 /* always in second place */);
} else {
layoutParams.width = LayoutParams.WRAP_CONTENT;
layoutParams.weight = 0;
- switchToParent(view, parent, index);
+ switchToParent(mSecurityFooter, parent, index);
index++;
}
- view.setLayoutParams(layoutParams);
+ mSecurityFooter.setLayoutParams(layoutParams);
}
if (mFooter != null) {
@@ -703,14 +614,6 @@ public class QSPanel extends LinearLayout implements Tunable, Callback, Brightne
if (!mExpanded && mTileLayout instanceof PagedTileLayout) {
((PagedTileLayout) mTileLayout).setCurrentItem(0, false);
}
- mMetricsLogger.visibility(MetricsEvent.QS_PANEL, mExpanded);
- if (!mExpanded) {
- mUiEventLogger.log(closePanelEvent());
- closeDetail();
- } else {
- mUiEventLogger.log(openPanelEvent());
- logTiles();
- }
}
public void setPageListener(final PagedTileLayout.PageListener pageListener) {
@@ -723,56 +626,16 @@ public class QSPanel extends LinearLayout implements Tunable, Callback, Brightne
return mExpanded;
}
- public void setListening(boolean listening) {
+ /** */
+ public void setListening(boolean listening, String cachedSpecs) {
if (mListening == listening) return;
mListening = listening;
if (mTileLayout != null) {
- mQSLogger.logAllTilesChangeListening(listening, getDumpableTag(), mCachedSpecs);
+ mQSLogger.logAllTilesChangeListening(listening, getDumpableTag(), cachedSpecs);
mTileLayout.setListening(listening);
}
- if (mListening) {
- refreshAllTiles();
- }
}
- private String getTilesSpecs() {
- return mRecords.stream()
- .map(tileRecord -> tileRecord.tile.getTileSpec())
- .collect(Collectors.joining(","));
- }
-
- public void setListening(boolean listening, boolean expanded) {
- setListening(listening && expanded);
- if (mSecurityFooter != null) {
- mSecurityFooter.setListening(listening);
- }
- // Set the listening as soon as the QS fragment starts listening regardless of the expansion,
- // so it will update the current brightness before the slider is visible.
- setBrightnessListening(listening);
- }
-
- public void setBrightnessListening(boolean listening) {
- if (mBrightnessController == null) {
- return;
- }
- if (listening) {
- mBrightnessController.registerCallbacks();
- } else {
- mBrightnessController.unregisterCallbacks();
- }
- }
-
- public void refreshAllTiles() {
- if (mBrightnessController != null) {
- mBrightnessController.checkRestrictionAndSetEnabled();
- }
- for (TileRecord r : mRecords) {
- r.tile.refreshState();
- }
- if (mSecurityFooter != null) {
- mSecurityFooter.refreshState();
- }
- }
public void showDetailAdapter(boolean show, DetailAdapter adapter, int[] locationInWindow) {
int xInWindow = locationInWindow[0];
@@ -794,33 +657,10 @@ public class QSPanel extends LinearLayout implements Tunable, Callback, Brightne
mHandler.obtainMessage(H.SHOW_DETAIL, show ? 1 : 0, 0, r).sendToTarget();
}
- public void setTiles(Collection<QSTile> tiles) {
- setTiles(tiles, false);
- }
-
- public void setTiles(Collection<QSTile> tiles, boolean collapsedView) {
- if (!collapsedView) {
- mQsTileRevealController.updateRevealedTiles(tiles);
- }
- for (TileRecord record : mRecords) {
- mTileLayout.removeTile(record);
- record.tile.removeCallback(record.callback);
- }
- mRecords.clear();
- mCachedSpecs = "";
- for (QSTile tile : tiles) {
- addTile(tile, collapsedView);
- }
- }
-
- protected void drawTile(TileRecord r, QSTile.State state) {
+ protected void drawTile(QSPanelControllerBase.TileRecord r, QSTile.State state) {
r.tileView.onStateChanged(state);
}
- protected QSTileView createTileView(QSTile tile, boolean collapsedView) {
- return mHost.createTileView(tile, collapsedView);
- }
-
protected QSEvent openPanelEvent() {
return QSEvent.QS_PANEL_EXPANDED;
}
@@ -837,14 +677,15 @@ public class QSPanel extends LinearLayout implements Tunable, Callback, Brightne
return mExpanded;
}
- protected TileRecord addTile(final QSTile tile, boolean collapsedView) {
- final TileRecord r = new TileRecord();
- r.tile = tile;
- r.tileView = createTileView(tile, collapsedView);
+ void updateRevealedTiles(Collection<QSTile> tiles) {
+ mQsTileRevealController.updateRevealedTiles(tiles);
+ }
+
+ void addTile(QSPanelControllerBase.TileRecord tileRecord) {
final QSTile.Callback callback = new QSTile.Callback() {
@Override
public void onStateChanged(QSTile.State state) {
- drawTile(r, state);
+ drawTile(tileRecord, state);
}
@Override
@@ -852,22 +693,22 @@ public class QSPanel extends LinearLayout implements Tunable, Callback, Brightne
// Both the collapsed and full QS panels get this callback, this check determines
// which one should handle showing the detail.
if (shouldShowDetail()) {
- QSPanel.this.showDetail(show, r);
+ QSPanel.this.showDetail(show, tileRecord);
}
}
@Override
public void onToggleStateChanged(boolean state) {
- if (mDetailRecord == r) {
+ if (mDetailRecord == tileRecord) {
fireToggleStateChanged(state);
}
}
@Override
public void onScanStateChanged(boolean state) {
- r.scanState = state;
- if (mDetailRecord == r) {
- fireScanStateChanged(r.scanState);
+ tileRecord.scanState = state;
+ if (mDetailRecord == tileRecord) {
+ fireScanStateChanged(tileRecord.scanState);
}
}
@@ -879,20 +720,20 @@ public class QSPanel extends LinearLayout implements Tunable, Callback, Brightne
}
}
};
- r.tile.addCallback(callback);
- r.callback = callback;
- r.tileView.init(r.tile);
- r.tile.refreshState();
- mRecords.add(r);
- mCachedSpecs = getTilesSpecs();
+
+ tileRecord.tile.addCallback(callback);
+ tileRecord.callback = callback;
+ tileRecord.tileView.init(tileRecord.tile);
+ tileRecord.tile.refreshState();
if (mTileLayout != null) {
- mTileLayout.addTile(r);
+ mTileLayout.addTile(tileRecord);
}
-
- return r;
}
+ void removeTile(QSPanelControllerBase.TileRecord tileRecord) {
+ mTileLayout.removeTile(tileRecord);
+ }
public void showEdit(final View v) {
v.post(new Runnable() {
@@ -925,8 +766,8 @@ public class QSPanel extends LinearLayout implements Tunable, Callback, Brightne
}
protected void handleShowDetail(Record r, boolean show) {
- if (r instanceof TileRecord) {
- handleShowDetailTile((TileRecord) r, show);
+ if (r instanceof QSPanelControllerBase.TileRecord) {
+ handleShowDetailTile((QSPanelControllerBase.TileRecord) r, show);
} else {
int x = 0;
int y = 0;
@@ -938,7 +779,7 @@ public class QSPanel extends LinearLayout implements Tunable, Callback, Brightne
}
}
- private void handleShowDetailTile(TileRecord r, boolean show) {
+ private void handleShowDetailTile(QSPanelControllerBase.TileRecord r, boolean show) {
if ((mDetailRecord != null) == show && mDetailRecord == r) return;
if (show) {
@@ -959,8 +800,8 @@ public class QSPanel extends LinearLayout implements Tunable, Callback, Brightne
protected void setDetailRecord(Record r) {
if (r == mDetailRecord) return;
mDetailRecord = r;
- final boolean scanState = mDetailRecord instanceof TileRecord
- && ((TileRecord) mDetailRecord).scanState;
+ final boolean scanState = mDetailRecord instanceof QSPanelControllerBase.TileRecord
+ && ((QSPanelControllerBase.TileRecord) mDetailRecord).scanState;
fireScanStateChanged(scanState);
}
@@ -972,15 +813,6 @@ public class QSPanel extends LinearLayout implements Tunable, Callback, Brightne
}
mGridContentVisible = visible;
}
-
- private void logTiles() {
- for (int i = 0; i < mRecords.size(); i++) {
- QSTile tile = mRecords.get(i).tile;
- mMetricsLogger.write(tile.populate(new LogMaker(tile.getMetricsCategory())
- .setType(MetricsEvent.TYPE_OPEN)));
- }
- }
-
private void fireShowingDetail(DetailAdapter detail, int x, int y) {
if (mCallback != null) {
mCallback.onShowingDetail(detail, x, y);
@@ -999,46 +831,15 @@ public class QSPanel extends LinearLayout implements Tunable, Callback, Brightne
}
}
- public void clickTile(ComponentName tile) {
- final String spec = CustomTile.toSpec(tile);
- final int N = mRecords.size();
- for (int i = 0; i < N; i++) {
- if (mRecords.get(i).tile.getTileSpec().equals(spec)) {
- mRecords.get(i).tile.click();
- break;
- }
- }
- }
-
QSTileLayout getTileLayout() {
return mTileLayout;
}
- QSTileView getTileView(QSTile tile) {
- for (TileRecord r : mRecords) {
- if (r.tile == tile) {
- return r.tileView;
- }
- }
- return null;
- }
-
- @Nullable
- public QSSecurityFooter getSecurityFooter() {
- return mSecurityFooter;
- }
-
@Nullable
public View getDivider() {
return mDivider;
}
- public void showDeviceMonitoringDialog() {
- if (mSecurityFooter != null) {
- mSecurityFooter.showDeviceMonitoringDialog();
- }
- }
-
public void setContentMargins(int startMargin, int endMargin) {
// Only some views actually want this content padding, others want to go all the way
// to the edge like the brightness slider
@@ -1121,9 +922,11 @@ public class QSPanel extends LinearLayout implements Tunable, Callback, Brightne
*/
protected void updateMargins(View view, int start, int end) {
LayoutParams lp = (LayoutParams) view.getLayoutParams();
- lp.setMarginStart(start);
- lp.setMarginEnd(end);
- view.setLayoutParams(lp);
+ if (lp != null) {
+ lp.setMarginStart(start);
+ lp.setMarginEnd(end);
+ view.setLayoutParams(lp);
+ }
}
public MediaHost getMediaHost() {
@@ -1141,6 +944,14 @@ public class QSPanel extends LinearLayout implements Tunable, Callback, Brightne
mMediaVisibilityChangedListener = visibilityChangedListener;
}
+ public boolean isListening() {
+ return mListening;
+ }
+
+ public void setSecurityFooter(View view) {
+ mSecurityFooter = view;
+ }
+
private class H extends Handler {
private static final int SHOW_DETAIL = 1;
private static final int SET_TILE_VISIBILITY = 2;
@@ -1156,46 +967,32 @@ public class QSPanel extends LinearLayout implements Tunable, Callback, Brightne
}
}
- @Override
- public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
- pw.println(getClass().getSimpleName() + ":");
- pw.println(" Tile records:");
- for (TileRecord record : mRecords) {
- if (record.tile instanceof Dumpable) {
- pw.print(" "); ((Dumpable) record.tile).dump(fd, pw, args);
- pw.print(" "); pw.println(record.tileView.toString());
- }
- }
- }
-
-
protected static class Record {
DetailAdapter detailAdapter;
int x;
int y;
}
- public static final class TileRecord extends Record {
- public QSTile tile;
- public com.android.systemui.plugins.qs.QSTileView tileView;
- public boolean scanState;
- public QSTile.Callback callback;
- }
-
public interface QSTileLayout {
-
+ /** */
default void saveInstanceState(Bundle outState) {}
+ /** */
default void restoreInstanceState(Bundle savedInstanceState) {}
- void addTile(TileRecord tile);
+ /** */
+ void addTile(QSPanelControllerBase.TileRecord tile);
- void removeTile(TileRecord tile);
+ /** */
+ void removeTile(QSPanelControllerBase.TileRecord tile);
- int getOffsetTop(TileRecord tile);
+ /** */
+ int getOffsetTop(QSPanelControllerBase.TileRecord tile);
+ /** */
boolean updateResources();
+ /** */
void setListening(boolean listening);
/**
@@ -1222,4 +1019,8 @@ public class QSPanel extends LinearLayout implements Tunable, Callback, Brightne
int getNumVisibleTiles();
}
+
+ interface OnConfigurationChangedListener {
+ void onConfigurationChange(Configuration newConfig);
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSPanelController.java b/packages/SystemUI/src/com/android/systemui/qs/QSPanelController.java
new file mode 100644
index 000000000000..f222b0d1ccc0
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSPanelController.java
@@ -0,0 +1,201 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.qs;
+
+import static com.android.systemui.qs.QSPanel.QS_SHOW_BRIGHTNESS;
+
+import android.annotation.NonNull;
+import android.content.res.Configuration;
+import android.view.View;
+import android.view.ViewGroup;
+
+import com.android.internal.logging.MetricsLogger;
+import com.android.internal.logging.UiEventLogger;
+import com.android.systemui.R;
+import com.android.systemui.dump.DumpManager;
+import com.android.systemui.media.MediaHost;
+import com.android.systemui.plugins.qs.QSTile;
+import com.android.systemui.qs.customize.QSCustomizer;
+import com.android.systemui.qs.dagger.QSScope;
+import com.android.systemui.settings.BrightnessController;
+import com.android.systemui.statusbar.policy.BrightnessMirrorController;
+import com.android.systemui.tuner.TunerService;
+
+import javax.inject.Inject;
+
+/**
+ * Controller for {@link QSPanel}.
+ */
+@QSScope
+public class QSPanelController extends QSPanelControllerBase<QSPanel> {
+ private final QSSecurityFooter mQsSecurityFooter;
+ private final TunerService mTunerService;
+ private final BrightnessController mBrightnessController;
+
+ private final QSPanel.OnConfigurationChangedListener mOnConfigurationChangedListener =
+ new QSPanel.OnConfigurationChangedListener() {
+ @Override
+ public void onConfigurationChange(Configuration newConfig) {
+ mView.updateResources();
+ mQsSecurityFooter.onConfigurationChanged();
+ if (mView.isListening()) {
+ refreshAllTiles();
+ }
+ }
+ };
+ private BrightnessMirrorController mBrightnessMirrorController;
+
+ @Inject
+ QSPanelController(QSPanel view, QSSecurityFooter qsSecurityFooter, TunerService tunerService,
+ QSTileHost qstileHost, DumpManager dumpManager,
+ MetricsLogger metricsLogger, UiEventLogger uiEventLogger,
+ BrightnessController.Factory brightnessControllerFactory) {
+ super(view, qstileHost, metricsLogger, uiEventLogger, dumpManager);
+ mQsSecurityFooter = qsSecurityFooter;
+ mTunerService = tunerService;
+ mQsSecurityFooter.setHostEnvironment(qstileHost);
+ mBrightnessController = brightnessControllerFactory.create(
+ mView.findViewById(R.id.brightness_slider));
+ }
+
+ @Override
+ protected void onViewAttached() {
+ super.onViewAttached();
+ mTunerService.addTunable(mView, QS_SHOW_BRIGHTNESS);
+ mView.updateResources();
+ if (mView.isListening()) {
+ refreshAllTiles();
+ }
+ mView.addOnConfigurationChangedListener(mOnConfigurationChangedListener);
+ mView.setSecurityFooter(mQsSecurityFooter.getView());
+ switchTileLayout(true);
+ if (mBrightnessMirrorController != null) {
+ mBrightnessMirrorController.addCallback(mView);
+ }
+ }
+
+ @Override
+ protected void onViewDetached() {
+ mTunerService.removeTunable(mView);
+ mView.removeOnConfigurationChangedListener(mOnConfigurationChangedListener);
+ if (mBrightnessMirrorController != null) {
+ mBrightnessMirrorController.removeCallback(mView);
+ }
+ super.onViewDetached();
+ }
+
+ /** TODO(b/168904199): Remove this method once view is controllerized. */
+ QSPanel getView() {
+ return mView;
+ }
+
+ /**
+ * Set the header container of quick settings.
+ */
+ public void setHeaderContainer(@NonNull ViewGroup headerContainer) {
+ mView.setHeaderContainer(headerContainer);
+ }
+
+ public QSPanel.QSTileLayout getTileLayout() {
+ return mView.getTileLayout();
+ }
+
+ /** */
+ public void setCustomizer(QSCustomizer customizer) {
+ mView.setCustomizer(customizer);
+ }
+
+ /** */
+ public boolean isShowingCustomize() {
+ return mView.isShowingCustomize();
+ }
+
+ /** */
+ public void setVisibility(int visibility) {
+ mView.setVisibility(visibility);
+ }
+
+ /** */
+ public void setListening(boolean listening, boolean expanded) {
+ setListening(listening && expanded);
+ if (mView.isListening()) {
+ refreshAllTiles();
+ }
+
+ mQsSecurityFooter.setListening(listening);
+
+ // Set the listening as soon as the QS fragment starts listening regardless of the
+ //expansion, so it will update the current brightness before the slider is visible.
+ if (listening) {
+ mBrightnessController.registerCallbacks();
+ } else {
+ mBrightnessController.unregisterCallbacks();
+ }
+ }
+
+ /** */
+ public QSTileRevealController getQsTileRevealController() {
+ return mView.getQsTileRevealController();
+ }
+
+ /** */
+ public MediaHost getMediaHost() {
+ return mView.getMediaHost();
+ }
+
+ /** */
+ public void setBrightnessMirror(BrightnessMirrorController brightnessMirrorController) {
+ mBrightnessMirrorController = brightnessMirrorController;
+ mView.setBrightnessMirror(brightnessMirrorController);
+ }
+
+ /** Get the QSTileHost this panel uses. */
+ public QSTileHost getHost() {
+ return mHost;
+ }
+
+
+ /** Open the details for a specific tile.. */
+ public void openDetails(String subPanel) {
+ QSTile tile = getTile(subPanel);
+ if (tile != null) {
+ mView.openDetails(tile);
+ }
+ }
+
+ /** Show the device monitoring dialog. */
+ public void showDeviceMonitoringDialog() {
+ mQsSecurityFooter.showDeviceMonitoringDialog();
+ }
+
+ /** Update appearance of QSPanel. */
+ public void updateResources() {
+ mView.updateResources();
+ }
+
+ /** Update state of all tiles. */
+ public void refreshAllTiles() {
+ mBrightnessController.checkRestrictionAndSetEnabled();
+ super.refreshAllTiles();
+ mQsSecurityFooter.refreshState();
+ }
+
+ /** Start customizing the Quick Settings. */
+ public void showEdit(View view) {
+ mView.showEdit(view);
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSPanelControllerBase.java b/packages/SystemUI/src/com/android/systemui/qs/QSPanelControllerBase.java
new file mode 100644
index 000000000000..fe92827806c6
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSPanelControllerBase.java
@@ -0,0 +1,250 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.qs;
+
+import static com.android.internal.logging.nano.MetricsProto.MetricsEvent;
+
+import android.content.ComponentName;
+import android.content.res.Configuration;
+import android.metrics.LogMaker;
+
+import com.android.internal.logging.MetricsLogger;
+import com.android.internal.logging.UiEventLogger;
+import com.android.systemui.Dumpable;
+import com.android.systemui.dump.DumpManager;
+import com.android.systemui.media.MediaHost;
+import com.android.systemui.plugins.qs.QSTile;
+import com.android.systemui.plugins.qs.QSTileView;
+import com.android.systemui.qs.external.CustomTile;
+import com.android.systemui.util.ViewController;
+
+import java.io.FileDescriptor;
+import java.io.PrintWriter;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.stream.Collectors;
+
+/**
+ * Controller for QSPanel views.
+ *
+ * @param <T> Type of QSPanel.
+ */
+public abstract class QSPanelControllerBase<T extends QSPanel> extends ViewController<T>
+ implements Dumpable{
+ protected final QSTileHost mHost;
+ private final MediaHost mMediaHost;
+ private final MetricsLogger mMetricsLogger;
+ private final UiEventLogger mUiEventLogger;
+ private final DumpManager mDumpManager;
+ protected final ArrayList<TileRecord> mRecords = new ArrayList<>();
+
+ private int mLastOrientation;
+
+ private final QSHost.Callback mQSHostCallback = this::setTiles;
+
+ private final QSPanel.OnConfigurationChangedListener mOnConfigurationChangedListener =
+ new QSPanel.OnConfigurationChangedListener() {
+ @Override
+ public void onConfigurationChange(Configuration newConfig) {
+ if (newConfig.orientation != mLastOrientation) {
+ mLastOrientation = newConfig.orientation;
+ switchTileLayout(false);
+ }
+ }
+ };
+ private String mCachedSpecs = "";
+
+ protected QSPanelControllerBase(T view, QSTileHost host,
+ MetricsLogger metricsLogger, UiEventLogger uiEventLogger, DumpManager dumpManager) {
+ super(view);
+ mHost = host;
+ mMediaHost = mView.getMediaHost();
+ mMetricsLogger = metricsLogger;
+ mUiEventLogger = uiEventLogger;
+ mDumpManager = dumpManager;
+ }
+
+ @Override
+ protected void onViewAttached() {
+ mView.addOnConfigurationChangedListener(mOnConfigurationChangedListener);
+ mHost.addCallback(mQSHostCallback);
+ mMediaHost.addVisibilityChangeListener(aBoolean -> {
+ switchTileLayout(false);
+ return null;
+ });
+ setTiles();
+ switchTileLayout(true);
+ mDumpManager.registerDumpable(mView.getDumpableTag(), this);
+ }
+
+ @Override
+ protected void onViewDetached() {
+ mView.removeOnConfigurationChangedListener(mOnConfigurationChangedListener);
+ mHost.removeCallback(mQSHostCallback);
+
+ for (TileRecord record : mRecords) {
+ record.tile.removeCallbacks();
+ }
+ mRecords.clear();
+ mDumpManager.unregisterDumpable(mView.getDumpableTag());
+ }
+
+ /** */
+ public void setTiles() {
+ setTiles(mHost.getTiles(), false);
+ }
+
+ /** */
+ public void setTiles(Collection<QSTile> tiles, boolean collapsedView) {
+ if (!collapsedView) {
+ mView.updateRevealedTiles(tiles);
+ }
+ for (QSPanelControllerBase.TileRecord record : mRecords) {
+ mView.removeTile(record);
+ record.tile.removeCallback(record.callback);
+ }
+ mRecords.clear();
+ mCachedSpecs = "";
+ for (QSTile tile : tiles) {
+ addTile(tile, collapsedView);
+ }
+ }
+
+ /** */
+ public void refreshAllTiles() {
+ for (QSPanelControllerBase.TileRecord r : mRecords) {
+ r.tile.refreshState();
+ }
+ }
+
+ private void addTile(final QSTile tile, boolean collapsedView) {
+ final TileRecord r = new TileRecord();
+ r.tile = tile;
+ r.tileView = mHost.createTileView(tile, collapsedView);
+ mView.addTile(r);
+ mRecords.add(r);
+ mCachedSpecs = getTilesSpecs();
+
+ }
+
+ /** */
+ public void clickTile(ComponentName tile) {
+ final String spec = CustomTile.toSpec(tile);
+ for (TileRecord record : mRecords) {
+ if (record.tile.getTileSpec().equals(spec)) {
+ record.tile.click();
+ break;
+ }
+ }
+ }
+ protected QSTile getTile(String subPanel) {
+ for (int i = 0; i < mRecords.size(); i++) {
+ if (subPanel.equals(mRecords.get(i).tile.getTileSpec())) {
+ return mRecords.get(i).tile;
+ }
+ }
+ return mHost.createTile(subPanel);
+ }
+
+
+ QSTileView getTileView(QSTile tile) {
+ for (QSPanelControllerBase.TileRecord r : mRecords) {
+ if (r.tile == tile) {
+ return r.tileView;
+ }
+ }
+ return null;
+ }
+
+ private String getTilesSpecs() {
+ return mRecords.stream()
+ .map(tileRecord -> tileRecord.tile.getTileSpec())
+ .collect(Collectors.joining(","));
+ }
+
+
+ /** */
+ public void setExpanded(boolean expanded) {
+ mView.setExpanded(expanded);
+ mMetricsLogger.visibility(MetricsEvent.QS_PANEL, expanded);
+ if (!expanded) {
+ mUiEventLogger.log(mView.closePanelEvent());
+ closeDetail();
+ } else {
+ mUiEventLogger.log(mView.openPanelEvent());
+ logTiles();
+ }
+ }
+
+ /** */
+ public void closeDetail() {
+ mView.closeDetail();
+ }
+
+ /** */
+ public void openDetails(String subPanel) {
+ QSTile tile = getTile(subPanel);
+ // If there's no tile with that name (as defined in QSFactoryImpl or other QSFactory),
+ // QSFactory will not be able to create a tile and getTile will return null
+ if (tile != null) {
+ mView.showDetailAdapter(
+ true, tile.getDetailAdapter(), new int[]{mView.getWidth() / 2, 0});
+ }
+ }
+
+
+ void setListening(boolean listening) {
+ mView.setListening(listening, mCachedSpecs);
+ }
+
+ boolean switchTileLayout(boolean force) {
+ if (mView.switchTileLayout(force, mRecords)) {
+ setTiles();
+ return true;
+ }
+ return false;
+ }
+
+ private void logTiles() {
+ for (int i = 0; i < mRecords.size(); i++) {
+ QSTile tile = mRecords.get(i).tile;
+ mMetricsLogger.write(tile.populate(new LogMaker(tile.getMetricsCategory())
+ .setType(MetricsEvent.TYPE_OPEN)));
+ }
+ }
+
+
+ @Override
+ public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
+ pw.println(getClass().getSimpleName() + ":");
+ pw.println(" Tile records:");
+ for (QSPanelControllerBase.TileRecord record : mRecords) {
+ if (record.tile instanceof Dumpable) {
+ pw.print(" "); ((Dumpable) record.tile).dump(fd, pw, args);
+ pw.print(" "); pw.println(record.tileView.toString());
+ }
+ }
+ }
+
+ /** */
+ public static final class TileRecord extends QSPanel.Record {
+ public QSTile tile;
+ public com.android.systemui.plugins.qs.QSTileView tileView;
+ public boolean scanState;
+ public QSTile.Callback callback;
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSSecurityFooter.java b/packages/SystemUI/src/com/android/systemui/qs/QSSecurityFooter.java
index 0891972c11d2..c90182b15da6 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSSecurityFooter.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSSecurityFooter.java
@@ -44,11 +44,15 @@ import com.android.systemui.Dependency;
import com.android.systemui.FontSizeUtils;
import com.android.systemui.R;
import com.android.systemui.plugins.ActivityStarter;
+import com.android.systemui.qs.dagger.QSScope;
import com.android.systemui.settings.UserTracker;
import com.android.systemui.statusbar.phone.SystemUIDialog;
import com.android.systemui.statusbar.policy.SecurityController;
-public class QSSecurityFooter implements OnClickListener, DialogInterface.OnClickListener {
+import javax.inject.Inject;
+
+@QSScope
+class QSSecurityFooter implements OnClickListener, DialogInterface.OnClickListener {
protected static final String TAG = "QSSecurityFooter";
protected static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
private static final boolean DEBUG_FORCE_VISIBLE = false;
@@ -72,12 +76,13 @@ public class QSSecurityFooter implements OnClickListener, DialogInterface.OnClic
private int mFooterTextId;
private int mFooterIconId;
+ @Inject
public QSSecurityFooter(QSPanel qsPanel, Context context, UserTracker userTracker) {
mRootView = LayoutInflater.from(context)
.inflate(R.layout.quick_settings_footer, qsPanel, false);
mRootView.setOnClickListener(this);
- mFooterText = (TextView) mRootView.findViewById(R.id.footer_text);
- mFooterIcon = (ImageView) mRootView.findViewById(R.id.footer_icon);
+ mFooterText = mRootView.findViewById(R.id.footer_text);
+ mFooterIcon = mRootView.findViewById(R.id.footer_icon);
mFooterIconId = R.drawable.ic_info_outline;
mContext = context;
mMainHandler = new Handler(Looper.myLooper());
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSTileRevealController.java b/packages/SystemUI/src/com/android/systemui/qs/QSTileRevealController.java
index 2f012e6e608e..3d4a417abf2e 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSTileRevealController.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSTileRevealController.java
@@ -8,11 +8,16 @@ import android.util.ArraySet;
import com.android.systemui.Prefs;
import com.android.systemui.plugins.qs.QSTile;
+import com.android.systemui.qs.dagger.QSScope;
import java.util.Collection;
import java.util.Collections;
import java.util.Set;
+import javax.inject.Inject;
+
+/** */
+@QSScope
public class QSTileRevealController {
private static final long QS_REVEAL_TILES_DELAY = 500L;
@@ -34,6 +39,7 @@ public class QSTileRevealController {
}
};
+ @Inject
QSTileRevealController(Context context, QSPanel qsPanel, PagedTileLayout pagedTileLayout) {
mContext = context;
mQSPanel = qsPanel;
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QuickQSPanel.java b/packages/SystemUI/src/com/android/systemui/qs/QuickQSPanel.java
index 82cb8639e9ee..84a5b6f0538d 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QuickQSPanel.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QuickQSPanel.java
@@ -28,23 +28,13 @@ import android.view.View;
import android.widget.LinearLayout;
import com.android.internal.logging.UiEventLogger;
-import com.android.systemui.Dependency;
import com.android.systemui.R;
-import com.android.systemui.broadcast.BroadcastDispatcher;
-import com.android.systemui.dump.DumpManager;
import com.android.systemui.media.MediaHierarchyManager;
import com.android.systemui.media.MediaHost;
import com.android.systemui.plugins.qs.QSTile;
import com.android.systemui.plugins.qs.QSTile.SignalState;
import com.android.systemui.plugins.qs.QSTile.State;
-import com.android.systemui.qs.customize.QSCustomizer;
import com.android.systemui.qs.logging.QSLogger;
-import com.android.systemui.settings.UserTracker;
-import com.android.systemui.tuner.TunerService;
-import com.android.systemui.tuner.TunerService.Tunable;
-
-import java.util.ArrayList;
-import java.util.Collection;
import javax.inject.Inject;
import javax.inject.Named;
@@ -68,15 +58,10 @@ public class QuickQSPanel extends QSPanel {
public QuickQSPanel(
@Named(VIEW_CONTEXT) Context context,
AttributeSet attrs,
- DumpManager dumpManager,
- BroadcastDispatcher broadcastDispatcher,
QSLogger qsLogger,
@Named(QUICK_QS_PANEL) MediaHost mediaHost,
- UiEventLogger uiEventLogger,
- UserTracker userTracker
- ) {
- super(context, attrs, dumpManager, broadcastDispatcher, qsLogger, mediaHost, uiEventLogger,
- userTracker);
+ UiEventLogger uiEventLogger) {
+ super(context, attrs, qsLogger, mediaHost, uiEventLogger);
sDefaultMaxTiles = getResources().getInteger(R.integer.quick_qs_panel_max_columns);
applyBottomMargin((View) mRegularTileLayout);
}
@@ -89,17 +74,12 @@ public class QuickQSPanel extends QSPanel {
}
@Override
- protected void addSecurityFooter() {
- // No footer needed
- }
-
- @Override
protected void addViewsAboveTiles() {
// Nothing to add above the tiles
}
@Override
- protected TileLayout createRegularTileLayout() {
+ public TileLayout createRegularTileLayout() {
return new QuickQSPanel.HeaderTileLayout(mContext, mUiEventLogger);
}
@@ -133,18 +113,6 @@ public class QuickQSPanel extends QSPanel {
}
@Override
- protected void onAttachedToWindow() {
- super.onAttachedToWindow();
- Dependency.get(TunerService.class).addTunable(mNumTiles, NUM_QUICK_TILES);
- }
-
- @Override
- protected void onDetachedFromWindow() {
- super.onDetachedFromWindow();
- Dependency.get(TunerService.class).removeTunable(mNumTiles);
- }
-
- @Override
protected String getDumpableTag() {
return TAG;
}
@@ -159,7 +127,7 @@ public class QuickQSPanel extends QSPanel {
}
@Override
- protected void drawTile(TileRecord r, State state) {
+ protected void drawTile(QSPanelControllerBase.TileRecord r, State state) {
if (state instanceof SignalState) {
SignalState copy = new SignalState();
state.copyTo(copy);
@@ -171,17 +139,8 @@ public class QuickQSPanel extends QSPanel {
super.drawTile(r, state);
}
- @Override
- public void setHost(QSTileHost host, QSCustomizer customizer) {
- super.setHost(host, customizer);
- setTiles(mHost.getTiles());
- }
-
public void setMaxTiles(int maxTiles) {
mMaxTiles = maxTiles;
- if (mHost != null) {
- setTiles(mHost.getTiles());
- }
}
@Override
@@ -192,25 +151,6 @@ public class QuickQSPanel extends QSPanel {
}
}
- @Override
- public void setTiles(Collection<QSTile> tiles) {
- ArrayList<QSTile> quickTiles = new ArrayList<>();
- for (QSTile tile : tiles) {
- quickTiles.add(tile);
- if (quickTiles.size() == mMaxTiles) {
- break;
- }
- }
- super.setTiles(quickTiles, true);
- }
-
- private final Tunable mNumTiles = new Tunable() {
- @Override
- public void onTuningChanged(String key, String newValue) {
- setMaxTiles(parseNumTiles(newValue));
- }
- };
-
public int getNumQuickTiles() {
return mMaxTiles;
}
@@ -308,7 +248,7 @@ public class QuickQSPanel extends QSPanel {
}
@Override
- protected void addTileView(TileRecord tile) {
+ protected void addTileView(QSPanelControllerBase.TileRecord tile) {
addView(tile.tileView, getChildCount(), generateTileLayoutParams());
}
@@ -371,7 +311,7 @@ public class QuickQSPanel extends QSPanel {
private void setAccessibilityOrder() {
if (mRecords != null && mRecords.size() > 0) {
View previousView = this;
- for (TileRecord record : mRecords) {
+ for (QSPanelControllerBase.TileRecord record : mRecords) {
if (record.tileView.getVisibility() == GONE) continue;
previousView = record.tileView.updateAccessibilityOrder(previousView);
}
@@ -383,7 +323,7 @@ public class QuickQSPanel extends QSPanel {
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
// Measure each QS tile.
- for (TileRecord record : mRecords) {
+ for (QSPanelControllerBase.TileRecord record : mRecords) {
if (record.tileView.getVisibility() == GONE) continue;
record.tileView.measure(exactly(mCellWidth), exactly(mCellHeight));
}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QuickQSPanelController.java b/packages/SystemUI/src/com/android/systemui/qs/QuickQSPanelController.java
new file mode 100644
index 000000000000..97b6e99a0390
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/qs/QuickQSPanelController.java
@@ -0,0 +1,83 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.qs;
+
+import static com.android.systemui.qs.QuickQSPanel.NUM_QUICK_TILES;
+import static com.android.systemui.qs.QuickQSPanel.parseNumTiles;
+
+import com.android.internal.logging.MetricsLogger;
+import com.android.internal.logging.UiEventLogger;
+import com.android.systemui.dump.DumpManager;
+import com.android.systemui.plugins.qs.QSTile;
+import com.android.systemui.qs.dagger.QSScope;
+import com.android.systemui.tuner.TunerService;
+import com.android.systemui.tuner.TunerService.Tunable;
+
+import java.util.ArrayList;
+
+import javax.inject.Inject;
+
+/** Controller for {@link QuickQSPanel}. */
+@QSScope
+public class QuickQSPanelController extends QSPanelControllerBase<QuickQSPanel> {
+ private final Tunable mNumTiles =
+ (key, newValue) -> setMaxTiles(parseNumTiles(newValue));
+
+ private final TunerService mTunerService;
+
+ @Inject
+ QuickQSPanelController(QuickQSPanel view, TunerService tunerService, QSTileHost qsTileHost,
+ MetricsLogger metricsLogger, UiEventLogger uiEventLogger,
+ DumpManager dumpManager) {
+ super(view, qsTileHost, metricsLogger, uiEventLogger, dumpManager);
+ mTunerService = tunerService;
+ }
+
+ @Override
+ protected void onViewAttached() {
+ super.onViewAttached();
+ mTunerService.addTunable(mNumTiles, NUM_QUICK_TILES);
+
+ }
+
+ @Override
+ protected void onViewDetached() {
+ super.onViewDetached();
+ mTunerService.removeTunable(mNumTiles);
+ }
+
+ public boolean isListening() {
+ return mView.isListening();
+ }
+
+ private void setMaxTiles(int parseNumTiles) {
+ mView.setMaxTiles(parseNumTiles);
+ setTiles();
+ }
+
+ @Override
+ public void setTiles() {
+ ArrayList<QSTile> quickTiles = new ArrayList<>();
+ for (QSTile tile : mHost.getTiles()) {
+ quickTiles.add(tile);
+ if (quickTiles.size() == mView.getNumQuickTiles()) {
+ break;
+ }
+ }
+ super.setTiles(quickTiles, true);
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QuickStatusBarHeader.java b/packages/SystemUI/src/com/android/systemui/qs/QuickStatusBarHeader.java
index a9fbc744b38e..5757602b9d0f 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QuickStatusBarHeader.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QuickStatusBarHeader.java
@@ -353,11 +353,7 @@ public class QuickStatusBarHeader extends RelativeLayout implements LifecycleOwn
mPrivacyChip.setExpanded(expansionFraction > 0.5);
mPrivacyChipAlphaAnimator.setPosition(keyguardExpansionFraction);
}
- if (expansionFraction < 1 && expansionFraction > 0.99) {
- if (mHeaderQsPanel.switchTileLayout()) {
- updateResources();
- }
- }
+
mKeyguardExpansionFraction = keyguardExpansionFraction;
}
@@ -446,7 +442,6 @@ public class QuickStatusBarHeader extends RelativeLayout implements LifecycleOwn
public void setQSPanel(final QSPanel qsPanel) {
//host.setHeaderView(mExpandIndicator);
mHeaderQsPanel.setQSPanelAndHeader(qsPanel, this);
- mHeaderQsPanel.setHost(qsPanel.getHost(), null /* No customization in header */);
Rect tintArea = new Rect(0, 0, 0, 0);
int colorForeground = Utils.getColorAttrDefaultColor(getContext(),
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QuickStatusBarHeaderController.java b/packages/SystemUI/src/com/android/systemui/qs/QuickStatusBarHeaderController.java
index 676a300b0ff2..febb71c3223b 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QuickStatusBarHeaderController.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QuickStatusBarHeaderController.java
@@ -44,6 +44,7 @@ import com.android.systemui.privacy.PrivacyChipEvent;
import com.android.systemui.privacy.PrivacyItem;
import com.android.systemui.privacy.PrivacyItemController;
import com.android.systemui.qs.carrier.QSCarrierGroupController;
+import com.android.systemui.qs.dagger.QSScope;
import com.android.systemui.settings.UserTracker;
import com.android.systemui.statusbar.CommandQueue;
import com.android.systemui.statusbar.phone.StatusBarIconController;
@@ -64,6 +65,7 @@ import javax.inject.Inject;
/**
* Controller for {@link QuickStatusBarHeader}.
*/
+@QSScope
class QuickStatusBarHeaderController extends ViewController<QuickStatusBarHeader> {
private static final String TAG = "QuickStatusBarHeader";
@@ -74,7 +76,7 @@ class QuickStatusBarHeaderController extends ViewController<QuickStatusBarHeader
private final ActivityStarter mActivityStarter;
private final UiEventLogger mUiEventLogger;
private final QSCarrierGroupController mQSCarrierGroupController;
- private final QuickQSPanel mHeaderQsPanel;
+ private final QuickQSPanelController mHeaderQsPanelController;
private final LifecycleRegistry mLifecycle;
private final OngoingPrivacyChip mPrivacyChip;
private final Clock mClockView;
@@ -93,6 +95,7 @@ class QuickStatusBarHeaderController extends ViewController<QuickStatusBarHeader
private AlarmClockInfo mNextAlarm;
private boolean mAllIndicatorsEnabled;
private boolean mMicCameraIndicatorsEnabled;
+ private boolean mLocationIndicatorsEnabled;
private boolean mPrivacyChipLogged;
private int mRingerMode = AudioManager.RINGER_MODE_NORMAL;
@@ -156,6 +159,14 @@ class QuickStatusBarHeaderController extends ViewController<QuickStatusBarHeader
}
}
+ @Override
+ public void onFlagLocationChanged(boolean flag) {
+ if (mLocationIndicatorsEnabled != flag) {
+ mLocationIndicatorsEnabled = flag;
+ update();
+ }
+ }
+
private void update() {
StatusIconContainer iconContainer = mView.requireViewById(R.id.statusIcons);
iconContainer.setIgnoredSlots(getIgnoredIconSlots());
@@ -194,13 +205,14 @@ class QuickStatusBarHeaderController extends ViewController<QuickStatusBarHeader
}
};
- private QuickStatusBarHeaderController(QuickStatusBarHeader view,
+ @Inject
+ QuickStatusBarHeaderController(QuickStatusBarHeader view,
ZenModeController zenModeController, NextAlarmController nextAlarmController,
PrivacyItemController privacyItemController, RingerModeTracker ringerModeTracker,
ActivityStarter activityStarter, UiEventLogger uiEventLogger,
QSTileHost qsTileHost, StatusBarIconController statusBarIconController,
CommandQueue commandQueue, DemoModeController demoModeController,
- UserTracker userTracker,
+ UserTracker userTracker, QuickQSPanelController quickQSPanelController,
QSCarrierGroupController.Builder qsCarrierGroupControllerBuilder) {
super(view);
mZenModeController = zenModeController;
@@ -215,6 +227,7 @@ class QuickStatusBarHeaderController extends ViewController<QuickStatusBarHeader
mDemoModeController = demoModeController;
mUserTracker = userTracker;
mLifecycle = new LifecycleRegistry(mLifecycleOwner);
+ mHeaderQsPanelController = quickQSPanelController;
mQSCarrierGroupController = qsCarrierGroupControllerBuilder
.setQSCarrierGroup(mView.findViewById(R.id.carrier_group))
@@ -222,7 +235,6 @@ class QuickStatusBarHeaderController extends ViewController<QuickStatusBarHeader
mPrivacyChip = mView.findViewById(R.id.privacy_chip);
- mHeaderQsPanel = mView.findViewById(R.id.quick_qs_panel);
mNextAlarmContainer = mView.findViewById(R.id.alarm_container);
mClockView = mView.findViewById(R.id.clock);
mRingerContainer = mView.findViewById(R.id.ringer_container);
@@ -252,6 +264,7 @@ class QuickStatusBarHeaderController extends ViewController<QuickStatusBarHeader
mAllIndicatorsEnabled = mPrivacyItemController.getAllIndicatorsAvailable();
mMicCameraIndicatorsEnabled = mPrivacyItemController.getMicCameraAvailable();
+ mLocationIndicatorsEnabled = mPrivacyItemController.getLocationAvailable();
setChipVisibility(mPrivacyChip.getVisibility() == View.VISIBLE);
@@ -280,8 +293,12 @@ class QuickStatusBarHeaderController extends ViewController<QuickStatusBarHeader
}
mListening = listening;
- mHeaderQsPanel.setListening(listening);
- if (mHeaderQsPanel.switchTileLayout()) {
+ mHeaderQsPanelController.setListening(listening);
+ if (mHeaderQsPanelController.isListening()) {
+ mHeaderQsPanelController.refreshAllTiles();
+ }
+
+ if (mHeaderQsPanelController.switchTileLayout(false)) {
mView.updateResources();
}
@@ -292,6 +309,7 @@ class QuickStatusBarHeaderController extends ViewController<QuickStatusBarHeader
// Get the most up to date info
mAllIndicatorsEnabled = mPrivacyItemController.getAllIndicatorsAvailable();
mMicCameraIndicatorsEnabled = mPrivacyItemController.getMicCameraAvailable();
+ mLocationIndicatorsEnabled = mPrivacyItemController.getLocationAvailable();
mPrivacyItemController.addCallback(mPICCallback);
} else {
mZenModeController.removeCallback(mZenModeControllerCallback);
@@ -323,7 +341,7 @@ class QuickStatusBarHeaderController extends ViewController<QuickStatusBarHeader
com.android.internal.R.string.status_bar_camera));
ignored.add(mView.getResources().getString(
com.android.internal.R.string.status_bar_microphone));
- if (mAllIndicatorsEnabled) {
+ if (mAllIndicatorsEnabled || mLocationIndicatorsEnabled) {
ignored.add(mView.getResources().getString(
com.android.internal.R.string.status_bar_location));
}
@@ -333,7 +351,7 @@ class QuickStatusBarHeaderController extends ViewController<QuickStatusBarHeader
}
private boolean getChipEnabled() {
- return mMicCameraIndicatorsEnabled || mAllIndicatorsEnabled;
+ return mMicCameraIndicatorsEnabled || mLocationIndicatorsEnabled || mAllIndicatorsEnabled;
}
private boolean isZenOverridingRinger() {
@@ -369,55 +387,4 @@ class QuickStatusBarHeaderController extends ViewController<QuickStatusBarHeader
mClockView.onDemoModeFinished();
}
}
-
- static class Builder {
- private final ZenModeController mZenModeController;
- private final NextAlarmController mNextAlarmController;
- private final PrivacyItemController mPrivacyItemController;
- private final RingerModeTracker mRingerModeTracker;
- private final ActivityStarter mActivityStarter;
- private final UiEventLogger mUiEventLogger;
- private final QSTileHost mQsTileHost;
- private final StatusBarIconController mStatusBarIconController;
- private final CommandQueue mCommandQueue;
- private final DemoModeController mDemoModeController;
- private final UserTracker mUserTracker;
- private final QSCarrierGroupController.Builder mQSCarrierGroupControllerBuilder;
- private QuickStatusBarHeader mView;
-
- @Inject
- Builder(ZenModeController zenModeController, NextAlarmController nextAlarmController,
- PrivacyItemController privacyItemController, RingerModeTracker ringerModeTracker,
- ActivityStarter activityStarter, UiEventLogger uiEventLogger, QSTileHost qsTileHost,
- StatusBarIconController statusBarIconController, CommandQueue commandQueue,
- DemoModeController demoModeController, UserTracker userTracker,
- QSCarrierGroupController.Builder qsCarrierGroupControllerBuilder) {
- mZenModeController = zenModeController;
- mNextAlarmController = nextAlarmController;
- mPrivacyItemController = privacyItemController;
- mRingerModeTracker = ringerModeTracker;
- mActivityStarter = activityStarter;
- mUiEventLogger = uiEventLogger;
- mQsTileHost = qsTileHost;
- mStatusBarIconController = statusBarIconController;
- mCommandQueue = commandQueue;
- mDemoModeController = demoModeController;
- mUserTracker = userTracker;
- mQSCarrierGroupControllerBuilder = qsCarrierGroupControllerBuilder;
- }
-
- public Builder setQuickStatusBarHeader(QuickStatusBarHeader view) {
- mView = view;
- return this;
- }
-
-
- QuickStatusBarHeaderController build() {
- return new QuickStatusBarHeaderController(mView, mZenModeController,
- mNextAlarmController, mPrivacyItemController, mRingerModeTracker,
- mActivityStarter, mUiEventLogger, mQsTileHost, mStatusBarIconController,
- mCommandQueue, mDemoModeController, mUserTracker,
- mQSCarrierGroupControllerBuilder);
- }
- }
}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/TileLayout.java b/packages/SystemUI/src/com/android/systemui/qs/TileLayout.java
index 694492a33524..4ab7afd46602 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/TileLayout.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/TileLayout.java
@@ -11,7 +11,7 @@ import android.view.ViewGroup;
import com.android.systemui.R;
import com.android.systemui.qs.QSPanel.QSTileLayout;
-import com.android.systemui.qs.QSPanel.TileRecord;
+import com.android.systemui.qs.QSPanelControllerBase.TileRecord;
import java.util.ArrayList;
diff --git a/packages/SystemUI/src/com/android/systemui/qs/customize/QSCustomizer.java b/packages/SystemUI/src/com/android/systemui/qs/customize/QSCustomizer.java
index 55b67e061c13..8097958fac39 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/customize/QSCustomizer.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/customize/QSCustomizer.java
@@ -74,9 +74,9 @@ public class QSCustomizer extends LinearLayout implements OnMenuItemClickListene
private final ScreenLifecycle mScreenLifecycle;
private final TileQueryHelper mTileQueryHelper;
private final View mTransparentView;
+ private final QSTileHost mHost;
private boolean isShown;
- private QSTileHost mHost;
private RecyclerView mRecyclerView;
private TileAdapter mTileAdapter;
private Toolbar mToolbar;
@@ -95,6 +95,7 @@ public class QSCustomizer extends LinearLayout implements OnMenuItemClickListene
KeyguardStateController keyguardStateController,
ScreenLifecycle screenLifecycle,
TileQueryHelper tileQueryHelper,
+ QSTileHost qsTileHost,
UiEventLogger uiEventLogger) {
super(new ContextThemeWrapper(context, R.style.edit_theme), attrs);
@@ -139,6 +140,8 @@ public class QSCustomizer extends LinearLayout implements OnMenuItemClickListene
mLightBarController = lightBarController;
mKeyguardStateController = keyguardStateController;
mScreenLifecycle = screenLifecycle;
+ mHost = qsTileHost;
+ mTileAdapter.setHost(mHost);
updateNavBackDrop(getResources().getConfiguration());
}
@@ -170,11 +173,6 @@ public class QSCustomizer extends LinearLayout implements OnMenuItemClickListene
mLightBarController.setQsCustomizing(mIsShowingNavBackdrop && isShown);
}
- public void setHost(QSTileHost host) {
- mHost = host;
- mTileAdapter.setHost(host);
- }
-
public void setContainer(NotificationsQuickSettingsContainer notificationsQsContainer) {
mNotifQsContainer = notificationsQsContainer;
}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/dagger/QSFragmentComponent.java b/packages/SystemUI/src/com/android/systemui/qs/dagger/QSFragmentComponent.java
new file mode 100644
index 000000000000..51b2c8dfffbd
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/qs/dagger/QSFragmentComponent.java
@@ -0,0 +1,55 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.qs.dagger;
+
+import com.android.systemui.qs.QSAnimator;
+import com.android.systemui.qs.QSContainerImplController;
+import com.android.systemui.qs.QSFooter;
+import com.android.systemui.qs.QSFragment;
+import com.android.systemui.qs.QSPanelController;
+import com.android.systemui.qs.QuickQSPanelController;
+
+import dagger.BindsInstance;
+import dagger.Subcomponent;
+
+/**
+ * Dagger Subcomponent for {@link QSFragment}.
+ */
+@Subcomponent(modules = {QSFragmentModule.class})
+@QSScope
+public interface QSFragmentComponent {
+ /** Factory for building a {@link QSFragmentComponent}. */
+ @Subcomponent.Factory
+ interface Factory {
+ QSFragmentComponent create(@BindsInstance QSFragment qsFragment);
+ }
+
+ /** Construct a {@link QSPanelController}. */
+ QSPanelController getQSPanelController();
+
+ /** Construct a {@link QuickQSPanelController}. */
+ QuickQSPanelController getQuickQSPanelController();
+
+ /** Construct a {@link QSAnimator}. */
+ QSAnimator getQSAnimator();
+
+ /** Construct a {@link QSContainerImplController}. */
+ QSContainerImplController getQSContainerImplController();
+
+ /** Construct a {@link QSFooter} */
+ QSFooter getQSFooter();
+}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/dagger/QSFragmentModule.java b/packages/SystemUI/src/com/android/systemui/qs/dagger/QSFragmentModule.java
new file mode 100644
index 000000000000..4bf4eff4c27e
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/qs/dagger/QSFragmentModule.java
@@ -0,0 +1,90 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.qs.dagger;
+
+import android.view.View;
+
+import com.android.systemui.R;
+import com.android.systemui.dagger.qualifiers.RootView;
+import com.android.systemui.plugins.qs.QS;
+import com.android.systemui.qs.QSContainerImpl;
+import com.android.systemui.qs.QSFooter;
+import com.android.systemui.qs.QSFooterView;
+import com.android.systemui.qs.QSFooterViewController;
+import com.android.systemui.qs.QSFragment;
+import com.android.systemui.qs.QSPanel;
+import com.android.systemui.qs.QuickQSPanel;
+import com.android.systemui.qs.QuickStatusBarHeader;
+
+import dagger.Binds;
+import dagger.Module;
+import dagger.Provides;
+
+/**
+ * Dagger Module for {@link QSFragmentComponent}.
+ */
+@Module
+public interface QSFragmentModule {
+ /** */
+ @Provides
+ @RootView
+ static View provideRootView(QSFragment qsFragment) {
+ return qsFragment.getView();
+ }
+
+ /** */
+ @Provides
+ static QSPanel provideQSPanel(@RootView View view) {
+ return view.findViewById(R.id.quick_settings_panel);
+ }
+
+ /** */
+ @Provides
+ static QSContainerImpl providesQSContainerImpl(@RootView View view) {
+ return view.findViewById(R.id.quick_settings_container);
+ }
+
+ /** */
+ @Binds
+ QS bindQS(QSFragment qsFragment);
+
+ /** */
+ @Provides
+ static QuickStatusBarHeader providesQuickStatusBarHeader(@RootView View view) {
+ return view.findViewById(R.id.header);
+ }
+
+ /** */
+ @Provides
+ static QuickQSPanel providesQuickQSPanel(QuickStatusBarHeader quickStatusBarHeader) {
+ return quickStatusBarHeader.findViewById(R.id.quick_qs_panel);
+ }
+
+ /** */
+ @Provides
+ static QSFooterView providesQSFooterView(@RootView View view) {
+ return view.findViewById(R.id.qs_footer);
+ }
+
+ /** */
+ @Provides
+ @QSScope
+ static QSFooter providesQSFooter(QSFooterViewController qsFooterViewController) {
+ qsFooterViewController.init();
+ return qsFooterViewController;
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/dagger/QSModule.java b/packages/SystemUI/src/com/android/systemui/qs/dagger/QSModule.java
index 953de6086ac7..7c799aefe90d 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/dagger/QSModule.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/dagger/QSModule.java
@@ -38,8 +38,8 @@ import dagger.Provides;
/**
* Module for QS dependencies
*/
-// TODO: Add other QS classes
-@Module(includes = {MediaModule.class})
+@Module(subcomponents = {QSFragmentComponent.class},
+ includes = {MediaModule.class})
public interface QSModule {
@Provides
@@ -60,7 +60,6 @@ public interface QSModule {
return manager;
}
-
/** */
@Binds
QSHost provideQsHost(QSTileHost controllerImpl);
diff --git a/packages/SystemUI/src/com/android/systemui/qs/dagger/QSScope.java b/packages/SystemUI/src/com/android/systemui/qs/dagger/QSScope.java
new file mode 100644
index 000000000000..f615eabb67dc
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/qs/dagger/QSScope.java
@@ -0,0 +1,32 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.qs.dagger;
+
+import static java.lang.annotation.RetentionPolicy.RUNTIME;
+
+import java.lang.annotation.Documented;
+import java.lang.annotation.Retention;
+
+import javax.inject.Scope;
+
+/**
+ * Scope annotation for singleton items within the {@link QSFragmentComponent}.
+ */
+@Documented
+@Retention(RUNTIME)
+@Scope
+public @interface QSScope {}
diff --git a/packages/SystemUI/src/com/android/systemui/screenshot/ActionProxyReceiver.java b/packages/SystemUI/src/com/android/systemui/screenshot/ActionProxyReceiver.java
index 3fd7f94514f3..5c26d9400c9f 100644
--- a/packages/SystemUI/src/com/android/systemui/screenshot/ActionProxyReceiver.java
+++ b/packages/SystemUI/src/com/android/systemui/screenshot/ActionProxyReceiver.java
@@ -16,12 +16,12 @@
package com.android.systemui.screenshot;
-import static com.android.systemui.screenshot.GlobalScreenshot.ACTION_TYPE_EDIT;
-import static com.android.systemui.screenshot.GlobalScreenshot.ACTION_TYPE_SHARE;
-import static com.android.systemui.screenshot.GlobalScreenshot.EXTRA_ACTION_INTENT;
-import static com.android.systemui.screenshot.GlobalScreenshot.EXTRA_DISALLOW_ENTER_PIP;
-import static com.android.systemui.screenshot.GlobalScreenshot.EXTRA_ID;
-import static com.android.systemui.screenshot.GlobalScreenshot.EXTRA_SMART_ACTIONS_ENABLED;
+import static com.android.systemui.screenshot.ScreenshotController.ACTION_TYPE_EDIT;
+import static com.android.systemui.screenshot.ScreenshotController.ACTION_TYPE_SHARE;
+import static com.android.systemui.screenshot.ScreenshotController.EXTRA_ACTION_INTENT;
+import static com.android.systemui.screenshot.ScreenshotController.EXTRA_DISALLOW_ENTER_PIP;
+import static com.android.systemui.screenshot.ScreenshotController.EXTRA_ID;
+import static com.android.systemui.screenshot.ScreenshotController.EXTRA_SMART_ACTIONS_ENABLED;
import static com.android.systemui.statusbar.phone.StatusBar.SYSTEM_DIALOG_REASON_SCREENSHOT;
import android.app.ActivityOptions;
diff --git a/packages/SystemUI/src/com/android/systemui/screenshot/DeleteScreenshotReceiver.java b/packages/SystemUI/src/com/android/systemui/screenshot/DeleteScreenshotReceiver.java
index 9028bb57c8e5..35839f39b491 100644
--- a/packages/SystemUI/src/com/android/systemui/screenshot/DeleteScreenshotReceiver.java
+++ b/packages/SystemUI/src/com/android/systemui/screenshot/DeleteScreenshotReceiver.java
@@ -16,10 +16,10 @@
package com.android.systemui.screenshot;
-import static com.android.systemui.screenshot.GlobalScreenshot.ACTION_TYPE_DELETE;
-import static com.android.systemui.screenshot.GlobalScreenshot.EXTRA_ID;
-import static com.android.systemui.screenshot.GlobalScreenshot.EXTRA_SMART_ACTIONS_ENABLED;
-import static com.android.systemui.screenshot.GlobalScreenshot.SCREENSHOT_URI_ID;
+import static com.android.systemui.screenshot.ScreenshotController.ACTION_TYPE_DELETE;
+import static com.android.systemui.screenshot.ScreenshotController.EXTRA_ID;
+import static com.android.systemui.screenshot.ScreenshotController.EXTRA_SMART_ACTIONS_ENABLED;
+import static com.android.systemui.screenshot.ScreenshotController.SCREENSHOT_URI_ID;
import android.content.BroadcastReceiver;
import android.content.ContentResolver;
diff --git a/packages/SystemUI/src/com/android/systemui/screenshot/GlobalScreenshot.java b/packages/SystemUI/src/com/android/systemui/screenshot/GlobalScreenshot.java
deleted file mode 100644
index 7d697539bf90..000000000000
--- a/packages/SystemUI/src/com/android/systemui/screenshot/GlobalScreenshot.java
+++ /dev/null
@@ -1,1191 +0,0 @@
-/*
- * Copyright (C) 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.systemui.screenshot;
-
-import static android.content.res.Configuration.ORIENTATION_LANDSCAPE;
-import static android.content.res.Configuration.ORIENTATION_PORTRAIT;
-import static android.view.WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;
-import static android.view.WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS;
-
-import android.animation.Animator;
-import android.animation.AnimatorListenerAdapter;
-import android.animation.AnimatorSet;
-import android.animation.ValueAnimator;
-import android.annotation.Nullable;
-import android.annotation.SuppressLint;
-import android.app.ActivityManager;
-import android.app.Notification;
-import android.app.PendingIntent;
-import android.content.ComponentName;
-import android.content.Context;
-import android.content.res.Configuration;
-import android.content.res.Resources;
-import android.graphics.Bitmap;
-import android.graphics.Color;
-import android.graphics.Insets;
-import android.graphics.Outline;
-import android.graphics.PixelFormat;
-import android.graphics.PointF;
-import android.graphics.Rect;
-import android.graphics.Region;
-import android.graphics.drawable.BitmapDrawable;
-import android.graphics.drawable.ColorDrawable;
-import android.graphics.drawable.Drawable;
-import android.graphics.drawable.Icon;
-import android.graphics.drawable.InsetDrawable;
-import android.graphics.drawable.LayerDrawable;
-import android.media.MediaActionSound;
-import android.net.Uri;
-import android.os.Handler;
-import android.os.IBinder;
-import android.os.Looper;
-import android.os.Message;
-import android.os.RemoteException;
-import android.provider.Settings;
-import android.util.DisplayMetrics;
-import android.util.Log;
-import android.util.MathUtils;
-import android.view.Display;
-import android.view.KeyEvent;
-import android.view.LayoutInflater;
-import android.view.MotionEvent;
-import android.view.SurfaceControl;
-import android.view.View;
-import android.view.ViewGroup;
-import android.view.ViewOutlineProvider;
-import android.view.ViewTreeObserver;
-import android.view.WindowInsets;
-import android.view.WindowManager;
-import android.view.accessibility.AccessibilityEvent;
-import android.view.accessibility.AccessibilityManager;
-import android.view.animation.AccelerateInterpolator;
-import android.view.animation.AnimationUtils;
-import android.view.animation.Interpolator;
-import android.widget.FrameLayout;
-import android.widget.HorizontalScrollView;
-import android.widget.ImageView;
-import android.widget.LinearLayout;
-import android.widget.Toast;
-
-import com.android.internal.logging.UiEventLogger;
-import com.android.systemui.R;
-import com.android.systemui.dagger.SysUISingleton;
-import com.android.systemui.dagger.qualifiers.Main;
-import com.android.systemui.shared.system.QuickStepContract;
-
-import java.util.ArrayList;
-import java.util.List;
-import java.util.function.Consumer;
-
-import javax.inject.Inject;
-
-/**
- * Class for handling device screen shots
- */
-@SysUISingleton
-public class GlobalScreenshot implements ViewTreeObserver.OnComputeInternalInsetsListener {
-
- /**
- * POD used in the AsyncTask which saves an image in the background.
- */
- static class SaveImageInBackgroundData {
- public Bitmap image;
- public Consumer<Uri> finisher;
- public GlobalScreenshot.ActionsReadyListener mActionsReadyListener;
-
- void clearImage() {
- image = null;
- }
- }
-
- /**
- * Structure returned by the SaveImageInBackgroundTask
- */
- static class SavedImageData {
- public Uri uri;
- public Notification.Action shareAction;
- public Notification.Action editAction;
- public Notification.Action deleteAction;
- public List<Notification.Action> smartActions;
-
- /**
- * Used to reset the return data on error
- */
- public void reset() {
- uri = null;
- shareAction = null;
- editAction = null;
- deleteAction = null;
- smartActions = null;
- }
- }
-
- abstract static class ActionsReadyListener {
- abstract void onActionsReady(SavedImageData imageData);
- }
-
- // These strings are used for communicating the action invoked to
- // ScreenshotNotificationSmartActionsProvider.
- static final String EXTRA_ACTION_TYPE = "android:screenshot_action_type";
- static final String EXTRA_ID = "android:screenshot_id";
- static final String ACTION_TYPE_DELETE = "Delete";
- static final String ACTION_TYPE_SHARE = "Share";
- static final String ACTION_TYPE_EDIT = "Edit";
- static final String EXTRA_SMART_ACTIONS_ENABLED = "android:smart_actions_enabled";
- static final String EXTRA_ACTION_INTENT = "android:screenshot_action_intent";
-
- static final String SCREENSHOT_URI_ID = "android:screenshot_uri_id";
- static final String EXTRA_CANCEL_NOTIFICATION = "android:screenshot_cancel_notification";
- static final String EXTRA_DISALLOW_ENTER_PIP = "android:screenshot_disallow_enter_pip";
-
- // From WizardManagerHelper.java
- private static final String SETTINGS_SECURE_USER_SETUP_COMPLETE = "user_setup_complete";
-
- private static final String TAG = "GlobalScreenshot";
-
- private static final long SCREENSHOT_FLASH_IN_DURATION_MS = 133;
- private static final long SCREENSHOT_FLASH_OUT_DURATION_MS = 217;
- // delay before starting to fade in dismiss button
- private static final long SCREENSHOT_TO_CORNER_DISMISS_DELAY_MS = 200;
- private static final long SCREENSHOT_TO_CORNER_X_DURATION_MS = 234;
- private static final long SCREENSHOT_TO_CORNER_Y_DURATION_MS = 500;
- private static final long SCREENSHOT_TO_CORNER_SCALE_DURATION_MS = 234;
- private static final long SCREENSHOT_ACTIONS_EXPANSION_DURATION_MS = 400;
- private static final long SCREENSHOT_ACTIONS_ALPHA_DURATION_MS = 100;
- private static final long SCREENSHOT_DISMISS_Y_DURATION_MS = 350;
- private static final long SCREENSHOT_DISMISS_ALPHA_DURATION_MS = 183;
- private static final long SCREENSHOT_DISMISS_ALPHA_OFFSET_MS = 50; // delay before starting fade
- private static final float SCREENSHOT_ACTIONS_START_SCALE_X = .7f;
- private static final float ROUNDED_CORNER_RADIUS = .05f;
- private static final int SCREENSHOT_CORNER_DEFAULT_TIMEOUT_MILLIS = 6000;
- private static final int MESSAGE_CORNER_TIMEOUT = 2;
-
- private final Interpolator mAccelerateInterpolator = new AccelerateInterpolator();
-
- private final ScreenshotNotificationsController mNotificationsController;
- private final UiEventLogger mUiEventLogger;
-
- private final Context mContext;
- private final ScreenshotSmartActions mScreenshotSmartActions;
- private final WindowManager mWindowManager;
- private final WindowManager.LayoutParams mWindowLayoutParams;
- private final Display mDisplay;
- private final DisplayMetrics mDisplayMetrics;
- private final AccessibilityManager mAccessibilityManager;
-
- private View mScreenshotLayout;
- private ScreenshotSelectorView mScreenshotSelectorView;
- private ImageView mScreenshotAnimatedView;
- private ImageView mScreenshotPreview;
- private ImageView mScreenshotFlash;
- private ImageView mActionsContainerBackground;
- private HorizontalScrollView mActionsContainer;
- private LinearLayout mActionsView;
- private ScreenshotActionChip mShareChip;
- private ScreenshotActionChip mEditChip;
- private ImageView mBackgroundProtection;
- private FrameLayout mDismissButton;
-
- private Bitmap mScreenBitmap;
- private SaveImageInBackgroundTask mSaveInBgTask;
- private Animator mScreenshotAnimation;
- private Runnable mOnCompleteRunnable;
- private Animator mDismissAnimation;
- private boolean mInDarkMode;
- private boolean mDirectionLTR;
- private boolean mOrientationPortrait;
-
- private float mCornerSizeX;
- private float mDismissDeltaY;
-
- private MediaActionSound mCameraSound;
-
- private int mNavMode;
- private int mLeftInset;
- private int mRightInset;
-
- private ArrayList<ScreenshotActionChip> mSmartChips = new ArrayList<>();
- private PendingInteraction mPendingInteraction;
- private enum PendingInteraction {
- PREVIEW,
- EDIT,
- SHARE
- }
-
- // standard material ease
- private final Interpolator mFastOutSlowIn;
-
- private final Handler mScreenshotHandler = new Handler(Looper.getMainLooper()) {
- @Override
- public void handleMessage(Message msg) {
- switch (msg.what) {
- case MESSAGE_CORNER_TIMEOUT:
- mUiEventLogger.log(ScreenshotEvent.SCREENSHOT_INTERACTION_TIMEOUT);
- GlobalScreenshot.this.dismissScreenshot("timeout", false);
- mOnCompleteRunnable.run();
- break;
- default:
- break;
- }
- }
- };
-
- @Inject
- public GlobalScreenshot(
- Context context, @Main Resources resources,
- ScreenshotSmartActions screenshotSmartActions,
- ScreenshotNotificationsController screenshotNotificationsController,
- UiEventLogger uiEventLogger) {
- mContext = context;
- mScreenshotSmartActions = screenshotSmartActions;
- mNotificationsController = screenshotNotificationsController;
- mUiEventLogger = uiEventLogger;
- mAccessibilityManager = AccessibilityManager.getInstance(mContext);
-
- reloadAssets();
- Configuration config = mContext.getResources().getConfiguration();
- mInDarkMode = config.isNightModeActive();
- mDirectionLTR = config.getLayoutDirection() == View.LAYOUT_DIRECTION_LTR;
- mOrientationPortrait = config.orientation == ORIENTATION_PORTRAIT;
-
- // Setup the window that we are going to use
- mWindowLayoutParams = new WindowManager.LayoutParams(
- ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT, 0, 0,
- WindowManager.LayoutParams.TYPE_SCREENSHOT,
- WindowManager.LayoutParams.FLAG_FULLSCREEN
- | WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN
- | WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL
- | WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH
- | WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED
- | WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM,
- PixelFormat.TRANSLUCENT);
- mWindowLayoutParams.setTitle("ScreenshotAnimation");
- mWindowLayoutParams.layoutInDisplayCutoutMode = LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS;
- mWindowLayoutParams.setFitInsetsTypes(0 /* types */);
- mWindowManager = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
- mDisplay = mWindowManager.getDefaultDisplay();
- mDisplayMetrics = new DisplayMetrics();
- mDisplay.getRealMetrics(mDisplayMetrics);
-
- mCornerSizeX = resources.getDimensionPixelSize(R.dimen.global_screenshot_x_scale);
- mDismissDeltaY = resources.getDimensionPixelSize(R.dimen.screenshot_dismissal_height_delta);
-
- mFastOutSlowIn =
- AnimationUtils.loadInterpolator(mContext, android.R.interpolator.fast_out_slow_in);
-
- // Setup the Camera shutter sound
- mCameraSound = new MediaActionSound();
- mCameraSound.load(MediaActionSound.SHUTTER_CLICK);
- }
-
- @Override // ViewTreeObserver.OnComputeInternalInsetsListener
- public void onComputeInternalInsets(ViewTreeObserver.InternalInsetsInfo inoutInfo) {
- inoutInfo.setTouchableInsets(ViewTreeObserver.InternalInsetsInfo.TOUCHABLE_INSETS_REGION);
- Region touchRegion = new Region();
-
- Rect screenshotRect = new Rect();
- mScreenshotPreview.getBoundsOnScreen(screenshotRect);
- touchRegion.op(screenshotRect, Region.Op.UNION);
- Rect actionsRect = new Rect();
- mActionsContainer.getBoundsOnScreen(actionsRect);
- touchRegion.op(actionsRect, Region.Op.UNION);
- Rect dismissRect = new Rect();
- mDismissButton.getBoundsOnScreen(dismissRect);
- touchRegion.op(dismissRect, Region.Op.UNION);
-
- if (QuickStepContract.isGesturalMode(mNavMode)) {
- // Receive touches in gesture insets such that they don't cause TOUCH_OUTSIDE
- Rect inset = new Rect(0, 0, mLeftInset, mDisplayMetrics.heightPixels);
- touchRegion.op(inset, Region.Op.UNION);
- inset.set(mDisplayMetrics.widthPixels - mRightInset, 0, mDisplayMetrics.widthPixels,
- mDisplayMetrics.heightPixels);
- touchRegion.op(inset, Region.Op.UNION);
- }
-
- inoutInfo.touchableRegion.set(touchRegion);
- }
-
- void takeScreenshotFullscreen(Consumer<Uri> finisher, Runnable onComplete) {
- mOnCompleteRunnable = onComplete;
-
- mDisplay.getRealMetrics(mDisplayMetrics);
- takeScreenshotInternal(
- finisher,
- new Rect(0, 0, mDisplayMetrics.widthPixels, mDisplayMetrics.heightPixels));
- }
-
- void handleImageAsScreenshot(Bitmap screenshot, Rect screenshotScreenBounds,
- Insets visibleInsets, int taskId, int userId, ComponentName topComponent,
- Consumer<Uri> finisher, Runnable onComplete) {
- // TODO: use task Id, userId, topComponent for smart handler
- mOnCompleteRunnable = onComplete;
-
- if (screenshot == null) {
- Log.e(TAG, "Got null bitmap from screenshot message");
- mNotificationsController.notifyScreenshotError(
- R.string.screenshot_failed_to_capture_text);
- finisher.accept(null);
- mOnCompleteRunnable.run();
- return;
- }
-
- if (aspectRatiosMatch(screenshot, visibleInsets, screenshotScreenBounds)) {
- saveScreenshot(screenshot, finisher, screenshotScreenBounds, visibleInsets, false);
- } else {
- saveScreenshot(screenshot, finisher,
- new Rect(0, 0, screenshot.getWidth(), screenshot.getHeight()), Insets.NONE,
- true);
- }
- }
-
- /**
- * Displays a screenshot selector
- */
- @SuppressLint("ClickableViewAccessibility")
- void takeScreenshotPartial(final Consumer<Uri> finisher, Runnable onComplete) {
- dismissScreenshot("new screenshot requested", true);
- mOnCompleteRunnable = onComplete;
-
- mWindowManager.addView(mScreenshotLayout, mWindowLayoutParams);
- mScreenshotSelectorView.setOnTouchListener((v, event) -> {
- ScreenshotSelectorView view = (ScreenshotSelectorView) v;
- switch (event.getAction()) {
- case MotionEvent.ACTION_DOWN:
- view.startSelection((int) event.getX(), (int) event.getY());
- return true;
- case MotionEvent.ACTION_MOVE:
- view.updateSelection((int) event.getX(), (int) event.getY());
- return true;
- case MotionEvent.ACTION_UP:
- view.setVisibility(View.GONE);
- mWindowManager.removeView(mScreenshotLayout);
- final Rect rect = view.getSelectionRect();
- if (rect != null) {
- if (rect.width() != 0 && rect.height() != 0) {
- // Need mScreenshotLayout to handle it after the view disappears
- mScreenshotLayout.post(() -> takeScreenshotInternal(finisher, rect));
- }
- }
-
- view.stopSelection();
- return true;
- }
-
- return false;
- });
- mScreenshotLayout.post(() -> {
- mScreenshotSelectorView.setVisibility(View.VISIBLE);
- mScreenshotSelectorView.requestFocus();
- });
- }
-
- /**
- * Cancels screenshot request
- */
- void stopScreenshot() {
- // If the selector layer still presents on screen, we remove it and resets its state.
- if (mScreenshotSelectorView.getSelectionRect() != null) {
- mWindowManager.removeView(mScreenshotLayout);
- mScreenshotSelectorView.stopSelection();
- }
- }
-
- /**
- * Clears current screenshot
- */
- void dismissScreenshot(String reason, boolean immediate) {
- Log.v(TAG, "clearing screenshot: " + reason);
- mScreenshotHandler.removeMessages(MESSAGE_CORNER_TIMEOUT);
- mScreenshotLayout.getViewTreeObserver().removeOnComputeInternalInsetsListener(this);
- if (!immediate) {
- mDismissAnimation = createScreenshotDismissAnimation();
- mDismissAnimation.addListener(new AnimatorListenerAdapter() {
- @Override
- public void onAnimationEnd(Animator animation) {
- super.onAnimationEnd(animation);
- clearScreenshot();
- }
- });
- mDismissAnimation.start();
- } else {
- clearScreenshot();
- }
- }
-
- private void onConfigChanged(Configuration newConfig) {
- boolean needsUpdate = false;
- // dark mode
- if (newConfig.isNightModeActive()) {
- // Night mode is active, we're using dark theme
- if (!mInDarkMode) {
- mInDarkMode = true;
- needsUpdate = true;
- }
- } else {
- // Night mode is not active, we're using the light theme
- if (mInDarkMode) {
- mInDarkMode = false;
- needsUpdate = true;
- }
- }
-
- // RTL configuration
- switch (newConfig.getLayoutDirection()) {
- case View.LAYOUT_DIRECTION_LTR:
- if (!mDirectionLTR) {
- mDirectionLTR = true;
- needsUpdate = true;
- }
- break;
- case View.LAYOUT_DIRECTION_RTL:
- if (mDirectionLTR) {
- mDirectionLTR = false;
- needsUpdate = true;
- }
- break;
- }
-
- // portrait/landscape orientation
- switch (newConfig.orientation) {
- case ORIENTATION_PORTRAIT:
- if (!mOrientationPortrait) {
- mOrientationPortrait = true;
- needsUpdate = true;
- }
- break;
- case ORIENTATION_LANDSCAPE:
- if (mOrientationPortrait) {
- mOrientationPortrait = false;
- needsUpdate = true;
- }
- break;
- }
-
- if (needsUpdate) {
- reloadAssets();
- }
-
- mNavMode = mContext.getResources().getInteger(
- com.android.internal.R.integer.config_navBarInteractionMode);
- }
-
- /**
- * Update assets (called when the dark theme status changes). We only need to update the dismiss
- * button and the actions container background, since the buttons are re-inflated on demand.
- */
- private void reloadAssets() {
- boolean wasAttached = mScreenshotLayout != null && mScreenshotLayout.isAttachedToWindow();
- if (wasAttached) {
- mWindowManager.removeView(mScreenshotLayout);
- }
-
- // Inflate the screenshot layout
- mScreenshotLayout = LayoutInflater.from(mContext).inflate(R.layout.global_screenshot, null);
- // TODO(159460485): Remove this when focus is handled properly in the system
- mScreenshotLayout.setOnTouchListener((v, event) -> {
- if (event.getActionMasked() == MotionEvent.ACTION_OUTSIDE) {
- // Once the user touches outside, stop listening for input
- setWindowFocusable(false);
- }
- return false;
- });
- mScreenshotLayout.setOnApplyWindowInsetsListener((v, insets) -> {
- if (QuickStepContract.isGesturalMode(mNavMode)) {
- Insets gestureInsets = insets.getInsets(
- WindowInsets.Type.systemGestures());
- mLeftInset = gestureInsets.left;
- mRightInset = gestureInsets.right;
- } else {
- mLeftInset = mRightInset = 0;
- }
- return mScreenshotLayout.onApplyWindowInsets(insets);
- });
- mScreenshotLayout.setOnKeyListener((v, keyCode, event) -> {
- if (keyCode == KeyEvent.KEYCODE_BACK) {
- dismissScreenshot("back pressed", false);
- return true;
- }
- return false;
- });
- // Get focus so that the key events go to the layout.
- mScreenshotLayout.setFocusableInTouchMode(true);
- mScreenshotLayout.requestFocus();
-
- mScreenshotAnimatedView =
- mScreenshotLayout.findViewById(R.id.global_screenshot_animated_view);
- mScreenshotAnimatedView.setClipToOutline(true);
- mScreenshotAnimatedView.setOutlineProvider(new ViewOutlineProvider() {
- @Override
- public void getOutline(View view, Outline outline) {
- outline.setRoundRect(new Rect(0, 0, view.getWidth(), view.getHeight()),
- ROUNDED_CORNER_RADIUS * view.getWidth());
- }
- });
- mScreenshotPreview = mScreenshotLayout.findViewById(R.id.global_screenshot_preview);
- mScreenshotPreview.setClipToOutline(true);
- mScreenshotPreview.setOutlineProvider(new ViewOutlineProvider() {
- @Override
- public void getOutline(View view, Outline outline) {
- outline.setRoundRect(new Rect(0, 0, view.getWidth(), view.getHeight()),
- ROUNDED_CORNER_RADIUS * view.getWidth());
- }
- });
-
- mActionsContainerBackground = mScreenshotLayout.findViewById(
- R.id.global_screenshot_actions_container_background);
- mActionsContainer = mScreenshotLayout.findViewById(
- R.id.global_screenshot_actions_container);
- mActionsView = mScreenshotLayout.findViewById(R.id.global_screenshot_actions);
- mBackgroundProtection = mScreenshotLayout.findViewById(
- R.id.global_screenshot_actions_background);
- mDismissButton = mScreenshotLayout.findViewById(R.id.global_screenshot_dismiss_button);
- mDismissButton.setOnClickListener(view -> {
- mUiEventLogger.log(ScreenshotEvent.SCREENSHOT_EXPLICIT_DISMISSAL);
- dismissScreenshot("dismiss_button", false);
- mOnCompleteRunnable.run();
- });
-
- mShareChip = mActionsContainer.findViewById(R.id.screenshot_share_chip);
- mEditChip = mActionsContainer.findViewById(R.id.screenshot_edit_chip);
-
- mScreenshotFlash = mScreenshotLayout.findViewById(R.id.global_screenshot_flash);
- mScreenshotSelectorView = mScreenshotLayout.findViewById(R.id.global_screenshot_selector);
- mScreenshotLayout.setFocusable(true);
- mScreenshotSelectorView.setFocusable(true);
- mScreenshotSelectorView.setFocusableInTouchMode(true);
- mScreenshotAnimatedView.setPivotX(0);
- mScreenshotAnimatedView.setPivotY(0);
- mActionsContainer.setScrollX(0);
-
- if (wasAttached) {
- mWindowManager.addView(mScreenshotLayout, mWindowLayoutParams);
- }
- }
-
- /**
- * Takes a screenshot of the current display and shows an animation.
- */
- private void takeScreenshotInternal(Consumer<Uri> finisher, Rect crop) {
- // copy the input Rect, since SurfaceControl.screenshot can mutate it
- Rect screenRect = new Rect(crop);
- int width = crop.width();
- int height = crop.height();
- final IBinder displayToken = SurfaceControl.getInternalDisplayToken();
- final SurfaceControl.DisplayCaptureArgs captureArgs =
- new SurfaceControl.DisplayCaptureArgs.Builder(displayToken)
- .setSourceCrop(crop)
- .setSize(width, height)
- .build();
- final SurfaceControl.ScreenshotHardwareBuffer screenshotBuffer =
- SurfaceControl.captureDisplay(captureArgs);
- Bitmap screenshot = screenshotBuffer == null ? null : screenshotBuffer.asBitmap();
-
- if (screenshot == null) {
- Log.e(TAG, "Screenshot bitmap was null");
- mNotificationsController.notifyScreenshotError(
- R.string.screenshot_failed_to_capture_text);
- finisher.accept(null);
- mOnCompleteRunnable.run();
- return;
- }
-
- saveScreenshot(screenshot, finisher, screenRect, Insets.NONE, true);
- }
-
- private void saveScreenshot(Bitmap screenshot, Consumer<Uri> finisher, Rect screenRect,
- Insets screenInsets, boolean showFlash) {
- if (mAccessibilityManager.isEnabled()) {
- AccessibilityEvent event =
- new AccessibilityEvent(AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED);
- event.setContentDescription(
- mContext.getResources().getString(R.string.screenshot_saving_title));
- mAccessibilityManager.sendAccessibilityEvent(event);
- }
-
- if (mScreenshotLayout.isAttachedToWindow()) {
- // if we didn't already dismiss for another reason
- if (mDismissAnimation == null || !mDismissAnimation.isRunning()) {
- mUiEventLogger.log(ScreenshotEvent.SCREENSHOT_REENTERED);
- }
- dismissScreenshot("new screenshot requested", true);
- }
-
- mScreenBitmap = screenshot;
-
- if (!isUserSetupComplete()) {
- // User setup isn't complete, so we don't want to show any UI beyond a toast, as editing
- // and sharing shouldn't be exposed to the user.
- saveScreenshotAndToast(finisher);
- return;
- }
-
- // Optimizations
- mScreenBitmap.setHasAlpha(false);
- mScreenBitmap.prepareToDraw();
-
- onConfigChanged(mContext.getResources().getConfiguration());
-
- if (mDismissAnimation != null && mDismissAnimation.isRunning()) {
- mDismissAnimation.cancel();
- }
-
- // The window is focusable by default
- setWindowFocusable(true);
-
- // Start the post-screenshot animation
- startAnimation(finisher, screenRect, screenInsets, showFlash);
- }
-
- /**
- * Save the bitmap but don't show the normal screenshot UI.. just a toast (or notification on
- * failure).
- */
- private void saveScreenshotAndToast(Consumer<Uri> finisher) {
- // Play the shutter sound to notify that we've taken a screenshot
- mScreenshotHandler.post(() -> {
- mCameraSound.play(MediaActionSound.SHUTTER_CLICK);
- });
-
- saveScreenshotInWorkerThread(finisher, new ActionsReadyListener() {
- @Override
- void onActionsReady(SavedImageData imageData) {
- finisher.accept(imageData.uri);
- if (imageData.uri == null) {
- mUiEventLogger.log(ScreenshotEvent.SCREENSHOT_NOT_SAVED);
- mNotificationsController.notifyScreenshotError(
- R.string.screenshot_failed_to_save_text);
- } else {
- mUiEventLogger.log(ScreenshotEvent.SCREENSHOT_SAVED);
-
- mScreenshotHandler.post(() -> {
- Toast.makeText(mContext, R.string.screenshot_saved_title,
- Toast.LENGTH_SHORT).show();
- });
- }
- }
- });
- }
-
- /**
- * Starts the animation after taking the screenshot
- */
- private void startAnimation(final Consumer<Uri> finisher, Rect screenRect, Insets screenInsets,
- boolean showFlash) {
- mScreenshotHandler.post(() -> {
- if (!mScreenshotLayout.isAttachedToWindow()) {
- mWindowManager.addView(mScreenshotLayout, mWindowLayoutParams);
- }
- mScreenshotAnimatedView.setImageDrawable(
- createScreenDrawable(mScreenBitmap, screenInsets));
- setAnimatedViewSize(screenRect.width(), screenRect.height());
- // Show when the animation starts
- mScreenshotAnimatedView.setVisibility(View.GONE);
-
- mScreenshotPreview.setImageDrawable(createScreenDrawable(mScreenBitmap, screenInsets));
- // make static preview invisible (from gone) so we can query its location on screen
- mScreenshotPreview.setVisibility(View.INVISIBLE);
-
- mScreenshotHandler.post(() -> {
- mScreenshotLayout.getViewTreeObserver().addOnComputeInternalInsetsListener(this);
-
- mScreenshotAnimation =
- createScreenshotDropInAnimation(screenRect, showFlash);
-
- saveScreenshotInWorkerThread(finisher, new ActionsReadyListener() {
- @Override
- void onActionsReady(SavedImageData imageData) {
- showUiOnActionsReady(imageData);
- }
- });
-
- // Play the shutter sound to notify that we've taken a screenshot
- mCameraSound.play(MediaActionSound.SHUTTER_CLICK);
-
- mScreenshotPreview.setLayerType(View.LAYER_TYPE_HARDWARE, null);
- mScreenshotPreview.buildLayer();
- mScreenshotAnimation.start();
- });
- });
- }
-
- /**
- * Creates a new worker thread and saves the screenshot to the media store.
- */
- private void saveScreenshotInWorkerThread(
- Consumer<Uri> finisher, @Nullable ActionsReadyListener actionsReadyListener) {
- SaveImageInBackgroundData data = new SaveImageInBackgroundData();
- data.image = mScreenBitmap;
- data.finisher = finisher;
- data.mActionsReadyListener = actionsReadyListener;
-
- if (mSaveInBgTask != null) {
- // just log success/failure for the pre-existing screenshot
- mSaveInBgTask.setActionsReadyListener(new ActionsReadyListener() {
- @Override
- void onActionsReady(SavedImageData imageData) {
- logSuccessOnActionsReady(imageData);
- }
- });
- }
-
- mSaveInBgTask = new SaveImageInBackgroundTask(mContext, mScreenshotSmartActions, data);
- mSaveInBgTask.execute();
- }
-
- /**
- * Sets up the action shade and its entrance animation, once we get the screenshot URI.
- */
- private void showUiOnActionsReady(SavedImageData imageData) {
- logSuccessOnActionsReady(imageData);
-
- AccessibilityManager accessibilityManager = (AccessibilityManager)
- mContext.getSystemService(Context.ACCESSIBILITY_SERVICE);
- long timeoutMs = accessibilityManager.getRecommendedTimeoutMillis(
- SCREENSHOT_CORNER_DEFAULT_TIMEOUT_MILLIS,
- AccessibilityManager.FLAG_CONTENT_CONTROLS);
-
- mScreenshotHandler.removeMessages(MESSAGE_CORNER_TIMEOUT);
- mScreenshotHandler.sendMessageDelayed(
- mScreenshotHandler.obtainMessage(MESSAGE_CORNER_TIMEOUT),
- timeoutMs);
-
- if (imageData.uri != null) {
- mScreenshotHandler.post(() -> {
- if (mScreenshotAnimation != null && mScreenshotAnimation.isRunning()) {
- mScreenshotAnimation.addListener(new AnimatorListenerAdapter() {
- @Override
- public void onAnimationEnd(Animator animation) {
- super.onAnimationEnd(animation);
- setChipIntents(imageData);
- }
- });
- } else {
- setChipIntents(imageData);
- }
- });
- }
- }
-
- /**
- * Logs success/failure of the screenshot saving task, and shows an error if it failed.
- */
- private void logSuccessOnActionsReady(SavedImageData imageData) {
- if (imageData.uri == null) {
- mUiEventLogger.log(ScreenshotEvent.SCREENSHOT_NOT_SAVED);
- mNotificationsController.notifyScreenshotError(
- R.string.screenshot_failed_to_save_text);
- } else {
- mUiEventLogger.log(ScreenshotEvent.SCREENSHOT_SAVED);
- }
- }
-
- private AnimatorSet createScreenshotDropInAnimation(Rect bounds, boolean showFlash) {
- Rect previewBounds = new Rect();
- mScreenshotPreview.getBoundsOnScreen(previewBounds);
-
- float cornerScale =
- mCornerSizeX / (mOrientationPortrait ? bounds.width() : bounds.height());
- final float currentScale = 1f;
-
- mScreenshotAnimatedView.setScaleX(currentScale);
- mScreenshotAnimatedView.setScaleY(currentScale);
-
- mDismissButton.setAlpha(0);
- mDismissButton.setVisibility(View.VISIBLE);
-
- AnimatorSet dropInAnimation = new AnimatorSet();
- ValueAnimator flashInAnimator = ValueAnimator.ofFloat(0, 1);
- flashInAnimator.setDuration(SCREENSHOT_FLASH_IN_DURATION_MS);
- flashInAnimator.setInterpolator(mFastOutSlowIn);
- flashInAnimator.addUpdateListener(animation ->
- mScreenshotFlash.setAlpha((float) animation.getAnimatedValue()));
-
- ValueAnimator flashOutAnimator = ValueAnimator.ofFloat(1, 0);
- flashOutAnimator.setDuration(SCREENSHOT_FLASH_OUT_DURATION_MS);
- flashOutAnimator.setInterpolator(mFastOutSlowIn);
- flashOutAnimator.addUpdateListener(animation ->
- mScreenshotFlash.setAlpha((float) animation.getAnimatedValue()));
-
- // animate from the current location, to the static preview location
- final PointF startPos = new PointF(bounds.centerX(), bounds.centerY());
- final PointF finalPos = new PointF(previewBounds.centerX(), previewBounds.centerY());
-
- ValueAnimator toCorner = ValueAnimator.ofFloat(0, 1);
- toCorner.setDuration(SCREENSHOT_TO_CORNER_Y_DURATION_MS);
- float xPositionPct =
- SCREENSHOT_TO_CORNER_X_DURATION_MS / (float) SCREENSHOT_TO_CORNER_Y_DURATION_MS;
- float dismissPct =
- SCREENSHOT_TO_CORNER_DISMISS_DELAY_MS / (float) SCREENSHOT_TO_CORNER_Y_DURATION_MS;
- float scalePct =
- SCREENSHOT_TO_CORNER_SCALE_DURATION_MS / (float) SCREENSHOT_TO_CORNER_Y_DURATION_MS;
- toCorner.addUpdateListener(animation -> {
- float t = animation.getAnimatedFraction();
- if (t < scalePct) {
- float scale = MathUtils.lerp(
- currentScale, cornerScale, mFastOutSlowIn.getInterpolation(t / scalePct));
- mScreenshotAnimatedView.setScaleX(scale);
- mScreenshotAnimatedView.setScaleY(scale);
- } else {
- mScreenshotAnimatedView.setScaleX(cornerScale);
- mScreenshotAnimatedView.setScaleY(cornerScale);
- }
-
- float currentScaleX = mScreenshotAnimatedView.getScaleX();
- float currentScaleY = mScreenshotAnimatedView.getScaleY();
-
- if (t < xPositionPct) {
- float xCenter = MathUtils.lerp(startPos.x, finalPos.x,
- mFastOutSlowIn.getInterpolation(t / xPositionPct));
- mScreenshotAnimatedView.setX(xCenter - bounds.width() * currentScaleX / 2f);
- } else {
- mScreenshotAnimatedView.setX(finalPos.x - bounds.width() * currentScaleX / 2f);
- }
- float yCenter = MathUtils.lerp(
- startPos.y, finalPos.y, mFastOutSlowIn.getInterpolation(t));
- mScreenshotAnimatedView.setY(yCenter - bounds.height() * currentScaleY / 2f);
-
- if (t >= dismissPct) {
- mDismissButton.setAlpha((t - dismissPct) / (1 - dismissPct));
- float currentX = mScreenshotAnimatedView.getX();
- float currentY = mScreenshotAnimatedView.getY();
- mDismissButton.setY(currentY - mDismissButton.getHeight() / 2f);
- if (mDirectionLTR) {
- mDismissButton.setX(currentX
- + bounds.width() * currentScaleX - mDismissButton.getWidth() / 2f);
- } else {
- mDismissButton.setX(currentX - mDismissButton.getWidth() / 2f);
- }
- }
- });
-
- toCorner.addListener(new AnimatorListenerAdapter() {
- @Override
- public void onAnimationStart(Animator animation) {
- super.onAnimationStart(animation);
- mScreenshotAnimatedView.setVisibility(View.VISIBLE);
- }
- });
-
- mScreenshotFlash.setAlpha(0f);
- mScreenshotFlash.setVisibility(View.VISIBLE);
-
- if (showFlash) {
- dropInAnimation.play(flashOutAnimator).after(flashInAnimator);
- dropInAnimation.play(flashOutAnimator).with(toCorner);
- } else {
- dropInAnimation.play(toCorner);
- }
-
- dropInAnimation.addListener(new AnimatorListenerAdapter() {
- @Override
- public void onAnimationEnd(Animator animation) {
- super.onAnimationEnd(animation);
- mDismissButton.setAlpha(1);
- float dismissOffset = mDismissButton.getWidth() / 2f;
- float finalDismissX = mDirectionLTR
- ? finalPos.x - dismissOffset + bounds.width() * cornerScale / 2f
- : finalPos.x - dismissOffset - bounds.width() * cornerScale / 2f;
- mDismissButton.setX(finalDismissX);
- mDismissButton.setY(
- finalPos.y - dismissOffset - bounds.height() * cornerScale / 2f);
- mScreenshotAnimatedView.setScaleX(1);
- mScreenshotAnimatedView.setScaleY(1);
- mScreenshotAnimatedView.setX(finalPos.x - bounds.width() * cornerScale / 2f);
- mScreenshotAnimatedView.setY(finalPos.y - bounds.height() * cornerScale / 2f);
- mScreenshotAnimatedView.setVisibility(View.GONE);
- mScreenshotPreview.setVisibility(View.VISIBLE);
- mScreenshotLayout.forceLayout();
- createScreenshotActionsShadeAnimation().start();
- }
- });
-
- return dropInAnimation;
- }
-
- private ValueAnimator createScreenshotActionsShadeAnimation() {
- // By default the activities won't be able to start immediately; override this to keep
- // the same behavior as if started from a notification
- try {
- ActivityManager.getService().resumeAppSwitches();
- } catch (RemoteException e) {
- }
-
- ArrayList<ScreenshotActionChip> chips = new ArrayList<>();
-
- mShareChip.setText(mContext.getString(com.android.internal.R.string.share));
- mShareChip.setIcon(Icon.createWithResource(mContext, R.drawable.ic_screenshot_share), true);
- mShareChip.setOnClickListener(v -> {
- mShareChip.setIsPending(true);
- mEditChip.setIsPending(false);
- mPendingInteraction = PendingInteraction.SHARE;
- });
- chips.add(mShareChip);
-
- mEditChip.setText(mContext.getString(com.android.internal.R.string.screenshot_edit));
- mEditChip.setIcon(Icon.createWithResource(mContext, R.drawable.ic_screenshot_edit), true);
- mEditChip.setOnClickListener(v -> {
- mEditChip.setIsPending(true);
- mShareChip.setIsPending(false);
- mPendingInteraction = PendingInteraction.EDIT;
- });
- chips.add(mEditChip);
-
- mScreenshotPreview.setOnClickListener(v -> {
- mShareChip.setIsPending(false);
- mEditChip.setIsPending(false);
- mPendingInteraction = PendingInteraction.PREVIEW;
- });
-
- // remove the margin from the last chip so that it's correctly aligned with the end
- LinearLayout.LayoutParams params = (LinearLayout.LayoutParams)
- mActionsView.getChildAt(0).getLayoutParams();
- params.setMarginStart(0);
- mActionsView.getChildAt(0).setLayoutParams(params);
-
- ValueAnimator animator = ValueAnimator.ofFloat(0, 1);
- animator.setDuration(SCREENSHOT_ACTIONS_EXPANSION_DURATION_MS);
- float alphaFraction = (float) SCREENSHOT_ACTIONS_ALPHA_DURATION_MS
- / SCREENSHOT_ACTIONS_EXPANSION_DURATION_MS;
- mActionsContainer.setAlpha(0f);
- mActionsContainerBackground.setAlpha(0f);
- mActionsContainer.setVisibility(View.VISIBLE);
- mActionsContainerBackground.setVisibility(View.VISIBLE);
-
- animator.addUpdateListener(animation -> {
- float t = animation.getAnimatedFraction();
- mBackgroundProtection.setAlpha(t);
- float containerAlpha = t < alphaFraction ? t / alphaFraction : 1;
- mActionsContainer.setAlpha(containerAlpha);
- mActionsContainerBackground.setAlpha(containerAlpha);
- float containerScale = SCREENSHOT_ACTIONS_START_SCALE_X
- + (t * (1 - SCREENSHOT_ACTIONS_START_SCALE_X));
- mActionsContainer.setScaleX(containerScale);
- mActionsContainerBackground.setScaleX(containerScale);
- for (ScreenshotActionChip chip : chips) {
- chip.setAlpha(t);
- chip.setScaleX(1 / containerScale); // invert to keep size of children constant
- }
- mActionsContainer.setScrollX(mDirectionLTR ? 0 : mActionsContainer.getWidth());
- mActionsContainer.setPivotX(mDirectionLTR ? 0 : mActionsContainer.getWidth());
- mActionsContainerBackground.setPivotX(
- mDirectionLTR ? 0 : mActionsContainerBackground.getWidth());
- });
- return animator;
- }
-
- private void setChipIntents(SavedImageData imageData) {
- mShareChip.setPendingIntent(imageData.shareAction.actionIntent, () -> {
- mUiEventLogger.log(ScreenshotEvent.SCREENSHOT_SHARE_TAPPED);
- dismissScreenshot("chip tapped", false);
- mOnCompleteRunnable.run();
- });
-
- mEditChip.setPendingIntent(imageData.editAction.actionIntent, () -> {
- mUiEventLogger.log(ScreenshotEvent.SCREENSHOT_EDIT_TAPPED);
- dismissScreenshot("chip tapped", false);
- mOnCompleteRunnable.run();
- });
-
- mScreenshotPreview.setOnClickListener(v -> {
- try {
- imageData.editAction.actionIntent.send();
- mUiEventLogger.log(ScreenshotEvent.SCREENSHOT_PREVIEW_TAPPED);
- dismissScreenshot("screenshot preview tapped", false);
- mOnCompleteRunnable.run();
- } catch (PendingIntent.CanceledException e) {
- Log.e(TAG, "Intent cancelled", e);
- }
- });
-
- if (mPendingInteraction != null) {
- switch(mPendingInteraction) {
- case PREVIEW:
- mScreenshotPreview.callOnClick();
- break;
- case SHARE:
- mShareChip.callOnClick();
- break;
- case EDIT:
- mEditChip.callOnClick();
- break;
- }
- } else {
- LayoutInflater inflater = LayoutInflater.from(mContext);
-
- for (Notification.Action smartAction : imageData.smartActions) {
- ScreenshotActionChip actionChip = (ScreenshotActionChip) inflater.inflate(
- R.layout.global_screenshot_action_chip, mActionsView, false);
- actionChip.setText(smartAction.title);
- actionChip.setIcon(smartAction.getIcon(), false);
- actionChip.setPendingIntent(smartAction.actionIntent,
- () -> {
- mUiEventLogger.log(ScreenshotEvent.SCREENSHOT_SMART_ACTION_TAPPED);
- dismissScreenshot("chip tapped", false);
- mOnCompleteRunnable.run();
- });
- actionChip.setAlpha(1);
- mActionsView.addView(actionChip);
- mSmartChips.add(actionChip);
- }
- }
- }
-
- private AnimatorSet createScreenshotDismissAnimation() {
- ValueAnimator alphaAnim = ValueAnimator.ofFloat(0, 1);
- alphaAnim.setStartDelay(SCREENSHOT_DISMISS_ALPHA_OFFSET_MS);
- alphaAnim.setDuration(SCREENSHOT_DISMISS_ALPHA_DURATION_MS);
- alphaAnim.addUpdateListener(animation -> {
- mScreenshotLayout.setAlpha(1 - animation.getAnimatedFraction());
- });
-
- ValueAnimator yAnim = ValueAnimator.ofFloat(0, 1);
- yAnim.setInterpolator(mAccelerateInterpolator);
- yAnim.setDuration(SCREENSHOT_DISMISS_Y_DURATION_MS);
- float screenshotStartY = mScreenshotPreview.getTranslationY();
- float dismissStartY = mDismissButton.getTranslationY();
- yAnim.addUpdateListener(animation -> {
- float yDelta = MathUtils.lerp(0, mDismissDeltaY, animation.getAnimatedFraction());
- mScreenshotPreview.setTranslationY(screenshotStartY + yDelta);
- mDismissButton.setTranslationY(dismissStartY + yDelta);
- mActionsContainer.setTranslationY(yDelta);
- mActionsContainerBackground.setTranslationY(yDelta);
- });
-
- AnimatorSet animSet = new AnimatorSet();
- animSet.play(yAnim).with(alphaAnim);
-
- return animSet;
- }
-
- private void clearScreenshot() {
- if (mScreenshotLayout.isAttachedToWindow()) {
- mWindowManager.removeView(mScreenshotLayout);
- }
-
- // Clear any references to the bitmap
- mScreenshotPreview.setImageDrawable(null);
- mScreenshotAnimatedView.setImageDrawable(null);
- mScreenshotAnimatedView.setVisibility(View.GONE);
- mActionsContainerBackground.setVisibility(View.GONE);
- mActionsContainer.setVisibility(View.GONE);
- mBackgroundProtection.setAlpha(0f);
- mDismissButton.setVisibility(View.GONE);
- mScreenshotPreview.setVisibility(View.GONE);
- mScreenshotPreview.setLayerType(View.LAYER_TYPE_NONE, null);
- mScreenshotPreview.setOnClickListener(null);
- mShareChip.setOnClickListener(null);
- mEditChip.setOnClickListener(null);
- mShareChip.setIsPending(false);
- mEditChip.setIsPending(false);
- mPendingInteraction = null;
- for (ScreenshotActionChip chip : mSmartChips) {
- mActionsView.removeView(chip);
- }
- mSmartChips.clear();
- mScreenshotLayout.setAlpha(1);
- mDismissButton.setTranslationY(0);
- mActionsContainer.setTranslationY(0);
- mActionsContainerBackground.setTranslationY(0);
- mScreenshotPreview.setTranslationY(0);
- }
-
- private void setAnimatedViewSize(int width, int height) {
- ViewGroup.LayoutParams layoutParams = mScreenshotAnimatedView.getLayoutParams();
- layoutParams.width = width;
- layoutParams.height = height;
- mScreenshotAnimatedView.setLayoutParams(layoutParams);
- }
-
- /**
- * Updates the window focusability. If the window is already showing, then it updates the
- * window immediately, otherwise the layout params will be applied when the window is next
- * shown.
- */
- private void setWindowFocusable(boolean focusable) {
- if (focusable) {
- mWindowLayoutParams.flags &= ~FLAG_NOT_FOCUSABLE;
- } else {
- mWindowLayoutParams.flags |= FLAG_NOT_FOCUSABLE;
- }
- if (mScreenshotLayout.isAttachedToWindow()) {
- mWindowManager.updateViewLayout(mScreenshotLayout, mWindowLayoutParams);
- }
- }
-
- private boolean isUserSetupComplete() {
- return Settings.Secure.getInt(mContext.getContentResolver(),
- SETTINGS_SECURE_USER_SETUP_COMPLETE, 0) == 1;
- }
-
- /** Does the aspect ratio of the bitmap with insets removed match the bounds. */
- private boolean aspectRatiosMatch(Bitmap bitmap, Insets bitmapInsets, Rect screenBounds) {
- int insettedWidth = bitmap.getWidth() - bitmapInsets.left - bitmapInsets.right;
- int insettedHeight = bitmap.getHeight() - bitmapInsets.top - bitmapInsets.bottom;
-
- if (insettedHeight == 0 || insettedWidth == 0 || bitmap.getWidth() == 0
- || bitmap.getHeight() == 0) {
- Log.e(TAG, String.format(
- "Provided bitmap and insets create degenerate region: %dx%d %s",
- bitmap.getWidth(), bitmap.getHeight(), bitmapInsets));
- return false;
- }
-
- float insettedBitmapAspect = ((float) insettedWidth) / insettedHeight;
- float boundsAspect = ((float) screenBounds.width()) / screenBounds.height();
-
- boolean matchWithinTolerance = Math.abs(insettedBitmapAspect - boundsAspect) < 0.1f;
- if (!matchWithinTolerance) {
- Log.d(TAG, String.format("aspectRatiosMatch: don't match bitmap: %f, bounds: %f",
- insettedBitmapAspect, boundsAspect));
- }
-
- return matchWithinTolerance;
- }
-
- /**
- * Create a drawable using the size of the bitmap and insets as the fractional inset parameters.
- */
- private Drawable createScreenDrawable(Bitmap bitmap, Insets insets) {
- int insettedWidth = bitmap.getWidth() - insets.left - insets.right;
- int insettedHeight = bitmap.getHeight() - insets.top - insets.bottom;
-
- BitmapDrawable bitmapDrawable = new BitmapDrawable(mContext.getResources(), bitmap);
- if (insettedHeight == 0 || insettedWidth == 0 || bitmap.getWidth() == 0
- || bitmap.getHeight() == 0) {
- Log.e(TAG, String.format(
- "Can't create insetted drawable, using 0 insets "
- + "bitmap and insets create degenerate region: %dx%d %s",
- bitmap.getWidth(), bitmap.getHeight(), insets));
- return bitmapDrawable;
- }
-
- InsetDrawable insetDrawable = new InsetDrawable(bitmapDrawable,
- -1f * insets.left / insettedWidth,
- -1f * insets.top / insettedHeight,
- -1f * insets.right / insettedWidth,
- -1f * insets.bottom / insettedHeight);
-
- if (insets.left < 0 || insets.top < 0 || insets.right < 0 || insets.bottom < 0) {
- // Are any of the insets negative, meaning the bitmap is smaller than the bounds so need
- // to fill in the background of the drawable.
- return new LayerDrawable(new Drawable[]{
- new ColorDrawable(Color.BLACK), insetDrawable});
- } else {
- return insetDrawable;
- }
- }
-}
diff --git a/packages/SystemUI/src/com/android/systemui/screenshot/SaveImageInBackgroundTask.java b/packages/SystemUI/src/com/android/systemui/screenshot/SaveImageInBackgroundTask.java
index f0ea597c458d..c0061ad97293 100644
--- a/packages/SystemUI/src/com/android/systemui/screenshot/SaveImageInBackgroundTask.java
+++ b/packages/SystemUI/src/com/android/systemui/screenshot/SaveImageInBackgroundTask.java
@@ -82,8 +82,8 @@ class SaveImageInBackgroundTask extends AsyncTask<Void, Void, Void> {
private final Context mContext;
private final ScreenshotSmartActions mScreenshotSmartActions;
- private final GlobalScreenshot.SaveImageInBackgroundData mParams;
- private final GlobalScreenshot.SavedImageData mImageData;
+ private final ScreenshotController.SaveImageInBackgroundData mParams;
+ private final ScreenshotController.SavedImageData mImageData;
private final String mImageFileName;
private final long mImageTime;
private final ScreenshotNotificationSmartActionsProvider mSmartActionsProvider;
@@ -92,10 +92,10 @@ class SaveImageInBackgroundTask extends AsyncTask<Void, Void, Void> {
private final Random mRandom = new Random();
SaveImageInBackgroundTask(Context context, ScreenshotSmartActions screenshotSmartActions,
- GlobalScreenshot.SaveImageInBackgroundData data) {
+ ScreenshotController.SaveImageInBackgroundData data) {
mContext = context;
mScreenshotSmartActions = screenshotSmartActions;
- mImageData = new GlobalScreenshot.SavedImageData();
+ mImageData = new ScreenshotController.SavedImageData();
// Prepare all the output metadata
mParams = data;
@@ -234,7 +234,7 @@ class SaveImageInBackgroundTask extends AsyncTask<Void, Void, Void> {
* Update the listener run when the saving task completes. Used to avoid showing UI for the
* first screenshot when a second one is taken.
*/
- void setActionsReadyListener(GlobalScreenshot.ActionsReadyListener listener) {
+ void setActionsReadyListener(ScreenshotController.ActionsReadyListener listener) {
mParams.mActionsReadyListener = listener;
}
@@ -287,10 +287,10 @@ class SaveImageInBackgroundTask extends AsyncTask<Void, Void, Void> {
// Create a share action for the notification
PendingIntent shareAction = PendingIntent.getBroadcastAsUser(context, requestCode,
new Intent(context, ActionProxyReceiver.class)
- .putExtra(GlobalScreenshot.EXTRA_ACTION_INTENT, pendingIntent)
- .putExtra(GlobalScreenshot.EXTRA_DISALLOW_ENTER_PIP, true)
- .putExtra(GlobalScreenshot.EXTRA_ID, mScreenshotId)
- .putExtra(GlobalScreenshot.EXTRA_SMART_ACTIONS_ENABLED,
+ .putExtra(ScreenshotController.EXTRA_ACTION_INTENT, pendingIntent)
+ .putExtra(ScreenshotController.EXTRA_DISALLOW_ENTER_PIP, true)
+ .putExtra(ScreenshotController.EXTRA_ID, mScreenshotId)
+ .putExtra(ScreenshotController.EXTRA_SMART_ACTIONS_ENABLED,
mSmartActionsEnabled)
.setAction(Intent.ACTION_SEND)
.addFlags(Intent.FLAG_RECEIVER_FOREGROUND),
@@ -332,9 +332,9 @@ class SaveImageInBackgroundTask extends AsyncTask<Void, Void, Void> {
// Create a edit action
PendingIntent editAction = PendingIntent.getBroadcastAsUser(context, requestCode,
new Intent(context, ActionProxyReceiver.class)
- .putExtra(GlobalScreenshot.EXTRA_ACTION_INTENT, pendingIntent)
- .putExtra(GlobalScreenshot.EXTRA_ID, mScreenshotId)
- .putExtra(GlobalScreenshot.EXTRA_SMART_ACTIONS_ENABLED,
+ .putExtra(ScreenshotController.EXTRA_ACTION_INTENT, pendingIntent)
+ .putExtra(ScreenshotController.EXTRA_ID, mScreenshotId)
+ .putExtra(ScreenshotController.EXTRA_SMART_ACTIONS_ENABLED,
mSmartActionsEnabled)
.setAction(Intent.ACTION_EDIT)
.addFlags(Intent.FLAG_RECEIVER_FOREGROUND),
@@ -355,9 +355,9 @@ class SaveImageInBackgroundTask extends AsyncTask<Void, Void, Void> {
// Create a delete action for the notification
PendingIntent deleteAction = PendingIntent.getBroadcast(context, requestCode,
new Intent(context, DeleteScreenshotReceiver.class)
- .putExtra(GlobalScreenshot.SCREENSHOT_URI_ID, uri.toString())
- .putExtra(GlobalScreenshot.EXTRA_ID, mScreenshotId)
- .putExtra(GlobalScreenshot.EXTRA_SMART_ACTIONS_ENABLED,
+ .putExtra(ScreenshotController.SCREENSHOT_URI_ID, uri.toString())
+ .putExtra(ScreenshotController.EXTRA_ID, mScreenshotId)
+ .putExtra(ScreenshotController.EXTRA_SMART_ACTIONS_ENABLED,
mSmartActionsEnabled)
.addFlags(Intent.FLAG_RECEIVER_FOREGROUND),
PendingIntent.FLAG_CANCEL_CURRENT | PendingIntent.FLAG_ONE_SHOT);
@@ -395,7 +395,7 @@ class SaveImageInBackgroundTask extends AsyncTask<Void, Void, Void> {
ScreenshotNotificationSmartActionsProvider.ACTION_TYPE,
ScreenshotNotificationSmartActionsProvider.DEFAULT_ACTION_TYPE);
Intent intent = new Intent(context, SmartActionsReceiver.class)
- .putExtra(GlobalScreenshot.EXTRA_ACTION_INTENT, action.actionIntent)
+ .putExtra(ScreenshotController.EXTRA_ACTION_INTENT, action.actionIntent)
.addFlags(Intent.FLAG_RECEIVER_FOREGROUND);
addIntentExtras(mScreenshotId, intent, actionType, mSmartActionsEnabled);
PendingIntent broadcastIntent = PendingIntent.getBroadcast(context,
@@ -411,9 +411,9 @@ class SaveImageInBackgroundTask extends AsyncTask<Void, Void, Void> {
private static void addIntentExtras(String screenshotId, Intent intent, String actionType,
boolean smartActionsEnabled) {
intent
- .putExtra(GlobalScreenshot.EXTRA_ACTION_TYPE, actionType)
- .putExtra(GlobalScreenshot.EXTRA_ID, screenshotId)
- .putExtra(GlobalScreenshot.EXTRA_SMART_ACTIONS_ENABLED, smartActionsEnabled);
+ .putExtra(ScreenshotController.EXTRA_ACTION_TYPE, actionType)
+ .putExtra(ScreenshotController.EXTRA_ID, screenshotId)
+ .putExtra(ScreenshotController.EXTRA_SMART_ACTIONS_ENABLED, smartActionsEnabled);
}
diff --git a/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotController.java b/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotController.java
new file mode 100644
index 000000000000..5d8f70c4e460
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotController.java
@@ -0,0 +1,665 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.screenshot;
+
+import static android.content.res.Configuration.ORIENTATION_LANDSCAPE;
+import static android.content.res.Configuration.ORIENTATION_PORTRAIT;
+import static android.view.Display.DEFAULT_DISPLAY;
+
+import static java.util.Objects.requireNonNull;
+
+import android.animation.Animator;
+import android.animation.AnimatorListenerAdapter;
+import android.annotation.Nullable;
+import android.annotation.SuppressLint;
+import android.app.Notification;
+import android.app.WindowContext;
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.res.Configuration;
+import android.graphics.Bitmap;
+import android.graphics.Insets;
+import android.graphics.PixelFormat;
+import android.graphics.Rect;
+import android.hardware.display.DisplayManager;
+import android.media.MediaActionSound;
+import android.net.Uri;
+import android.os.Handler;
+import android.os.IBinder;
+import android.os.Looper;
+import android.os.Message;
+import android.provider.Settings;
+import android.util.DisplayMetrics;
+import android.util.Log;
+import android.view.Display;
+import android.view.KeyEvent;
+import android.view.LayoutInflater;
+import android.view.MotionEvent;
+import android.view.SurfaceControl;
+import android.view.View;
+import android.view.ViewGroup;
+import android.view.WindowManager;
+import android.view.accessibility.AccessibilityEvent;
+import android.view.accessibility.AccessibilityManager;
+import android.widget.Toast;
+
+import com.android.internal.logging.UiEventLogger;
+import com.android.systemui.R;
+
+import java.util.List;
+import java.util.function.Consumer;
+
+import javax.inject.Inject;
+
+/**
+ * Controls the state and flow for screenshots.
+ */
+public class ScreenshotController {
+ /**
+ * POD used in the AsyncTask which saves an image in the background.
+ */
+ static class SaveImageInBackgroundData {
+ public Bitmap image;
+ public Consumer<Uri> finisher;
+ public ScreenshotController.ActionsReadyListener mActionsReadyListener;
+
+ void clearImage() {
+ image = null;
+ }
+ }
+
+ /**
+ * Structure returned by the SaveImageInBackgroundTask
+ */
+ static class SavedImageData {
+ public Uri uri;
+ public Notification.Action shareAction;
+ public Notification.Action editAction;
+ public Notification.Action deleteAction;
+ public List<Notification.Action> smartActions;
+
+ /**
+ * Used to reset the return data on error
+ */
+ public void reset() {
+ uri = null;
+ shareAction = null;
+ editAction = null;
+ deleteAction = null;
+ smartActions = null;
+ }
+ }
+
+ abstract static class ActionsReadyListener {
+ abstract void onActionsReady(ScreenshotController.SavedImageData imageData);
+ }
+
+ private static final String TAG = "GlobalScreenshotController";
+
+ // These strings are used for communicating the action invoked to
+ // ScreenshotNotificationSmartActionsProvider.
+ static final String EXTRA_ACTION_TYPE = "android:screenshot_action_type";
+ static final String EXTRA_ID = "android:screenshot_id";
+ static final String ACTION_TYPE_DELETE = "Delete";
+ static final String ACTION_TYPE_SHARE = "Share";
+ static final String ACTION_TYPE_EDIT = "Edit";
+ static final String EXTRA_SMART_ACTIONS_ENABLED = "android:smart_actions_enabled";
+ static final String EXTRA_ACTION_INTENT = "android:screenshot_action_intent";
+
+ static final String SCREENSHOT_URI_ID = "android:screenshot_uri_id";
+ static final String EXTRA_CANCEL_NOTIFICATION = "android:screenshot_cancel_notification";
+ static final String EXTRA_DISALLOW_ENTER_PIP = "android:screenshot_disallow_enter_pip";
+
+
+ private static final int MESSAGE_CORNER_TIMEOUT = 2;
+ private static final int SCREENSHOT_CORNER_DEFAULT_TIMEOUT_MILLIS = 6000;
+
+ // From WizardManagerHelper.java
+ private static final String SETTINGS_SECURE_USER_SETUP_COMPLETE = "user_setup_complete";
+
+ private final Context mContext;
+ private final ScreenshotNotificationsController mNotificationsController;
+ private final ScreenshotSmartActions mScreenshotSmartActions;
+ private final UiEventLogger mUiEventLogger;
+
+ private final WindowManager mWindowManager;
+ private final WindowManager.LayoutParams mWindowLayoutParams;
+ private final Display mDisplay;
+ private final DisplayMetrics mDisplayMetrics;
+ private final AccessibilityManager mAccessibilityManager;
+ private final MediaActionSound mCameraSound;
+
+ private ScreenshotView mScreenshotView;
+ private Bitmap mScreenBitmap;
+ private SaveImageInBackgroundTask mSaveInBgTask;
+
+ private Animator mScreenshotAnimation;
+ private Animator mDismissAnimation;
+
+ private Runnable mOnCompleteRunnable;
+ private boolean mInDarkMode;
+ private boolean mDirectionLTR;
+ private boolean mOrientationPortrait;
+
+ private final Handler mScreenshotHandler = new Handler(Looper.getMainLooper()) {
+ @Override
+ public void handleMessage(Message msg) {
+ switch (msg.what) {
+ case MESSAGE_CORNER_TIMEOUT:
+ mUiEventLogger.log(ScreenshotEvent.SCREENSHOT_INTERACTION_TIMEOUT);
+ ScreenshotController.this.dismissScreenshot(false);
+ mOnCompleteRunnable.run();
+ break;
+ default:
+ break;
+ }
+ }
+ };
+
+ @Inject
+ ScreenshotController(Context context, ScreenshotSmartActions screenshotSmartActions,
+ ScreenshotNotificationsController screenshotNotificationsController,
+ UiEventLogger uiEventLogger) {
+ mScreenshotSmartActions = screenshotSmartActions;
+ mNotificationsController = screenshotNotificationsController;
+ mUiEventLogger = uiEventLogger;
+
+ // Create a visual (Window) context
+ // After this, our windowToken is available from mContext.getActivityToken()
+ final DisplayManager dm = requireNonNull(context.getSystemService(DisplayManager.class));
+ mDisplay = dm.getDisplay(DEFAULT_DISPLAY);
+ Context displayContext = context.createDisplayContext(mDisplay);
+ mContext = new WindowContext(displayContext, WindowManager.LayoutParams.TYPE_SCREENSHOT,
+ null);
+ mWindowManager = mContext.getSystemService(WindowManager.class);
+
+ mAccessibilityManager = AccessibilityManager.getInstance(mContext);
+
+ reloadAssets();
+ Configuration config = mContext.getResources().getConfiguration();
+ mInDarkMode = config.isNightModeActive();
+ mDirectionLTR = config.getLayoutDirection() == View.LAYOUT_DIRECTION_LTR;
+ mOrientationPortrait = config.orientation == ORIENTATION_PORTRAIT;
+
+ // Setup the window that we are going to use
+ mWindowLayoutParams = new WindowManager.LayoutParams(
+ ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT, 0, 0,
+ WindowManager.LayoutParams.TYPE_SCREENSHOT,
+ WindowManager.LayoutParams.FLAG_FULLSCREEN
+ | WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN
+ | WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL
+ | WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH
+ | WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED
+ | WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM,
+ PixelFormat.TRANSLUCENT);
+ mWindowLayoutParams.setTitle("ScreenshotAnimation");
+ mWindowLayoutParams.layoutInDisplayCutoutMode =
+ WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS;
+ mWindowLayoutParams.setFitInsetsTypes(0 /* types */);
+
+ mDisplayMetrics = new DisplayMetrics();
+ mDisplay.getRealMetrics(mDisplayMetrics);
+
+ // Setup the Camera shutter sound
+ mCameraSound = new MediaActionSound();
+ mCameraSound.load(MediaActionSound.SHUTTER_CLICK);
+ }
+
+ void takeScreenshotFullscreen(Consumer<Uri> finisher, Runnable onComplete) {
+ mOnCompleteRunnable = onComplete;
+
+ mDisplay.getRealMetrics(mDisplayMetrics);
+ takeScreenshotInternal(
+ finisher,
+ new Rect(0, 0, mDisplayMetrics.widthPixels, mDisplayMetrics.heightPixels));
+ }
+
+ void handleImageAsScreenshot(Bitmap screenshot, Rect screenshotScreenBounds,
+ Insets visibleInsets, int taskId, int userId, ComponentName topComponent,
+ Consumer<Uri> finisher, Runnable onComplete) {
+ // TODO: use task Id, userId, topComponent for smart handler
+ mOnCompleteRunnable = onComplete;
+
+ if (screenshot == null) {
+ Log.e(TAG, "Got null bitmap from screenshot message");
+ mNotificationsController.notifyScreenshotError(
+ R.string.screenshot_failed_to_capture_text);
+ finisher.accept(null);
+ mOnCompleteRunnable.run();
+ return;
+ }
+
+ if (aspectRatiosMatch(screenshot, visibleInsets, screenshotScreenBounds)) {
+ saveScreenshot(screenshot, finisher, screenshotScreenBounds, visibleInsets, false);
+ } else {
+ saveScreenshot(screenshot, finisher,
+ new Rect(0, 0, screenshot.getWidth(), screenshot.getHeight()), Insets.NONE,
+ true);
+ }
+ }
+
+ /**
+ * Displays a screenshot selector
+ */
+ @SuppressLint("ClickableViewAccessibility")
+ void takeScreenshotPartial(final Consumer<Uri> finisher, Runnable onComplete) {
+ dismissScreenshot(true);
+ mOnCompleteRunnable = onComplete;
+
+ mWindowManager.addView(mScreenshotView, mWindowLayoutParams);
+
+ mScreenshotView.takePartialScreenshot(
+ rect -> takeScreenshotInternal(finisher, rect));
+ }
+
+ boolean isDismissing() {
+ return (mDismissAnimation != null && mDismissAnimation.isRunning());
+ }
+
+ /**
+ * Clears current screenshot
+ */
+ void dismissScreenshot(boolean immediate) {
+ Log.v(TAG, "clearing screenshot");
+ mScreenshotHandler.removeMessages(MESSAGE_CORNER_TIMEOUT);
+ mScreenshotView.getViewTreeObserver().removeOnComputeInternalInsetsListener(
+ mScreenshotView);
+ if (!immediate) {
+ mDismissAnimation = mScreenshotView.createScreenshotDismissAnimation();
+ mDismissAnimation.addListener(new AnimatorListenerAdapter() {
+ @Override
+ public void onAnimationEnd(Animator animation) {
+ super.onAnimationEnd(animation);
+ clearScreenshot();
+ }
+ });
+ mDismissAnimation.start();
+ } else {
+ clearScreenshot();
+ }
+ }
+
+ private void onConfigChanged(Configuration newConfig) {
+ boolean needsUpdate = false;
+ // dark mode
+ if (newConfig.isNightModeActive()) {
+ // Night mode is active, we're using dark theme
+ if (!mInDarkMode) {
+ mInDarkMode = true;
+ needsUpdate = true;
+ }
+ } else {
+ // Night mode is not active, we're using the light theme
+ if (mInDarkMode) {
+ mInDarkMode = false;
+ needsUpdate = true;
+ }
+ }
+
+ // RTL configuration
+ switch (newConfig.getLayoutDirection()) {
+ case View.LAYOUT_DIRECTION_LTR:
+ if (!mDirectionLTR) {
+ mDirectionLTR = true;
+ needsUpdate = true;
+ }
+ break;
+ case View.LAYOUT_DIRECTION_RTL:
+ if (mDirectionLTR) {
+ mDirectionLTR = false;
+ needsUpdate = true;
+ }
+ break;
+ }
+
+ // portrait/landscape orientation
+ switch (newConfig.orientation) {
+ case ORIENTATION_PORTRAIT:
+ if (!mOrientationPortrait) {
+ mOrientationPortrait = true;
+ needsUpdate = true;
+ }
+ break;
+ case ORIENTATION_LANDSCAPE:
+ if (mOrientationPortrait) {
+ mOrientationPortrait = false;
+ needsUpdate = true;
+ }
+ break;
+ }
+
+ if (needsUpdate) {
+ reloadAssets();
+ }
+ }
+
+ /**
+ * Update assets (called when the dark theme status changes). We only need to update the dismiss
+ * button and the actions container background, since the buttons are re-inflated on demand.
+ */
+ private void reloadAssets() {
+ boolean wasAttached = mScreenshotView != null && mScreenshotView.isAttachedToWindow();
+ if (wasAttached) {
+ mWindowManager.removeView(mScreenshotView);
+ }
+
+ // Inflate the screenshot layout
+ mScreenshotView = (ScreenshotView)
+ LayoutInflater.from(mContext).inflate(R.layout.global_screenshot, null);
+
+ // TODO(159460485): Remove this when focus is handled properly in the system
+ mScreenshotView.setOnTouchListener((v, event) -> {
+ if (event.getActionMasked() == MotionEvent.ACTION_OUTSIDE) {
+ // Once the user touches outside, stop listening for input
+ setWindowFocusable(false);
+ }
+ return false;
+ });
+
+ mScreenshotView.setOnKeyListener((v, keyCode, event) -> {
+ if (keyCode == KeyEvent.KEYCODE_BACK) {
+ dismissScreenshot(false);
+ return true;
+ }
+ return false;
+ });
+
+ if (wasAttached) {
+ mWindowManager.addView(mScreenshotView, mWindowLayoutParams);
+ }
+ }
+
+ /**
+ * Takes a screenshot of the current display and shows an animation.
+ */
+ private void takeScreenshotInternal(Consumer<Uri> finisher, Rect crop) {
+ // copy the input Rect, since SurfaceControl.screenshot can mutate it
+ Rect screenRect = new Rect(crop);
+ int width = crop.width();
+ int height = crop.height();
+ final IBinder displayToken = SurfaceControl.getInternalDisplayToken();
+ final SurfaceControl.DisplayCaptureArgs captureArgs =
+ new SurfaceControl.DisplayCaptureArgs.Builder(displayToken)
+ .setSourceCrop(crop)
+ .setSize(width, height)
+ .build();
+ final SurfaceControl.ScreenshotHardwareBuffer screenshotBuffer =
+ SurfaceControl.captureDisplay(captureArgs);
+ Bitmap screenshot = screenshotBuffer == null ? null : screenshotBuffer.asBitmap();
+
+ if (screenshot == null) {
+ Log.e(TAG, "Screenshot bitmap was null");
+ mNotificationsController.notifyScreenshotError(
+ R.string.screenshot_failed_to_capture_text);
+ finisher.accept(null);
+ mOnCompleteRunnable.run();
+ return;
+ }
+
+ saveScreenshot(screenshot, finisher, screenRect, Insets.NONE, true);
+ }
+
+ private void saveScreenshot(Bitmap screenshot, Consumer<Uri> finisher, Rect screenRect,
+ Insets screenInsets, boolean showFlash) {
+ if (mAccessibilityManager.isEnabled()) {
+ AccessibilityEvent event =
+ new AccessibilityEvent(AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED);
+ event.setContentDescription(
+ mContext.getResources().getString(R.string.screenshot_saving_title));
+ mAccessibilityManager.sendAccessibilityEvent(event);
+ }
+
+ if (mScreenshotView.isAttachedToWindow()) {
+ // if we didn't already dismiss for another reason
+ if (mDismissAnimation == null || !mDismissAnimation.isRunning()) {
+ mUiEventLogger.log(ScreenshotEvent.SCREENSHOT_REENTERED);
+ }
+ dismissScreenshot(true);
+ }
+
+ mScreenBitmap = screenshot;
+
+ if (!isUserSetupComplete()) {
+ // User setup isn't complete, so we don't want to show any UI beyond a toast, as editing
+ // and sharing shouldn't be exposed to the user.
+ saveScreenshotAndToast(finisher);
+ return;
+ }
+
+ // Optimizations
+ mScreenBitmap.setHasAlpha(false);
+ mScreenBitmap.prepareToDraw();
+
+ onConfigChanged(mContext.getResources().getConfiguration());
+
+ if (mDismissAnimation != null && mDismissAnimation.isRunning()) {
+ mDismissAnimation.cancel();
+ }
+
+ // The window is focusable by default
+ setWindowFocusable(true);
+
+ // Start the post-screenshot animation
+ startAnimation(finisher, screenRect, screenInsets, showFlash);
+ }
+
+ /**
+ * Save the bitmap but don't show the normal screenshot UI.. just a toast (or notification on
+ * failure).
+ */
+ private void saveScreenshotAndToast(Consumer<Uri> finisher) {
+ // Play the shutter sound to notify that we've taken a screenshot
+ mScreenshotHandler.post(() -> {
+ mCameraSound.play(MediaActionSound.SHUTTER_CLICK);
+ });
+
+ saveScreenshotInWorkerThread(finisher,
+ new ScreenshotController.ActionsReadyListener() {
+ @Override
+ void onActionsReady(ScreenshotController.SavedImageData imageData) {
+ finisher.accept(imageData.uri);
+ if (imageData.uri == null) {
+ mUiEventLogger.log(ScreenshotEvent.SCREENSHOT_NOT_SAVED);
+ mNotificationsController.notifyScreenshotError(
+ R.string.screenshot_failed_to_save_text);
+ } else {
+ mUiEventLogger.log(ScreenshotEvent.SCREENSHOT_SAVED);
+
+ mScreenshotHandler.post(() -> {
+ Toast.makeText(mContext, R.string.screenshot_saved_title,
+ Toast.LENGTH_SHORT).show();
+ });
+ }
+ }
+ });
+ }
+
+ /**
+ * Starts the animation after taking the screenshot
+ */
+ private void startAnimation(final Consumer<Uri> finisher, Rect screenRect, Insets screenInsets,
+ boolean showFlash) {
+ mScreenshotHandler.post(() -> {
+ if (!mScreenshotView.isAttachedToWindow()) {
+ mWindowManager.addView(mScreenshotView, mWindowLayoutParams);
+ }
+
+ mScreenshotView.prepareForAnimation(mScreenBitmap, screenRect, screenInsets);
+
+ mScreenshotHandler.post(() -> {
+ mScreenshotView.getViewTreeObserver().addOnComputeInternalInsetsListener(
+ mScreenshotView);
+
+ mScreenshotAnimation =
+ mScreenshotView.createScreenshotDropInAnimation(screenRect, showFlash,
+ this::onElementTapped);
+
+ saveScreenshotInWorkerThread(finisher,
+ new ScreenshotController.ActionsReadyListener() {
+ @Override
+ void onActionsReady(
+ ScreenshotController.SavedImageData imageData) {
+ showUiOnActionsReady(imageData);
+ }
+ });
+
+ // Play the shutter sound to notify that we've taken a screenshot
+ mCameraSound.play(MediaActionSound.SHUTTER_CLICK);
+
+ mScreenshotAnimation.start();
+ });
+ });
+ }
+
+ /**
+ * Creates a new worker thread and saves the screenshot to the media store.
+ */
+ private void saveScreenshotInWorkerThread(
+ Consumer<Uri> finisher,
+ @Nullable ScreenshotController.ActionsReadyListener actionsReadyListener) {
+ ScreenshotController.SaveImageInBackgroundData
+ data = new ScreenshotController.SaveImageInBackgroundData();
+ data.image = mScreenBitmap;
+ data.finisher = finisher;
+ data.mActionsReadyListener = actionsReadyListener;
+
+ if (mSaveInBgTask != null) {
+ // just log success/failure for the pre-existing screenshot
+ mSaveInBgTask.setActionsReadyListener(
+ new ScreenshotController.ActionsReadyListener() {
+ @Override
+ void onActionsReady(ScreenshotController.SavedImageData imageData) {
+ logSuccessOnActionsReady(imageData);
+ }
+ });
+ }
+
+ mSaveInBgTask = new SaveImageInBackgroundTask(mContext, mScreenshotSmartActions, data);
+ mSaveInBgTask.execute();
+ }
+
+ /**
+ * Sets up the action shade and its entrance animation, once we get the screenshot URI.
+ */
+ private void showUiOnActionsReady(ScreenshotController.SavedImageData imageData) {
+ logSuccessOnActionsReady(imageData);
+
+ AccessibilityManager accessibilityManager = (AccessibilityManager)
+ mContext.getSystemService(Context.ACCESSIBILITY_SERVICE);
+ long timeoutMs = accessibilityManager.getRecommendedTimeoutMillis(
+ SCREENSHOT_CORNER_DEFAULT_TIMEOUT_MILLIS,
+ AccessibilityManager.FLAG_CONTENT_CONTROLS);
+
+ mScreenshotHandler.removeMessages(MESSAGE_CORNER_TIMEOUT);
+ mScreenshotHandler.sendMessageDelayed(
+ mScreenshotHandler.obtainMessage(MESSAGE_CORNER_TIMEOUT),
+ timeoutMs);
+
+ if (imageData.uri != null) {
+ mScreenshotHandler.post(() -> {
+ if (mScreenshotAnimation != null && mScreenshotAnimation.isRunning()) {
+ mScreenshotAnimation.addListener(new AnimatorListenerAdapter() {
+ @Override
+ public void onAnimationEnd(Animator animation) {
+ super.onAnimationEnd(animation);
+ mScreenshotView.setChipIntents(
+ imageData, event -> onElementTapped(event));
+ }
+ });
+ } else {
+ mScreenshotView.setChipIntents(
+ imageData, this::onElementTapped);
+ }
+ });
+ }
+ }
+
+ private void onElementTapped(ScreenshotEvent event) {
+ mUiEventLogger.log(event);
+ dismissScreenshot(false);
+ mOnCompleteRunnable.run();
+ }
+
+ /**
+ * Logs success/failure of the screenshot saving task, and shows an error if it failed.
+ */
+ private void logSuccessOnActionsReady(ScreenshotController.SavedImageData imageData) {
+ if (imageData.uri == null) {
+ mUiEventLogger.log(ScreenshotEvent.SCREENSHOT_NOT_SAVED);
+ mNotificationsController.notifyScreenshotError(
+ R.string.screenshot_failed_to_save_text);
+ } else {
+ mUiEventLogger.log(ScreenshotEvent.SCREENSHOT_SAVED);
+ }
+ }
+
+ private void clearScreenshot() {
+ if (mScreenshotView.isAttachedToWindow()) {
+ mWindowManager.removeView(mScreenshotView);
+ }
+
+ mScreenshotView.reset();
+ }
+
+ private boolean isUserSetupComplete() {
+ return Settings.Secure.getInt(mContext.getContentResolver(),
+ SETTINGS_SECURE_USER_SETUP_COMPLETE, 0) == 1;
+ }
+
+
+ /**
+ * Updates the window focusability. If the window is already showing, then it updates the
+ * window immediately, otherwise the layout params will be applied when the window is next
+ * shown.
+ */
+ private void setWindowFocusable(boolean focusable) {
+ if (focusable) {
+ mWindowLayoutParams.flags &= ~WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;
+ } else {
+ mWindowLayoutParams.flags |= WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;
+ }
+ if (mScreenshotView.isAttachedToWindow()) {
+ mWindowManager.updateViewLayout(mScreenshotView, mWindowLayoutParams);
+ }
+ }
+
+ /** Does the aspect ratio of the bitmap with insets removed match the bounds. */
+ private static boolean aspectRatiosMatch(Bitmap bitmap, Insets bitmapInsets,
+ Rect screenBounds) {
+ int insettedWidth = bitmap.getWidth() - bitmapInsets.left - bitmapInsets.right;
+ int insettedHeight = bitmap.getHeight() - bitmapInsets.top - bitmapInsets.bottom;
+
+ if (insettedHeight == 0 || insettedWidth == 0 || bitmap.getWidth() == 0
+ || bitmap.getHeight() == 0) {
+ Log.e(TAG, String.format(
+ "Provided bitmap and insets create degenerate region: %dx%d %s",
+ bitmap.getWidth(), bitmap.getHeight(), bitmapInsets));
+ return false;
+ }
+
+ float insettedBitmapAspect = ((float) insettedWidth) / insettedHeight;
+ float boundsAspect = ((float) screenBounds.width()) / screenBounds.height();
+
+ boolean matchWithinTolerance = Math.abs(insettedBitmapAspect - boundsAspect) < 0.1f;
+ if (!matchWithinTolerance) {
+ Log.d(TAG, String.format("aspectRatiosMatch: don't match bitmap: %f, bounds: %f",
+ insettedBitmapAspect, boundsAspect));
+ }
+
+ return matchWithinTolerance;
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotNotificationsController.java b/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotNotificationsController.java
index 6d1299ba98ac..a946513870c9 100644
--- a/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotNotificationsController.java
+++ b/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotNotificationsController.java
@@ -185,7 +185,7 @@ public class ScreenshotNotificationsController {
* @param actionData SavedImageData struct with image URI and actions
*/
public void showScreenshotActionsNotification(
- GlobalScreenshot.SavedImageData actionData) {
+ ScreenshotController.SavedImageData actionData) {
mNotificationBuilder.addAction(actionData.shareAction);
mNotificationBuilder.addAction(actionData.editAction);
mNotificationBuilder.addAction(actionData.deleteAction);
diff --git a/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotSelectorView.java b/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotSelectorView.java
index 07a92460f3ea..c793b5b9639e 100644
--- a/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotSelectorView.java
+++ b/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotSelectorView.java
@@ -26,8 +26,11 @@ import android.graphics.PorterDuff;
import android.graphics.PorterDuffXfermode;
import android.graphics.Rect;
import android.util.AttributeSet;
+import android.view.MotionEvent;
import android.view.View;
+import java.util.function.Consumer;
+
/**
* Draws a selection rectangle while taking screenshot
*/
@@ -36,6 +39,8 @@ public class ScreenshotSelectorView extends View {
private Rect mSelectionRect;
private final Paint mPaintSelection, mPaintBackground;
+ private Consumer<Rect> mOnScreenshotSelected;
+
public ScreenshotSelectorView(Context context) {
this(context, null);
}
@@ -46,14 +51,54 @@ public class ScreenshotSelectorView extends View {
mPaintBackground.setAlpha(160);
mPaintSelection = new Paint(Color.TRANSPARENT);
mPaintSelection.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.CLEAR));
+
+ setOnTouchListener((v, event) -> {
+ switch (event.getAction()) {
+ case MotionEvent.ACTION_DOWN:
+ startSelection((int) event.getX(), (int) event.getY());
+ return true;
+ case MotionEvent.ACTION_MOVE:
+ updateSelection((int) event.getX(), (int) event.getY());
+ return true;
+ case MotionEvent.ACTION_UP:
+ setVisibility(View.GONE);
+ final Rect rect = getSelectionRect();
+ if (mOnScreenshotSelected != null
+ && rect != null
+ && rect.width() != 0 && rect.height() != 0) {
+ mOnScreenshotSelected.accept(rect);
+ }
+ stopSelection();
+ return true;
+ }
+ return false;
+ });
+ }
+
+ @Override
+ public void draw(Canvas canvas) {
+ canvas.drawRect(mLeft, mTop, mRight, mBottom, mPaintBackground);
+ if (mSelectionRect != null) {
+ canvas.drawRect(mSelectionRect, mPaintSelection);
+ }
+ }
+
+ void setOnScreenshotSelected(Consumer<Rect> onScreenshotSelected) {
+ mOnScreenshotSelected = onScreenshotSelected;
+ }
+
+ void stop() {
+ if (getSelectionRect() != null) {
+ stopSelection();
+ }
}
- public void startSelection(int x, int y) {
+ private void startSelection(int x, int y) {
mStartPoint = new Point(x, y);
mSelectionRect = new Rect(x, y, x, y);
}
- public void updateSelection(int x, int y) {
+ private void updateSelection(int x, int y) {
if (mSelectionRect != null) {
mSelectionRect.left = Math.min(mStartPoint.x, x);
mSelectionRect.right = Math.max(mStartPoint.x, x);
@@ -63,20 +108,12 @@ public class ScreenshotSelectorView extends View {
}
}
- public Rect getSelectionRect() {
+ private Rect getSelectionRect() {
return mSelectionRect;
}
- public void stopSelection() {
+ private void stopSelection() {
mStartPoint = null;
mSelectionRect = null;
}
-
- @Override
- public void draw(Canvas canvas) {
- canvas.drawRect(mLeft, mTop, mRight, mBottom, mPaintBackground);
- if (mSelectionRect != null) {
- canvas.drawRect(mSelectionRect, mPaintSelection);
- }
- }
}
diff --git a/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotView.java b/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotView.java
new file mode 100644
index 000000000000..03fe2920405f
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotView.java
@@ -0,0 +1,611 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.screenshot;
+
+import static android.content.res.Configuration.ORIENTATION_PORTRAIT;
+
+import static java.util.Objects.requireNonNull;
+
+import android.animation.Animator;
+import android.animation.AnimatorListenerAdapter;
+import android.animation.AnimatorSet;
+import android.animation.ValueAnimator;
+import android.app.ActivityManager;
+import android.app.Notification;
+import android.app.PendingIntent;
+import android.content.Context;
+import android.content.res.Resources;
+import android.graphics.Bitmap;
+import android.graphics.Color;
+import android.graphics.Insets;
+import android.graphics.Outline;
+import android.graphics.PointF;
+import android.graphics.Rect;
+import android.graphics.Region;
+import android.graphics.drawable.BitmapDrawable;
+import android.graphics.drawable.ColorDrawable;
+import android.graphics.drawable.Drawable;
+import android.graphics.drawable.Icon;
+import android.graphics.drawable.InsetDrawable;
+import android.graphics.drawable.LayerDrawable;
+import android.os.RemoteException;
+import android.util.AttributeSet;
+import android.util.DisplayMetrics;
+import android.util.Log;
+import android.util.MathUtils;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.view.ViewOutlineProvider;
+import android.view.ViewTreeObserver;
+import android.view.WindowInsets;
+import android.view.animation.AccelerateInterpolator;
+import android.view.animation.AnimationUtils;
+import android.view.animation.Interpolator;
+import android.widget.FrameLayout;
+import android.widget.HorizontalScrollView;
+import android.widget.ImageView;
+import android.widget.LinearLayout;
+
+import com.android.systemui.R;
+import com.android.systemui.shared.system.QuickStepContract;
+
+import java.util.ArrayList;
+import java.util.function.Consumer;
+
+/**
+ * Handles the visual elements and animations for the screenshot flow.
+ */
+public class ScreenshotView extends FrameLayout implements
+ ViewTreeObserver.OnComputeInternalInsetsListener {
+
+ private static final String TAG = "GlobalScreenshotView";
+
+ private static final long SCREENSHOT_FLASH_IN_DURATION_MS = 133;
+ private static final long SCREENSHOT_FLASH_OUT_DURATION_MS = 217;
+ // delay before starting to fade in dismiss button
+ private static final long SCREENSHOT_TO_CORNER_DISMISS_DELAY_MS = 200;
+ private static final long SCREENSHOT_TO_CORNER_X_DURATION_MS = 234;
+ private static final long SCREENSHOT_TO_CORNER_Y_DURATION_MS = 500;
+ private static final long SCREENSHOT_TO_CORNER_SCALE_DURATION_MS = 234;
+ private static final long SCREENSHOT_ACTIONS_EXPANSION_DURATION_MS = 400;
+ private static final long SCREENSHOT_ACTIONS_ALPHA_DURATION_MS = 100;
+ private static final long SCREENSHOT_DISMISS_Y_DURATION_MS = 350;
+ private static final long SCREENSHOT_DISMISS_ALPHA_DURATION_MS = 183;
+ private static final long SCREENSHOT_DISMISS_ALPHA_OFFSET_MS = 50; // delay before starting fade
+ private static final float SCREENSHOT_ACTIONS_START_SCALE_X = .7f;
+ private static final float ROUNDED_CORNER_RADIUS = .05f;
+
+ private final Interpolator mAccelerateInterpolator = new AccelerateInterpolator();
+
+ private final Resources mResources;
+ private final Interpolator mFastOutSlowIn;
+ private final DisplayMetrics mDisplayMetrics;
+ private final float mCornerSizeX;
+ private final float mDismissDeltaY;
+
+ private int mNavMode;
+ private int mLeftInset;
+ private int mRightInset;
+ private boolean mOrientationPortrait;
+ private boolean mDirectionLTR;
+
+ private ScreenshotSelectorView mScreenshotSelectorView;
+ private ImageView mScreenshotAnimatedView;
+ private ImageView mScreenshotPreview;
+ private ImageView mScreenshotFlash;
+ private ImageView mActionsContainerBackground;
+ private HorizontalScrollView mActionsContainer;
+ private LinearLayout mActionsView;
+ private ImageView mBackgroundProtection;
+ private FrameLayout mDismissButton;
+ private ScreenshotActionChip mShareChip;
+ private ScreenshotActionChip mEditChip;
+
+ private ArrayList<ScreenshotActionChip> mSmartChips = new ArrayList<>();
+ private PendingInteraction mPendingInteraction;
+
+ private enum PendingInteraction {
+ PREVIEW,
+ EDIT,
+ SHARE
+ }
+
+ public ScreenshotView(Context context) {
+ this(context, null);
+ }
+
+ public ScreenshotView(Context context, AttributeSet attrs) {
+ this(context, attrs, 0);
+ }
+
+ public ScreenshotView(Context context, AttributeSet attrs, int defStyleAttr) {
+ this(context, attrs, defStyleAttr, 0);
+ }
+
+ public ScreenshotView(
+ Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
+ super(context, attrs, defStyleAttr, defStyleRes);
+ mResources = mContext.getResources();
+
+ mCornerSizeX = mResources.getDimensionPixelSize(R.dimen.global_screenshot_x_scale);
+ mDismissDeltaY = mResources.getDimensionPixelSize(
+ R.dimen.screenshot_dismissal_height_delta);
+
+ // standard material ease
+ mFastOutSlowIn =
+ AnimationUtils.loadInterpolator(mContext, android.R.interpolator.fast_out_slow_in);
+
+ mDisplayMetrics = new DisplayMetrics();
+ mContext.getDisplay().getRealMetrics(mDisplayMetrics);
+ }
+
+ @Override // ViewTreeObserver.OnComputeInternalInsetsListener
+ public void onComputeInternalInsets(ViewTreeObserver.InternalInsetsInfo inoutInfo) {
+ inoutInfo.setTouchableInsets(ViewTreeObserver.InternalInsetsInfo.TOUCHABLE_INSETS_REGION);
+ Region touchRegion = new Region();
+
+ Rect screenshotRect = new Rect();
+ mScreenshotPreview.getBoundsOnScreen(screenshotRect);
+ touchRegion.op(screenshotRect, Region.Op.UNION);
+ Rect actionsRect = new Rect();
+ mActionsContainer.getBoundsOnScreen(actionsRect);
+ touchRegion.op(actionsRect, Region.Op.UNION);
+ Rect dismissRect = new Rect();
+ mDismissButton.getBoundsOnScreen(dismissRect);
+ touchRegion.op(dismissRect, Region.Op.UNION);
+
+ if (QuickStepContract.isGesturalMode(mNavMode)) {
+ // Receive touches in gesture insets such that they don't cause TOUCH_OUTSIDE
+ Rect inset = new Rect(0, 0, mLeftInset, mDisplayMetrics.heightPixels);
+ touchRegion.op(inset, Region.Op.UNION);
+ inset.set(mDisplayMetrics.widthPixels - mRightInset, 0, mDisplayMetrics.widthPixels,
+ mDisplayMetrics.heightPixels);
+ touchRegion.op(inset, Region.Op.UNION);
+ }
+
+ inoutInfo.touchableRegion.set(touchRegion);
+ }
+
+ @Override // View
+ protected void onFinishInflate() {
+ mScreenshotAnimatedView = requireNonNull(
+ findViewById(R.id.global_screenshot_animated_view));
+ mScreenshotPreview = requireNonNull(findViewById(R.id.global_screenshot_preview));
+ mActionsContainerBackground = requireNonNull(findViewById(
+ R.id.global_screenshot_actions_container_background));
+ mActionsContainer = requireNonNull(findViewById(R.id.global_screenshot_actions_container));
+ mActionsView = requireNonNull(findViewById(R.id.global_screenshot_actions));
+ mBackgroundProtection = requireNonNull(
+ findViewById(R.id.global_screenshot_actions_background));
+ mDismissButton = requireNonNull(findViewById(R.id.global_screenshot_dismiss_button));
+ mScreenshotFlash = requireNonNull(findViewById(R.id.global_screenshot_flash));
+ mScreenshotSelectorView = requireNonNull(findViewById(R.id.global_screenshot_selector));
+ mShareChip = requireNonNull(mActionsContainer.findViewById(R.id.screenshot_share_chip));
+ mEditChip = requireNonNull(mActionsContainer.findViewById(R.id.screenshot_edit_chip));
+
+ mScreenshotAnimatedView.setClipToOutline(true);
+ mScreenshotAnimatedView.setOutlineProvider(new ViewOutlineProvider() {
+ @Override
+ public void getOutline(View view, Outline outline) {
+ outline.setRoundRect(new Rect(0, 0, view.getWidth(), view.getHeight()),
+ ROUNDED_CORNER_RADIUS * view.getWidth());
+ }
+ });
+ mScreenshotPreview.setClipToOutline(true);
+ mScreenshotPreview.setOutlineProvider(new ViewOutlineProvider() {
+ @Override
+ public void getOutline(View view, Outline outline) {
+ outline.setRoundRect(new Rect(0, 0, view.getWidth(), view.getHeight()),
+ ROUNDED_CORNER_RADIUS * view.getWidth());
+ }
+ });
+
+ setFocusable(true);
+ mScreenshotSelectorView.setFocusable(true);
+ mScreenshotSelectorView.setFocusableInTouchMode(true);
+ mScreenshotAnimatedView.setPivotX(0);
+ mScreenshotAnimatedView.setPivotY(0);
+ mActionsContainer.setScrollX(0);
+
+ mNavMode = getResources().getInteger(
+ com.android.internal.R.integer.config_navBarInteractionMode);
+ mOrientationPortrait =
+ getResources().getConfiguration().orientation == ORIENTATION_PORTRAIT;
+ mDirectionLTR =
+ getResources().getConfiguration().getLayoutDirection() == View.LAYOUT_DIRECTION_LTR;
+
+ setOnApplyWindowInsetsListener((v, insets) -> {
+ if (QuickStepContract.isGesturalMode(mNavMode)) {
+ Insets gestureInsets = insets.getInsets(
+ WindowInsets.Type.systemGestures());
+ mLeftInset = gestureInsets.left;
+ mRightInset = gestureInsets.right;
+ } else {
+ mLeftInset = mRightInset = 0;
+ }
+ return ScreenshotView.this.onApplyWindowInsets(insets);
+ });
+
+ // Get focus so that the key events go to the layout.
+ setFocusableInTouchMode(true);
+ requestFocus();
+ }
+
+ void takePartialScreenshot(Consumer<Rect> onPartialScreenshotSelected) {
+ mScreenshotSelectorView.setOnScreenshotSelected(onPartialScreenshotSelected);
+ mScreenshotSelectorView.setVisibility(View.VISIBLE);
+ mScreenshotSelectorView.requestFocus();
+ }
+
+ void prepareForAnimation(Bitmap bitmap, Rect screenRect, Insets screenInsets) {
+ mScreenshotAnimatedView.setImageDrawable(
+ createScreenDrawable(mResources, bitmap, screenInsets));
+ setAnimatedViewSize(screenRect.width(), screenRect.height());
+
+ // will show when the animation starts
+ mScreenshotAnimatedView.setVisibility(View.GONE);
+
+ mScreenshotPreview.setImageDrawable(createScreenDrawable(mResources, bitmap, screenInsets));
+ // make static preview invisible (from gone) so we can query its location on screen
+ mScreenshotPreview.setVisibility(View.INVISIBLE);
+ }
+
+ AnimatorSet createScreenshotDropInAnimation(Rect bounds, boolean showFlash,
+ Consumer<ScreenshotEvent> onElementTapped) {
+ mScreenshotPreview.setLayerType(View.LAYER_TYPE_HARDWARE, null);
+ mScreenshotPreview.buildLayer();
+
+ Rect previewBounds = new Rect();
+ mScreenshotPreview.getBoundsOnScreen(previewBounds);
+
+ float cornerScale =
+ mCornerSizeX / (mOrientationPortrait ? bounds.width() : bounds.height());
+ final float currentScale = 1f;
+
+ mScreenshotAnimatedView.setScaleX(currentScale);
+ mScreenshotAnimatedView.setScaleY(currentScale);
+
+ mDismissButton.setAlpha(0);
+ mDismissButton.setVisibility(View.VISIBLE);
+
+ AnimatorSet dropInAnimation = new AnimatorSet();
+ ValueAnimator flashInAnimator = ValueAnimator.ofFloat(0, 1);
+ flashInAnimator.setDuration(SCREENSHOT_FLASH_IN_DURATION_MS);
+ flashInAnimator.setInterpolator(mFastOutSlowIn);
+ flashInAnimator.addUpdateListener(animation ->
+ mScreenshotFlash.setAlpha((float) animation.getAnimatedValue()));
+
+ ValueAnimator flashOutAnimator = ValueAnimator.ofFloat(1, 0);
+ flashOutAnimator.setDuration(SCREENSHOT_FLASH_OUT_DURATION_MS);
+ flashOutAnimator.setInterpolator(mFastOutSlowIn);
+ flashOutAnimator.addUpdateListener(animation ->
+ mScreenshotFlash.setAlpha((float) animation.getAnimatedValue()));
+
+ // animate from the current location, to the static preview location
+ final PointF startPos = new PointF(bounds.centerX(), bounds.centerY());
+ final PointF finalPos = new PointF(previewBounds.centerX(), previewBounds.centerY());
+
+ ValueAnimator toCorner = ValueAnimator.ofFloat(0, 1);
+ toCorner.setDuration(SCREENSHOT_TO_CORNER_Y_DURATION_MS);
+ float xPositionPct =
+ SCREENSHOT_TO_CORNER_X_DURATION_MS / (float) SCREENSHOT_TO_CORNER_Y_DURATION_MS;
+ float dismissPct =
+ SCREENSHOT_TO_CORNER_DISMISS_DELAY_MS / (float) SCREENSHOT_TO_CORNER_Y_DURATION_MS;
+ float scalePct =
+ SCREENSHOT_TO_CORNER_SCALE_DURATION_MS / (float) SCREENSHOT_TO_CORNER_Y_DURATION_MS;
+ toCorner.addUpdateListener(animation -> {
+ float t = animation.getAnimatedFraction();
+ if (t < scalePct) {
+ float scale = MathUtils.lerp(
+ currentScale, cornerScale, mFastOutSlowIn.getInterpolation(t / scalePct));
+ mScreenshotAnimatedView.setScaleX(scale);
+ mScreenshotAnimatedView.setScaleY(scale);
+ } else {
+ mScreenshotAnimatedView.setScaleX(cornerScale);
+ mScreenshotAnimatedView.setScaleY(cornerScale);
+ }
+
+ float currentScaleX = mScreenshotAnimatedView.getScaleX();
+ float currentScaleY = mScreenshotAnimatedView.getScaleY();
+
+ if (t < xPositionPct) {
+ float xCenter = MathUtils.lerp(startPos.x, finalPos.x,
+ mFastOutSlowIn.getInterpolation(t / xPositionPct));
+ mScreenshotAnimatedView.setX(xCenter - bounds.width() * currentScaleX / 2f);
+ } else {
+ mScreenshotAnimatedView.setX(finalPos.x - bounds.width() * currentScaleX / 2f);
+ }
+ float yCenter = MathUtils.lerp(
+ startPos.y, finalPos.y, mFastOutSlowIn.getInterpolation(t));
+ mScreenshotAnimatedView.setY(yCenter - bounds.height() * currentScaleY / 2f);
+
+ if (t >= dismissPct) {
+ mDismissButton.setAlpha((t - dismissPct) / (1 - dismissPct));
+ float currentX = mScreenshotAnimatedView.getX();
+ float currentY = mScreenshotAnimatedView.getY();
+ mDismissButton.setY(currentY - mDismissButton.getHeight() / 2f);
+ if (mDirectionLTR) {
+ mDismissButton.setX(currentX
+ + bounds.width() * currentScaleX - mDismissButton.getWidth() / 2f);
+ } else {
+ mDismissButton.setX(currentX - mDismissButton.getWidth() / 2f);
+ }
+ }
+ });
+
+ toCorner.addListener(new AnimatorListenerAdapter() {
+ @Override
+ public void onAnimationStart(Animator animation) {
+ super.onAnimationStart(animation);
+ mScreenshotAnimatedView.setVisibility(View.VISIBLE);
+ }
+ });
+
+ mScreenshotFlash.setAlpha(0f);
+ mScreenshotFlash.setVisibility(View.VISIBLE);
+
+ if (showFlash) {
+ dropInAnimation.play(flashOutAnimator).after(flashInAnimator);
+ dropInAnimation.play(flashOutAnimator).with(toCorner);
+ } else {
+ dropInAnimation.play(toCorner);
+ }
+
+ dropInAnimation.addListener(new AnimatorListenerAdapter() {
+ @Override
+ public void onAnimationEnd(Animator animation) {
+ super.onAnimationEnd(animation);
+ mDismissButton.setOnClickListener(view ->
+ onElementTapped.accept(ScreenshotEvent.SCREENSHOT_EXPLICIT_DISMISSAL));
+ mDismissButton.setAlpha(1);
+ float dismissOffset = mDismissButton.getWidth() / 2f;
+ float finalDismissX = mDirectionLTR
+ ? finalPos.x - dismissOffset + bounds.width() * cornerScale / 2f
+ : finalPos.x - dismissOffset - bounds.width() * cornerScale / 2f;
+ mDismissButton.setX(finalDismissX);
+ mDismissButton.setY(
+ finalPos.y - dismissOffset - bounds.height() * cornerScale / 2f);
+ mScreenshotAnimatedView.setScaleX(1);
+ mScreenshotAnimatedView.setScaleY(1);
+ mScreenshotAnimatedView.setX(finalPos.x - bounds.width() * cornerScale / 2f);
+ mScreenshotAnimatedView.setY(finalPos.y - bounds.height() * cornerScale / 2f);
+ mScreenshotAnimatedView.setVisibility(View.GONE);
+ mScreenshotPreview.setVisibility(View.VISIBLE);
+ forceLayout();
+ createScreenshotActionsShadeAnimation().start();
+ }
+ });
+
+ return dropInAnimation;
+ }
+
+ ValueAnimator createScreenshotActionsShadeAnimation() {
+ // By default the activities won't be able to start immediately; override this to keep
+ // the same behavior as if started from a notification
+ try {
+ ActivityManager.getService().resumeAppSwitches();
+ } catch (RemoteException e) {
+ }
+
+ ArrayList<ScreenshotActionChip> chips = new ArrayList<>();
+
+ mShareChip.setText(mContext.getString(com.android.internal.R.string.share));
+ mShareChip.setIcon(Icon.createWithResource(mContext, R.drawable.ic_screenshot_share), true);
+ mShareChip.setOnClickListener(v -> {
+ mShareChip.setIsPending(true);
+ mEditChip.setIsPending(false);
+ mPendingInteraction = PendingInteraction.SHARE;
+ });
+ chips.add(mShareChip);
+
+ mEditChip.setText(mContext.getString(com.android.internal.R.string.screenshot_edit));
+ mEditChip.setIcon(Icon.createWithResource(mContext, R.drawable.ic_screenshot_edit), true);
+ mEditChip.setOnClickListener(v -> {
+ mEditChip.setIsPending(true);
+ mShareChip.setIsPending(false);
+ mPendingInteraction = PendingInteraction.EDIT;
+ });
+ chips.add(mEditChip);
+
+ mScreenshotPreview.setOnClickListener(v -> {
+ mShareChip.setIsPending(false);
+ mEditChip.setIsPending(false);
+ mPendingInteraction = PendingInteraction.PREVIEW;
+ });
+
+ // remove the margin from the last chip so that it's correctly aligned with the end
+ LinearLayout.LayoutParams params = (LinearLayout.LayoutParams)
+ mActionsView.getChildAt(0).getLayoutParams();
+ params.setMarginEnd(0);
+ mActionsView.getChildAt(0).setLayoutParams(params);
+
+ ValueAnimator animator = ValueAnimator.ofFloat(0, 1);
+ animator.setDuration(SCREENSHOT_ACTIONS_EXPANSION_DURATION_MS);
+ float alphaFraction = (float) SCREENSHOT_ACTIONS_ALPHA_DURATION_MS
+ / SCREENSHOT_ACTIONS_EXPANSION_DURATION_MS;
+ mActionsContainer.setAlpha(0f);
+ mActionsContainerBackground.setAlpha(0f);
+ mActionsContainer.setVisibility(View.VISIBLE);
+ mActionsContainerBackground.setVisibility(View.VISIBLE);
+
+ animator.addUpdateListener(animation -> {
+ float t = animation.getAnimatedFraction();
+ mBackgroundProtection.setAlpha(t);
+ float containerAlpha = t < alphaFraction ? t / alphaFraction : 1;
+ mActionsContainer.setAlpha(containerAlpha);
+ mActionsContainerBackground.setAlpha(containerAlpha);
+ float containerScale = SCREENSHOT_ACTIONS_START_SCALE_X
+ + (t * (1 - SCREENSHOT_ACTIONS_START_SCALE_X));
+ mActionsContainer.setScaleX(containerScale);
+ mActionsContainerBackground.setScaleX(containerScale);
+ for (ScreenshotActionChip chip : chips) {
+ chip.setAlpha(t);
+ chip.setScaleX(1 / containerScale); // invert to keep size of children constant
+ }
+ mActionsContainer.setScrollX(mDirectionLTR ? 0 : mActionsContainer.getWidth());
+ mActionsContainer.setPivotX(mDirectionLTR ? 0 : mActionsContainer.getWidth());
+ mActionsContainerBackground.setPivotX(
+ mDirectionLTR ? 0 : mActionsContainerBackground.getWidth());
+ });
+ return animator;
+ }
+
+ void setChipIntents(ScreenshotController.SavedImageData imageData,
+ Consumer<ScreenshotEvent> onElementTapped) {
+ mShareChip.setPendingIntent(imageData.shareAction.actionIntent,
+ () -> onElementTapped.accept(ScreenshotEvent.SCREENSHOT_SHARE_TAPPED));
+ mEditChip.setPendingIntent(imageData.editAction.actionIntent,
+ () -> onElementTapped.accept(ScreenshotEvent.SCREENSHOT_EDIT_TAPPED));
+ mScreenshotPreview.setOnClickListener(v -> {
+ try {
+ imageData.editAction.actionIntent.send();
+ } catch (PendingIntent.CanceledException e) {
+ Log.e(TAG, "Intent cancelled", e);
+ }
+ onElementTapped.accept(ScreenshotEvent.SCREENSHOT_PREVIEW_TAPPED);
+ });
+
+ if (mPendingInteraction != null) {
+ switch (mPendingInteraction) {
+ case PREVIEW:
+ mScreenshotPreview.callOnClick();
+ break;
+ case SHARE:
+ mShareChip.callOnClick();
+ break;
+ case EDIT:
+ mEditChip.callOnClick();
+ break;
+ }
+ } else {
+ LayoutInflater inflater = LayoutInflater.from(mContext);
+
+ for (Notification.Action smartAction : imageData.smartActions) {
+ ScreenshotActionChip actionChip = (ScreenshotActionChip) inflater.inflate(
+ R.layout.global_screenshot_action_chip, mActionsView, false);
+ actionChip.setText(smartAction.title);
+ actionChip.setIcon(smartAction.getIcon(), false);
+ actionChip.setPendingIntent(smartAction.actionIntent,
+ () -> onElementTapped.accept(
+ ScreenshotEvent.SCREENSHOT_SMART_ACTION_TAPPED));
+ mActionsView.addView(actionChip);
+ mSmartChips.add(actionChip);
+ }
+ }
+ }
+
+
+ AnimatorSet createScreenshotDismissAnimation() {
+ ValueAnimator alphaAnim = ValueAnimator.ofFloat(0, 1);
+ alphaAnim.setStartDelay(SCREENSHOT_DISMISS_ALPHA_OFFSET_MS);
+ alphaAnim.setDuration(SCREENSHOT_DISMISS_ALPHA_DURATION_MS);
+ alphaAnim.addUpdateListener(animation -> {
+ setAlpha(1 - animation.getAnimatedFraction());
+ });
+
+ ValueAnimator yAnim = ValueAnimator.ofFloat(0, 1);
+ yAnim.setInterpolator(mAccelerateInterpolator);
+ yAnim.setDuration(SCREENSHOT_DISMISS_Y_DURATION_MS);
+ float screenshotStartY = mScreenshotPreview.getTranslationY();
+ float dismissStartY = mDismissButton.getTranslationY();
+ yAnim.addUpdateListener(animation -> {
+ float yDelta = MathUtils.lerp(0, mDismissDeltaY, animation.getAnimatedFraction());
+ mScreenshotPreview.setTranslationY(screenshotStartY + yDelta);
+ mDismissButton.setTranslationY(dismissStartY + yDelta);
+ mActionsContainer.setTranslationY(yDelta);
+ mActionsContainerBackground.setTranslationY(yDelta);
+ });
+
+ AnimatorSet animSet = new AnimatorSet();
+ animSet.play(yAnim).with(alphaAnim);
+
+ return animSet;
+ }
+
+ void reset() {
+ // Clear any references to the bitmap
+ mScreenshotPreview.setImageDrawable(null);
+ mScreenshotAnimatedView.setImageDrawable(null);
+ mScreenshotAnimatedView.setVisibility(View.GONE);
+ mActionsContainerBackground.setVisibility(View.GONE);
+ mActionsContainer.setVisibility(View.GONE);
+ mBackgroundProtection.setAlpha(0f);
+ mDismissButton.setVisibility(View.GONE);
+ mScreenshotPreview.setVisibility(View.GONE);
+ mScreenshotPreview.setLayerType(View.LAYER_TYPE_NONE, null);
+ mScreenshotPreview.setContentDescription(
+ mContext.getResources().getString(R.string.screenshot_preview_description));
+ mScreenshotPreview.setOnClickListener(null);
+ mShareChip.setOnClickListener(null);
+ mEditChip.setOnClickListener(null);
+ mShareChip.setIsPending(false);
+ mEditChip.setIsPending(false);
+ mPendingInteraction = null;
+ for (ScreenshotActionChip chip : mSmartChips) {
+ mActionsView.removeView(chip);
+ }
+ mSmartChips.clear();
+ setAlpha(1);
+ mDismissButton.setTranslationY(0);
+ mActionsContainer.setTranslationY(0);
+ mActionsContainerBackground.setTranslationY(0);
+ mScreenshotPreview.setTranslationY(0);
+ mScreenshotSelectorView.stop();
+ }
+
+ private void setAnimatedViewSize(int width, int height) {
+ ViewGroup.LayoutParams layoutParams = mScreenshotAnimatedView.getLayoutParams();
+ layoutParams.width = width;
+ layoutParams.height = height;
+ mScreenshotAnimatedView.setLayoutParams(layoutParams);
+ }
+
+ /**
+ * Create a drawable using the size of the bitmap and insets as the fractional inset parameters.
+ */
+ private static Drawable createScreenDrawable(Resources res, Bitmap bitmap, Insets insets) {
+ int insettedWidth = bitmap.getWidth() - insets.left - insets.right;
+ int insettedHeight = bitmap.getHeight() - insets.top - insets.bottom;
+
+ BitmapDrawable bitmapDrawable = new BitmapDrawable(res, bitmap);
+ if (insettedHeight == 0 || insettedWidth == 0 || bitmap.getWidth() == 0
+ || bitmap.getHeight() == 0) {
+ Log.e(TAG, String.format(
+ "Can't create insetted drawable, using 0 insets "
+ + "bitmap and insets create degenerate region: %dx%d %s",
+ bitmap.getWidth(), bitmap.getHeight(), insets));
+ return bitmapDrawable;
+ }
+
+ InsetDrawable insetDrawable = new InsetDrawable(bitmapDrawable,
+ -1f * insets.left / insettedWidth,
+ -1f * insets.top / insettedHeight,
+ -1f * insets.right / insettedWidth,
+ -1f * insets.bottom / insettedHeight);
+
+ if (insets.left < 0 || insets.top < 0 || insets.right < 0 || insets.bottom < 0) {
+ // Are any of the insets negative, meaning the bitmap is smaller than the bounds so need
+ // to fill in the background of the drawable.
+ return new LayerDrawable(new Drawable[]{
+ new ColorDrawable(Color.BLACK), insetDrawable});
+ } else {
+ return insetDrawable;
+ }
+ }
+
+}
diff --git a/packages/SystemUI/src/com/android/systemui/screenshot/SmartActionsReceiver.java b/packages/SystemUI/src/com/android/systemui/screenshot/SmartActionsReceiver.java
index 217235b16ecf..f32529fdaf04 100644
--- a/packages/SystemUI/src/com/android/systemui/screenshot/SmartActionsReceiver.java
+++ b/packages/SystemUI/src/com/android/systemui/screenshot/SmartActionsReceiver.java
@@ -16,9 +16,9 @@
package com.android.systemui.screenshot;
-import static com.android.systemui.screenshot.GlobalScreenshot.EXTRA_ACTION_INTENT;
-import static com.android.systemui.screenshot.GlobalScreenshot.EXTRA_ACTION_TYPE;
-import static com.android.systemui.screenshot.GlobalScreenshot.EXTRA_ID;
+import static com.android.systemui.screenshot.ScreenshotController.EXTRA_ACTION_INTENT;
+import static com.android.systemui.screenshot.ScreenshotController.EXTRA_ACTION_TYPE;
+import static com.android.systemui.screenshot.ScreenshotController.EXTRA_ID;
import android.app.ActivityOptions;
import android.app.PendingIntent;
diff --git a/packages/SystemUI/src/com/android/systemui/screenshot/TakeScreenshotService.java b/packages/SystemUI/src/com/android/systemui/screenshot/TakeScreenshotService.java
index a043f0f1e50c..4e2283396e25 100644
--- a/packages/SystemUI/src/com/android/systemui/screenshot/TakeScreenshotService.java
+++ b/packages/SystemUI/src/com/android/systemui/screenshot/TakeScreenshotService.java
@@ -52,7 +52,7 @@ import javax.inject.Inject;
public class TakeScreenshotService extends Service {
private static final String TAG = "TakeScreenshotService";
- private final GlobalScreenshot mScreenshot;
+ private final ScreenshotController mScreenshot;
private final UserManager mUserManager;
private final UiEventLogger mUiEventLogger;
@@ -61,7 +61,7 @@ public class TakeScreenshotService extends Service {
@Override
public void onReceive(Context context, Intent intent) {
if (ACTION_CLOSE_SYSTEM_DIALOGS.equals(intent.getAction()) && mScreenshot != null) {
- mScreenshot.dismissScreenshot("close system dialogs", false);
+ mScreenshot.dismissScreenshot(false);
}
}
};
@@ -125,7 +125,7 @@ public class TakeScreenshotService extends Service {
};
@Inject
- public TakeScreenshotService(GlobalScreenshot globalScreenshot, UserManager userManager,
+ public TakeScreenshotService(ScreenshotController globalScreenshot, UserManager userManager,
UiEventLogger uiEventLogger) {
mScreenshot = globalScreenshot;
mUserManager = userManager;
@@ -144,7 +144,9 @@ public class TakeScreenshotService extends Service {
@Override
public boolean onUnbind(Intent intent) {
- if (mScreenshot != null) mScreenshot.stopScreenshot();
+ if (mScreenshot != null && !mScreenshot.isDismissing()) {
+ mScreenshot.dismissScreenshot(true);
+ }
unregisterReceiver(mBroadcastReceiver);
return true;
}
diff --git a/packages/SystemUI/src/com/android/systemui/settings/BrightnessController.java b/packages/SystemUI/src/com/android/systemui/settings/BrightnessController.java
index 1bea72aea2ba..72034f84fd30 100644
--- a/packages/SystemUI/src/com/android/systemui/settings/BrightnessController.java
+++ b/packages/SystemUI/src/com/android/systemui/settings/BrightnessController.java
@@ -50,6 +50,8 @@ import com.android.systemui.broadcast.BroadcastDispatcher;
import java.util.ArrayList;
+import javax.inject.Inject;
+
public class BrightnessController implements ToggleSlider.Listener {
private static final String TAG = "StatusBar.BrightnessController";
private static final int SLIDER_ANIMATION_DURATION = 3000;
@@ -475,4 +477,20 @@ public class BrightnessController implements ToggleSlider.Listener {
mSliderAnimator.start();
}
+ /** Factory for creating a {@link BrightnessController}. */
+ public static class Factory {
+ private final Context mContext;
+ private final BroadcastDispatcher mBroadcastDispatcher;
+
+ @Inject
+ public Factory(Context context, BroadcastDispatcher broadcastDispatcher) {
+ mContext = context;
+ mBroadcastDispatcher = broadcastDispatcher;
+ }
+
+ /** Create a {@link BrightnessController} */
+ public BrightnessController create(ToggleSlider toggleSlider) {
+ return new BrightnessController(mContext, toggleSlider, mBroadcastDispatcher);
+ }
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/MediaTransferManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/MediaTransferManager.java
deleted file mode 100644
index 1b1a51b8a57b..000000000000
--- a/packages/SystemUI/src/com/android/systemui/statusbar/MediaTransferManager.java
+++ /dev/null
@@ -1,212 +0,0 @@
-/*
- * Copyright (C) 2019 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.systemui.statusbar;
-
-import android.content.Context;
-import android.content.res.ColorStateList;
-import android.graphics.drawable.Drawable;
-import android.graphics.drawable.GradientDrawable;
-import android.graphics.drawable.RippleDrawable;
-import android.service.notification.StatusBarNotification;
-import android.util.FeatureFlagUtils;
-import android.util.Log;
-import android.view.View;
-import android.view.ViewGroup;
-import android.view.ViewParent;
-import android.widget.ImageView;
-import android.widget.LinearLayout;
-import android.widget.TextView;
-
-import com.android.settingslib.bluetooth.LocalBluetoothManager;
-import com.android.settingslib.media.InfoMediaManager;
-import com.android.settingslib.media.LocalMediaManager;
-import com.android.settingslib.media.MediaDevice;
-import com.android.settingslib.widget.AdaptiveIcon;
-import com.android.systemui.Dependency;
-import com.android.systemui.media.dialog.MediaOutputDialogFactory;
-import com.android.systemui.statusbar.notification.collection.NotificationEntry;
-import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
-
-import java.util.ArrayList;
-import java.util.List;
-
-/**
- * Class for handling MediaTransfer state over a set of notifications.
- */
-public class MediaTransferManager {
- private final Context mContext;
- private final MediaOutputDialogFactory mMediaOutputDialogFactory;
- private MediaDevice mDevice;
- private List<View> mViews = new ArrayList<>();
- private LocalMediaManager mLocalMediaManager;
-
- private static final String TAG = "MediaTransferManager";
-
- private final View.OnClickListener mOnClickHandler = new View.OnClickListener() {
- @Override
- public void onClick(View view) {
- if (handleMediaTransfer(view)) {
- return;
- }
- }
-
- private boolean handleMediaTransfer(View view) {
- if (view.findViewById(com.android.internal.R.id.media_seamless) == null) {
- return false;
- }
-
- ViewParent parent = view.getParent();
- StatusBarNotification statusBarNotification =
- getRowForParent(parent).getEntry().getSbn();
- mMediaOutputDialogFactory.create(statusBarNotification.getPackageName(), true);
- return true;
- }
- };
-
- private final LocalMediaManager.DeviceCallback mMediaDeviceCallback =
- new LocalMediaManager.DeviceCallback() {
- @Override
- public void onDeviceListUpdate(List<MediaDevice> devices) {
- MediaDevice currentDevice = mLocalMediaManager.getCurrentConnectedDevice();
- // Check because this can be called several times while changing devices
- if (mDevice == null || !mDevice.equals(currentDevice)) {
- mDevice = currentDevice;
- updateAllChips();
- }
- }
-
- @Override
- public void onSelectedDeviceStateChanged(MediaDevice device, int state) {
- if (mDevice == null || !mDevice.equals(device)) {
- mDevice = device;
- updateAllChips();
- }
- }
- };
-
- public MediaTransferManager(Context context) {
- mContext = context;
- mMediaOutputDialogFactory = Dependency.get(MediaOutputDialogFactory.class);
- LocalBluetoothManager lbm = Dependency.get(LocalBluetoothManager.class);
- InfoMediaManager imm = new InfoMediaManager(mContext, null, null, lbm);
- mLocalMediaManager = new LocalMediaManager(mContext, lbm, imm, null);
- }
-
- /**
- * Mark a view as removed. If no views remain the media device listener will be unregistered.
- * @param root
- */
- public void setRemoved(View root) {
- if (!FeatureFlagUtils.isEnabled(mContext, FeatureFlagUtils.SEAMLESS_TRANSFER)
- || mLocalMediaManager == null || root == null) {
- return;
- }
- View view = root.findViewById(com.android.internal.R.id.media_seamless);
- if (mViews.remove(view)) {
- if (mViews.size() == 0) {
- mLocalMediaManager.unregisterCallback(mMediaDeviceCallback);
- }
- } else {
- Log.e(TAG, "Tried to remove unknown view " + view);
- }
- }
-
- private ExpandableNotificationRow getRowForParent(ViewParent parent) {
- while (parent != null) {
- if (parent instanceof ExpandableNotificationRow) {
- return ((ExpandableNotificationRow) parent);
- }
- parent = parent.getParent();
- }
- return null;
- }
-
- /**
- * apply the action button for MediaTransfer
- *
- * @param root The parent container of the view.
- * @param entry The entry of MediaTransfer action button.
- */
- public void applyMediaTransferView(ViewGroup root, NotificationEntry entry) {
- if (!FeatureFlagUtils.isEnabled(mContext, FeatureFlagUtils.SEAMLESS_TRANSFER)
- || mLocalMediaManager == null || root == null) {
- return;
- }
-
- View view = root.findViewById(com.android.internal.R.id.media_seamless);
- if (view == null) {
- return;
- }
-
- view.setVisibility(View.VISIBLE);
- view.setOnClickListener(mOnClickHandler);
- if (!mViews.contains(view)) {
- mViews.add(view);
- if (mViews.size() == 1) {
- mLocalMediaManager.registerCallback(mMediaDeviceCallback);
- }
- }
-
- // Initial update
- mLocalMediaManager.startScan();
- mDevice = mLocalMediaManager.getCurrentConnectedDevice();
- updateChip(view);
- }
-
- private void updateAllChips() {
- for (View view : mViews) {
- updateChip(view);
- }
- }
-
- private void updateChip(View view) {
- ExpandableNotificationRow enr = getRowForParent(view.getParent());
- int fgColor = enr.getNotificationHeader().getOriginalIconColor();
- ColorStateList fgTintList = ColorStateList.valueOf(fgColor);
- int bgColor = enr.getCurrentBackgroundTint();
-
- // Update outline color
- LinearLayout viewLayout = (LinearLayout) view;
- RippleDrawable bkgDrawable = (RippleDrawable) viewLayout.getBackground();
- GradientDrawable rect = (GradientDrawable) bkgDrawable.getDrawable(0);
- rect.setStroke(2, fgColor);
- rect.setColor(bgColor);
-
- ImageView iconView = view.findViewById(com.android.internal.R.id.media_seamless_image);
- TextView deviceName = view.findViewById(com.android.internal.R.id.media_seamless_text);
- deviceName.setTextColor(fgTintList);
-
- if (mDevice != null) {
- Drawable icon = mDevice.getIcon();
- iconView.setVisibility(View.VISIBLE);
- iconView.setImageTintList(fgTintList);
-
- if (icon instanceof AdaptiveIcon) {
- AdaptiveIcon aIcon = (AdaptiveIcon) icon;
- aIcon.setBackgroundColor(bgColor);
- iconView.setImageDrawable(aIcon);
- } else {
- iconView.setImageDrawable(icon);
- }
- deviceName.setText(mDevice.getName());
- } else {
- // Reset to default
- iconView.setVisibility(View.GONE);
- deviceName.setText(com.android.internal.R.string.ext_media_seamless_action);
- }
- }
-}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationHeaderUtil.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationHeaderUtil.java
index 670a65f55844..597658276d49 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationHeaderUtil.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationHeaderUtil.java
@@ -17,18 +17,16 @@
package com.android.systemui.statusbar;
import android.app.Notification;
-import android.content.res.Configuration;
-import android.graphics.PorterDuff;
import android.graphics.drawable.Icon;
import android.text.TextUtils;
-import android.view.NotificationHeaderView;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.TextView;
-import com.android.internal.util.ContrastColorUtil;
+import com.android.internal.widget.CachingIconView;
import com.android.internal.widget.ConversationLayout;
+import com.android.internal.widget.NotificationExpandButton;
import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
import com.android.systemui.statusbar.notification.row.NotificationContentView;
@@ -67,32 +65,14 @@ public class NotificationHeaderUtil {
private final static ResultApplicator mGreyApplicator = new ResultApplicator() {
@Override
public void apply(View parent, View view, boolean apply, boolean reset) {
- NotificationHeaderView header = (NotificationHeaderView) view;
- ImageView icon = (ImageView) view.findViewById(
- com.android.internal.R.id.icon);
- ImageView expand = (ImageView) view.findViewById(
- com.android.internal.R.id.expand_button);
- applyToChild(icon, apply, header.getOriginalIconColor());
- applyToChild(expand, apply, header.getOriginalNotificationColor());
- }
-
- private void applyToChild(View view, boolean shouldApply, int originalColor) {
- if (originalColor != NotificationHeaderView.NO_COLOR) {
- ImageView imageView = (ImageView) view;
- imageView.getDrawable().mutate();
- if (shouldApply) {
- // lets gray it out
- Configuration config = view.getContext().getResources().getConfiguration();
- boolean inNightMode = (config.uiMode & Configuration.UI_MODE_NIGHT_MASK)
- == Configuration.UI_MODE_NIGHT_YES;
- int grey = ContrastColorUtil.resolveColor(view.getContext(),
- Notification.COLOR_DEFAULT, inNightMode);
- imageView.getDrawable().setColorFilter(grey, PorterDuff.Mode.SRC_ATOP);
- } else {
- // lets reset it
- imageView.getDrawable().setColorFilter(originalColor,
- PorterDuff.Mode.SRC_ATOP);
- }
+ CachingIconView icon = view.findViewById(com.android.internal.R.id.icon);
+ if (icon != null) {
+ icon.setGrayedOut(apply);
+ }
+ NotificationExpandButton expand =
+ view.findViewById(com.android.internal.R.id.expand_button);
+ if (expand != null) {
+ expand.setGrayedOut(apply);
}
}
};
@@ -178,7 +158,7 @@ public class NotificationHeaderUtil {
private void sanitizeHeaderViews(ExpandableNotificationRow row) {
if (row.isSummaryWithChildren()) {
- sanitizeHeader(row.getNotificationHeader());
+ sanitizeHeader(row.getNotificationViewWrapper().getNotificationHeader());
return;
}
final NotificationContentView layout = row.getPrivateLayout();
@@ -275,7 +255,8 @@ public class NotificationHeaderUtil {
}
public void init() {
- mParentView = mParentRow.getNotificationHeader().findViewById(mId);
+ mParentView = mParentRow.getNotificationViewWrapper().getNotificationHeader()
+ .findViewById(mId);
mParentData = mExtractor == null ? null : mExtractor.extractData(mParentRow);
mApply = !mComparator.isEmpty(mParentView);
}
@@ -305,7 +286,7 @@ public class NotificationHeaderUtil {
public void apply(ExpandableNotificationRow row, boolean reset) {
boolean apply = mApply && !reset;
if (row.isSummaryWithChildren()) {
- applyToView(apply, reset, row.getNotificationHeader());
+ applyToView(apply, reset, row.getNotificationViewWrapper().getNotificationHeader());
return;
}
applyToView(apply, reset, row.getPrivateLayout().getContractedChild());
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/ViewTransformationHelper.java b/packages/SystemUI/src/com/android/systemui/statusbar/ViewTransformationHelper.java
index 83e51cd43ed2..7ecdc812cbd3 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/ViewTransformationHelper.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/ViewTransformationHelper.java
@@ -106,12 +106,8 @@ public class ViewTransformationHelper implements TransformableView,
mViewTransformationAnimation.cancel();
}
mViewTransformationAnimation = ValueAnimator.ofFloat(0.0f, 1.0f);
- mViewTransformationAnimation.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
- @Override
- public void onAnimationUpdate(ValueAnimator animation) {
- transformTo(notification, animation.getAnimatedFraction());
- }
- });
+ mViewTransformationAnimation.addUpdateListener(
+ animation -> transformTo(notification, animation.getAnimatedFraction()));
mViewTransformationAnimation.setInterpolator(Interpolators.LINEAR);
mViewTransformationAnimation.setDuration(StackStateAnimator.ANIMATION_DURATION_STANDARD);
mViewTransformationAnimation.addListener(new AnimatorListenerAdapter() {
@@ -167,12 +163,8 @@ public class ViewTransformationHelper implements TransformableView,
mViewTransformationAnimation.cancel();
}
mViewTransformationAnimation = ValueAnimator.ofFloat(0.0f, 1.0f);
- mViewTransformationAnimation.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
- @Override
- public void onAnimationUpdate(ValueAnimator animation) {
- transformFrom(notification, animation.getAnimatedFraction());
- }
- });
+ mViewTransformationAnimation.addUpdateListener(
+ animation -> transformFrom(notification, animation.getAnimatedFraction()));
mViewTransformationAnimation.addListener(new AnimatorListenerAdapter() {
public boolean mCancelled;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRow.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRow.java
index ba88f628d632..f788dfe47a61 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRow.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRow.java
@@ -304,7 +304,6 @@ public class ExpandableNotificationRow extends ActivatableNotificationView
}
}
};
- private boolean mForceUnlocked;
private boolean mKeepInParent;
private boolean mRemoved;
private static final Property<ExpandableNotificationRow, Float> TRANSLATE_CONTENT =
@@ -410,8 +409,14 @@ public class ExpandableNotificationRow extends ActivatableNotificationView
setIconAnimationRunning(running, l);
}
if (mIsSummaryWithChildren) {
- setIconAnimationRunningForChild(running, mChildrenContainer.getHeaderView());
- setIconAnimationRunningForChild(running, mChildrenContainer.getLowPriorityHeaderView());
+ NotificationViewWrapper viewWrapper = mChildrenContainer.getNotificationViewWrapper();
+ if (viewWrapper != null) {
+ setIconAnimationRunningForChild(running, viewWrapper.getIcon());
+ }
+ NotificationViewWrapper lowPriWrapper = mChildrenContainer.getLowPriorityViewWrapper();
+ if (lowPriWrapper != null) {
+ setIconAnimationRunningForChild(running, lowPriWrapper.getIcon());
+ }
List<ExpandableNotificationRow> notificationChildren =
mChildrenContainer.getAttachedChildren();
for (int i = 0; i < notificationChildren.size(); i++) {
@@ -435,10 +440,9 @@ public class ExpandableNotificationRow extends ActivatableNotificationView
private void setIconAnimationRunningForChild(boolean running, View child) {
if (child != null) {
- ImageView icon = (ImageView) child.findViewById(com.android.internal.R.id.icon);
+ ImageView icon = child.findViewById(com.android.internal.R.id.icon);
setIconRunning(icon, running);
- ImageView rightIcon = (ImageView) child.findViewById(
- com.android.internal.R.id.right_icon);
+ ImageView rightIcon = child.findViewById(com.android.internal.R.id.right_icon);
setIconRunning(rightIcon, running);
}
}
@@ -594,7 +598,7 @@ public class ExpandableNotificationRow extends ActivatableNotificationView
public int getOriginalIconColor() {
if (mIsSummaryWithChildren && !shouldShowPublic()) {
- return mChildrenContainer.getVisibleHeader().getOriginalIconColor();
+ return mChildrenContainer.getVisibleWrapper().getOriginalIconColor();
}
int color = getShowingLayout().getOriginalIconColor();
if (color != Notification.COLOR_INVALID) {
@@ -1040,22 +1044,25 @@ public class ExpandableNotificationRow extends ActivatableNotificationView
}
}
- public NotificationHeaderView getNotificationHeader() {
+ /**
+ * @return the main notification view wrapper.
+ */
+ public NotificationViewWrapper getNotificationViewWrapper() {
if (mIsSummaryWithChildren) {
- return mChildrenContainer.getHeaderView();
+ return mChildrenContainer.getNotificationViewWrapper();
}
- return mPrivateLayout.getNotificationHeader();
+ return mPrivateLayout.getNotificationViewWrapper();
}
/**
- * @return the currently visible notification header. This can be different from
- * {@link #getNotificationHeader()} in case it is a low-priority group.
+ * @return the currently visible notification view wrapper. This can be different from
+ * {@link #getNotificationViewWrapper()} in case it is a low-priority group.
*/
- public NotificationHeaderView getVisibleNotificationHeader() {
+ public NotificationViewWrapper getVisibleNotificationViewWrapper() {
if (mIsSummaryWithChildren && !shouldShowPublic()) {
- return mChildrenContainer.getVisibleHeader();
+ return mChildrenContainer.getVisibleWrapper();
}
- return getShowingLayout().getVisibleNotificationHeader();
+ return getShowingLayout().getVisibleWrapper();
}
public void setLongPressListener(LongPressListener longPressListener) {
@@ -1294,16 +1301,6 @@ public class ExpandableNotificationRow extends ActivatableNotificationView
onAttachedChildrenCountChanged();
}
- public void setForceUnlocked(boolean forceUnlocked) {
- mForceUnlocked = forceUnlocked;
- if (mIsSummaryWithChildren) {
- List<ExpandableNotificationRow> notificationChildren = getAttachedChildren();
- for (ExpandableNotificationRow child : notificationChildren) {
- child.setForceUnlocked(forceUnlocked);
- }
- }
- }
-
@Override
public void dismiss(boolean refocusOnDismiss) {
super.dismiss(refocusOnDismiss);
@@ -1422,7 +1419,7 @@ public class ExpandableNotificationRow extends ActivatableNotificationView
@Override
public View getShelfTransformationTarget() {
if (mIsSummaryWithChildren && !shouldShowPublic()) {
- return mChildrenContainer.getVisibleHeader().getIcon();
+ return mChildrenContainer.getVisibleWrapper().getShelfTransformationTarget();
}
return getShowingLayout().getShelfTransformationTarget();
}
@@ -1693,37 +1690,30 @@ public class ExpandableNotificationRow extends ActivatableNotificationView
@Override
protected void onFinishInflate() {
super.onFinishInflate();
- mPublicLayout = (NotificationContentView) findViewById(R.id.expandedPublic);
- mPrivateLayout = (NotificationContentView) findViewById(R.id.expanded);
+ mPublicLayout = findViewById(R.id.expandedPublic);
+ mPrivateLayout = findViewById(R.id.expanded);
mLayouts = new NotificationContentView[] {mPrivateLayout, mPublicLayout};
for (NotificationContentView l : mLayouts) {
l.setExpandClickListener(mExpandClickListener);
l.setContainingNotification(this);
}
- mGutsStub = (ViewStub) findViewById(R.id.notification_guts_stub);
- mGutsStub.setOnInflateListener(new ViewStub.OnInflateListener() {
- @Override
- public void onInflate(ViewStub stub, View inflated) {
- mGuts = (NotificationGuts) inflated;
- mGuts.setClipTopAmount(getClipTopAmount());
- mGuts.setActualHeight(getActualHeight());
- mGutsStub = null;
- }
+ mGutsStub = findViewById(R.id.notification_guts_stub);
+ mGutsStub.setOnInflateListener((stub, inflated) -> {
+ mGuts = (NotificationGuts) inflated;
+ mGuts.setClipTopAmount(getClipTopAmount());
+ mGuts.setActualHeight(getActualHeight());
+ mGutsStub = null;
});
- mChildrenContainerStub = (ViewStub) findViewById(R.id.child_container_stub);
- mChildrenContainerStub.setOnInflateListener(new ViewStub.OnInflateListener() {
+ mChildrenContainerStub = findViewById(R.id.child_container_stub);
+ mChildrenContainerStub.setOnInflateListener((stub, inflated) -> {
+ mChildrenContainer = (NotificationChildrenContainer) inflated;
+ mChildrenContainer.setIsLowPriority(mIsLowPriority);
+ mChildrenContainer.setContainingNotification(ExpandableNotificationRow.this);
+ mChildrenContainer.onNotificationUpdated();
- @Override
- public void onInflate(ViewStub stub, View inflated) {
- mChildrenContainer = (NotificationChildrenContainer) inflated;
- mChildrenContainer.setIsLowPriority(mIsLowPriority);
- mChildrenContainer.setContainingNotification(ExpandableNotificationRow.this);
- mChildrenContainer.onNotificationUpdated();
-
- if (mShouldTranslateContents) {
- mTranslateableViews.add(mChildrenContainer);
- }
+ if (mShouldTranslateContents) {
+ mTranslateableViews.add(mChildrenContainer);
}
});
@@ -2183,7 +2173,7 @@ public class ExpandableNotificationRow extends ActivatableNotificationView
}
public boolean isUserLocked() {
- return mUserLocked && !mForceUnlocked;
+ return mUserLocked;
}
public void setUserLocked(boolean userLocked) {
@@ -2303,8 +2293,12 @@ public class ExpandableNotificationRow extends ActivatableNotificationView
private void onAttachedChildrenCountChanged() {
mIsSummaryWithChildren = mChildrenContainer != null
&& mChildrenContainer.getNotificationChildCount() > 0;
- if (mIsSummaryWithChildren && mChildrenContainer.getHeaderView() == null) {
- mChildrenContainer.recreateNotificationHeader(mExpandClickListener, isConversation());
+ if (mIsSummaryWithChildren) {
+ NotificationViewWrapper wrapper = mChildrenContainer.getNotificationViewWrapper();
+ if (wrapper == null || wrapper.getNotificationHeader() == null) {
+ mChildrenContainer.recreateNotificationHeader(mExpandClickListener,
+ isConversation());
+ }
}
getShowingLayout().updateBackgroundColor(false /* animate */);
mPrivateLayout.updateExpandButtons(isExpandable());
@@ -2414,9 +2408,9 @@ public class ExpandableNotificationRow extends ActivatableNotificationView
* the top.
*/
private void updateContentShiftHeight() {
- NotificationHeaderView notificationHeader = getVisibleNotificationHeader();
- if (notificationHeader != null) {
- CachingIconView icon = notificationHeader.getIcon();
+ NotificationViewWrapper wrapper = getVisibleNotificationViewWrapper();
+ CachingIconView icon = wrapper == null ? null : wrapper.getIcon();
+ if (icon != null) {
mIconTransformContentShift = getRelativeTopPadding(icon) + icon.getHeight();
} else {
mIconTransformContentShift = mContentShift;
@@ -2504,12 +2498,7 @@ public class ExpandableNotificationRow extends ActivatableNotificationView
.alpha(0f)
.setStartDelay(delay)
.setDuration(duration)
- .withEndAction(new Runnable() {
- @Override
- public void run() {
- hiddenView.setVisibility(View.INVISIBLE);
- }
- });
+ .withEndAction(() -> hiddenView.setVisibility(View.INVISIBLE));
}
for (View showView : shownChildren) {
showView.setVisibility(View.VISIBLE);
@@ -2867,7 +2856,7 @@ public class ExpandableNotificationRow extends ActivatableNotificationView
}
float x = event.getX();
float y = event.getY();
- NotificationHeaderView header = getVisibleNotificationHeader();
+ NotificationHeaderView header = getVisibleNotificationViewWrapper().getNotificationHeader();
if (header != null && header.isInTouchRect(x - getTranslation(), y)) {
return true;
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationContentView.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationContentView.java
index 8a644ed4d3ff..160b6f78d9a3 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationContentView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationContentView.java
@@ -44,7 +44,6 @@ import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.util.ContrastColorUtil;
import com.android.systemui.Dependency;
import com.android.systemui.R;
-import com.android.systemui.statusbar.MediaTransferManager;
import com.android.systemui.statusbar.RemoteInputController;
import com.android.systemui.statusbar.SmartReplyController;
import com.android.systemui.statusbar.TransformableView;
@@ -173,12 +172,10 @@ public class NotificationContentView extends FrameLayout {
private boolean mIsContentExpandable;
private boolean mRemoteInputVisible;
private int mUnrestrictedContentHeight;
- private MediaTransferManager mMediaTransferManager;
public NotificationContentView(Context context, AttributeSet attrs) {
super(context, attrs);
mHybridGroupManager = new HybridGroupManager(getContext());
- mMediaTransferManager = new MediaTransferManager(getContext());
mSmartReplyConstants = Dependency.get(SmartReplyConstants.class);
mSmartReplyController = Dependency.get(SmartReplyController.class);
initView();
@@ -1021,6 +1018,10 @@ public class NotificationContentView extends FrameLayout {
mSingleLineView };
}
+ public NotificationViewWrapper getVisibleWrapper() {
+ return getVisibleWrapper(mVisibleType);
+ }
+
public NotificationViewWrapper getVisibleWrapper(int visibleType) {
switch (visibleType) {
case VISIBLE_TYPE_EXPANDED:
@@ -1157,7 +1158,6 @@ public class NotificationContentView extends FrameLayout {
mHeadsUpWrapper.onContentUpdated(row);
}
applyRemoteInputAndSmartReply(entry);
- applyMediaTransfer(entry);
updateLegacy();
mForceSelectNextLayout = true;
mPreviousExpandedRemoteInputIntent = null;
@@ -1185,22 +1185,6 @@ public class NotificationContentView extends FrameLayout {
}
}
- private void applyMediaTransfer(final NotificationEntry entry) {
- if (!entry.isMediaNotification()) {
- return;
- }
-
- View bigContentView = mExpandedChild;
- if (bigContentView != null && (bigContentView instanceof ViewGroup)) {
- mMediaTransferManager.applyMediaTransferView((ViewGroup) bigContentView, entry);
- }
-
- View smallContentView = mContractedChild;
- if (smallContentView != null && (smallContentView instanceof ViewGroup)) {
- mMediaTransferManager.applyMediaTransferView((ViewGroup) smallContentView, entry);
- }
- }
-
/**
* Returns whether the {@link Notification} represented by entry has a free-form remote input.
* Such an input can be used e.g. to implement smart reply buttons - by passing the replies
@@ -1561,18 +1545,20 @@ public class NotificationContentView extends FrameLayout {
mIsContentExpandable = expandable;
}
- public NotificationHeaderView getNotificationHeader() {
- NotificationHeaderView header = null;
- if (mContractedChild != null) {
- header = mContractedWrapper.getNotificationHeader();
+ /**
+ * @return a view wrapper for one of the inflated states of the notification.
+ */
+ public NotificationViewWrapper getNotificationViewWrapper() {
+ if (mContractedChild != null && mContractedWrapper != null) {
+ return mContractedWrapper;
}
- if (header == null && mExpandedChild != null) {
- header = mExpandedWrapper.getNotificationHeader();
+ if (mExpandedChild != null && mExpandedWrapper != null) {
+ return mExpandedWrapper;
}
- if (header == null && mHeadsUpChild != null) {
- header = mHeadsUpWrapper.getNotificationHeader();
+ if (mHeadsUpChild != null && mHeadsUpWrapper != null) {
+ return mHeadsUpWrapper;
}
- return header;
+ return null;
}
public void showFeedbackIcon(boolean show) {
@@ -1600,11 +1586,6 @@ public class NotificationContentView extends FrameLayout {
}
}
- public NotificationHeaderView getVisibleNotificationHeader() {
- NotificationViewWrapper wrapper = getVisibleWrapper(mVisibleType);
- return wrapper == null ? null : wrapper.getNotificationHeader();
- }
-
public void setContainingNotification(ExpandableNotificationRow containingNotification) {
mContainingNotification = containingNotification;
}
@@ -1662,11 +1643,9 @@ public class NotificationContentView extends FrameLayout {
}
if (mExpandedWrapper != null) {
mExpandedWrapper.setRemoved();
- mMediaTransferManager.setRemoved(mExpandedChild);
}
if (mContractedWrapper != null) {
mContractedWrapper.setRemoved();
- mMediaTransferManager.setRemoved(mContractedChild);
}
if (mHeadsUpWrapper != null) {
mHeadsUpWrapper.setRemoved();
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationBigTextTemplateViewWrapper.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationBigTextTemplateViewWrapper.java
index 41f93cceacc7..d58c183f27e3 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationBigTextTemplateViewWrapper.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationBigTextTemplateViewWrapper.java
@@ -37,7 +37,7 @@ public class NotificationBigTextTemplateViewWrapper extends NotificationTemplate
}
private void resolveViews(StatusBarNotification notification) {
- mBigtext = (ImageFloatingTextView) mView.findViewById(com.android.internal.R.id.big_text);
+ mBigtext = mView.findViewById(com.android.internal.R.id.big_text);
}
@Override
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationHeaderViewWrapper.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationHeaderViewWrapper.java
index 3f5867477f16..8c8275628fac 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationHeaderViewWrapper.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationHeaderViewWrapper.java
@@ -55,8 +55,6 @@ public class NotificationHeaderViewWrapper extends NotificationViewWrapper {
protected final ViewTransformationHelper mTransformationHelper;
- protected int mColor;
-
private CachingIconView mIcon;
private NotificationExpandButton mExpandButton;
protected NotificationHeaderView mNotificationHeader;
@@ -119,7 +117,6 @@ public class NotificationHeaderViewWrapper extends NotificationViewWrapper {
mFeedbackIcon = mView.findViewById(com.android.internal.R.id.feedback);
if (mNotificationHeader != null) {
mNotificationHeader.setShowExpandButtonAtEnd(mShowExpandButtonAtEnd);
- mColor = mNotificationHeader.getOriginalIconColor();
}
}
@@ -279,6 +276,11 @@ public class NotificationHeaderViewWrapper extends NotificationViewWrapper {
}
@Override
+ public void setExpanded(boolean expanded) {
+ mExpandButton.setExpanded(expanded);
+ }
+
+ @Override
public void setRecentlyAudiblyAlerted(boolean audiblyAlerted) {
if (mAudiblyAlertedIcon != null) {
mAudiblyAlertedIcon.setVisibility(audiblyAlerted ? View.VISIBLE : View.GONE);
@@ -296,6 +298,11 @@ public class NotificationHeaderViewWrapper extends NotificationViewWrapper {
}
@Override
+ public CachingIconView getIcon() {
+ return mIcon;
+ }
+
+ @Override
public int getOriginalIconColor() {
return mIcon.getOriginalIconColor();
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationMediaTemplateViewWrapper.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationMediaTemplateViewWrapper.java
index 33c939054be5..2535e5ddc3d1 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationMediaTemplateViewWrapper.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationMediaTemplateViewWrapper.java
@@ -370,7 +370,7 @@ public class NotificationMediaTemplateViewWrapper extends NotificationTemplateVi
return;
}
- int tintColor = getNotificationHeader().getOriginalIconColor();
+ int tintColor = getOriginalIconColor();
mSeekBarElapsedTime.setTextColor(tintColor);
mSeekBarTotalTime.setTextColor(tintColor);
mSeekBarTotalTime.setShadowLayer(1.5f, 1.5f, 1.5f, mBackgroundColor);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationTemplateViewWrapper.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationTemplateViewWrapper.java
index 14aab9d62dfd..76ec59e0ec28 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationTemplateViewWrapper.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationTemplateViewWrapper.java
@@ -140,13 +140,13 @@ public class NotificationTemplateViewWrapper extends NotificationHeaderViewWrapp
}
private void resolveTemplateViews(StatusBarNotification notification) {
- mPicture = (ImageView) mView.findViewById(com.android.internal.R.id.right_icon);
+ mPicture = mView.findViewById(com.android.internal.R.id.right_icon);
if (mPicture != null) {
mPicture.setTag(ImageTransformState.ICON_TAG,
notification.getNotification().getLargeIcon());
}
- mTitle = (TextView) mView.findViewById(com.android.internal.R.id.title);
- mText = (TextView) mView.findViewById(com.android.internal.R.id.text);
+ mTitle = mView.findViewById(com.android.internal.R.id.title);
+ mText = mView.findViewById(com.android.internal.R.id.text);
final View progress = mView.findViewById(com.android.internal.R.id.progress);
if (progress instanceof ProgressBar) {
mProgressBar = (ProgressBar) progress;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationViewWrapper.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationViewWrapper.java
index 42f5e389d5a8..6920e3f4a7c6 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationViewWrapper.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationViewWrapper.java
@@ -29,7 +29,6 @@ import android.graphics.Rect;
import android.graphics.drawable.ColorDrawable;
import android.graphics.drawable.Drawable;
import android.os.Build;
-import android.util.ArraySet;
import android.view.NotificationHeaderView;
import android.view.View;
import android.view.ViewGroup;
@@ -38,7 +37,7 @@ import android.widget.TextView;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.graphics.ColorUtils;
import com.android.internal.util.ContrastColorUtil;
-import com.android.internal.widget.ConversationLayout;
+import com.android.internal.widget.CachingIconView;
import com.android.systemui.statusbar.CrossFadeHelper;
import com.android.systemui.statusbar.TransformableView;
import com.android.systemui.statusbar.notification.TransformState;
@@ -67,8 +66,7 @@ public abstract class NotificationViewWrapper implements TransformableView {
} else if ("messaging".equals(v.getTag())) {
return new NotificationMessagingTemplateViewWrapper(ctx, v, row);
} else if ("conversation".equals(v.getTag())) {
- return new NotificationConversationTemplateViewWrapper(ctx, (ConversationLayout) v,
- row);
+ return new NotificationConversationTemplateViewWrapper(ctx, v, row);
}
Class<? extends Notification.Style> style =
row.getEntry().getSbn().getNotification().getNotificationStyle();
@@ -231,6 +229,9 @@ public abstract class NotificationViewWrapper implements TransformableView {
*/
public void updateExpandability(boolean expandable, View.OnClickListener onClickListener) {}
+ /** Set the expanded state on the view wrapper */
+ public void setExpanded(boolean expanded) {}
+
/**
* @return the notification header if it exists
*/
@@ -241,7 +242,16 @@ public abstract class NotificationViewWrapper implements TransformableView {
/**
* @return the expand button if it exists
*/
- public @Nullable View getExpandButton() {
+ @Nullable
+ public View getExpandButton() {
+ return null;
+ }
+
+ /**
+ * @return the icon if it exists
+ */
+ @Nullable
+ public CachingIconView getIcon() {
return null;
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationChildrenContainer.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationChildrenContainer.java
index a396305a49b6..00bccfc1a323 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationChildrenContainer.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationChildrenContainer.java
@@ -31,6 +31,7 @@ import android.widget.RemoteViews;
import android.widget.TextView;
import com.android.internal.annotations.VisibleForTesting;
+import com.android.internal.widget.CachingIconView;
import com.android.systemui.R;
import com.android.systemui.statusbar.CrossFadeHelper;
import com.android.systemui.statusbar.NotificationHeaderUtil;
@@ -318,9 +319,8 @@ public class NotificationChildrenContainer extends ViewGroup {
RemoteViews header = builder.makeNotificationHeader();
if (mNotificationHeader == null) {
mNotificationHeader = (NotificationHeaderView) header.apply(getContext(), this);
- final View expandButton = mNotificationHeader.findViewById(
- com.android.internal.R.id.expand_button);
- expandButton.setVisibility(VISIBLE);
+ mNotificationHeader.findViewById(com.android.internal.R.id.expand_button)
+ .setVisibility(VISIBLE);
mNotificationHeader.setOnClickListener(mHeaderClickListener);
mNotificationHeaderWrapper = NotificationViewWrapper.wrap(getContext(),
mNotificationHeader, mContainingNotification);
@@ -361,9 +361,8 @@ public class NotificationChildrenContainer extends ViewGroup {
if (mNotificationHeaderLowPriority == null) {
mNotificationHeaderLowPriority = (NotificationHeaderView) header.apply(getContext(),
this);
- final View expandButton = mNotificationHeaderLowPriority.findViewById(
- com.android.internal.R.id.expand_button);
- expandButton.setVisibility(VISIBLE);
+ mNotificationHeaderLowPriority.findViewById(com.android.internal.R.id.expand_button)
+ .setVisibility(VISIBLE);
mNotificationHeaderLowPriority.setOnClickListener(mHeaderClickListener);
mNotificationHeaderWrapperLowPriority = NotificationViewWrapper.wrap(getContext(),
mNotificationHeaderLowPriority, mContainingNotification);
@@ -849,8 +848,8 @@ public class NotificationChildrenContainer extends ViewGroup {
public void setChildrenExpanded(boolean childrenExpanded) {
mChildrenExpanded = childrenExpanded;
updateExpansionStates();
- if (mNotificationHeader != null) {
- mNotificationHeader.setExpanded(childrenExpanded);
+ if (mNotificationHeaderWrapper != null) {
+ mNotificationHeaderWrapper.setExpanded(childrenExpanded);
}
final int count = mAttachedChildren.size();
for (int childIdx = 0; childIdx < count; childIdx++) {
@@ -869,12 +868,12 @@ public class NotificationChildrenContainer extends ViewGroup {
return mContainingNotification;
}
- public NotificationHeaderView getHeaderView() {
- return mNotificationHeader;
+ public NotificationViewWrapper getNotificationViewWrapper() {
+ return mNotificationHeaderWrapper;
}
- public NotificationHeaderView getLowPriorityHeaderView() {
- return mNotificationHeaderLowPriority;
+ public NotificationViewWrapper getLowPriorityViewWrapper() {
+ return mNotificationHeaderWrapperLowPriority;
}
@VisibleForTesting
@@ -1224,16 +1223,15 @@ public class NotificationChildrenContainer extends ViewGroup {
public void setShelfIconVisible(boolean iconVisible) {
if (mNotificationHeaderWrapper != null) {
- NotificationHeaderView header = mNotificationHeaderWrapper.getNotificationHeader();
- if (header != null) {
- header.getIcon().setForceHidden(iconVisible);
+ CachingIconView icon = mNotificationHeaderWrapper.getIcon();
+ if (icon != null) {
+ icon.setForceHidden(iconVisible);
}
}
if (mNotificationHeaderWrapperLowPriority != null) {
- NotificationHeaderView header
- = mNotificationHeaderWrapperLowPriority.getNotificationHeader();
- if (header != null) {
- header.getIcon().setForceHidden(iconVisible);
+ CachingIconView icon = mNotificationHeaderWrapperLowPriority.getIcon();
+ if (icon != null) {
+ icon.setForceHidden(iconVisible);
}
}
}
@@ -1254,12 +1252,14 @@ public class NotificationChildrenContainer extends ViewGroup {
}
}
- public NotificationHeaderView getVisibleHeader() {
- NotificationHeaderView header = mNotificationHeader;
+ /**
+ * @return the view wrapper for the currently showing priority.
+ */
+ public NotificationViewWrapper getVisibleWrapper() {
if (showingAsLowPriority()) {
- header = mNotificationHeaderLowPriority;
+ return mNotificationHeaderWrapperLowPriority;
}
- return header;
+ return mNotificationHeaderWrapper;
}
public void onExpansionChanged() {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBouncer.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBouncer.java
index af6ac223ada1..2767b7e1627d 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBouncer.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBouncer.java
@@ -38,9 +38,9 @@ import com.android.keyguard.KeyguardUpdateMonitor;
import com.android.keyguard.KeyguardUpdateMonitorCallback;
import com.android.keyguard.ViewMediatorCallback;
import com.android.keyguard.dagger.KeyguardBouncerComponent;
-import com.android.keyguard.dagger.RootView;
import com.android.systemui.DejankUtils;
import com.android.systemui.biometrics.AuthController;
+import com.android.systemui.dagger.qualifiers.RootView;
import com.android.systemui.keyguard.DismissCallbackRegistry;
import com.android.systemui.plugins.FalsingManager;
import com.android.systemui.shared.system.SysUiStatsLog;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarPolicy.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarPolicy.java
index e42c3dc4f589..6ed092f33d95 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarPolicy.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarPolicy.java
@@ -671,14 +671,18 @@ public class PhoneStatusBarPolicy
mIconController.setIconVisibility(mSlotCamera, showCamera);
mIconController.setIconVisibility(mSlotMicrophone, showMicrophone);
- if (mPrivacyItemController.getAllIndicatorsAvailable()) {
+ if (mPrivacyItemController.getAllIndicatorsAvailable()
+ || mPrivacyItemController.getLocationAvailable()) {
mIconController.setIconVisibility(mSlotLocation, showLocation);
}
}
@Override
public void onLocationActiveChanged(boolean active) {
- if (!mPrivacyItemController.getAllIndicatorsAvailable()) updateLocationFromController();
+ if (!mPrivacyItemController.getAllIndicatorsAvailable()
+ && !mPrivacyItemController.getLocationAvailable()) {
+ updateLocationFromController();
+ }
}
// Updates the status view based on the current state of location requests.
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 88a387d34f8d..c7932bb44cf4 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
@@ -172,7 +172,7 @@ import com.android.systemui.plugins.qs.QS;
import com.android.systemui.plugins.statusbar.NotificationSwipeActionHelper.SnoozeOption;
import com.android.systemui.plugins.statusbar.StatusBarStateController;
import com.android.systemui.qs.QSFragment;
-import com.android.systemui.qs.QSPanel;
+import com.android.systemui.qs.QSPanelController;
import com.android.systemui.recents.ScreenPinningRequest;
import com.android.systemui.shared.plugins.PluginManager;
import com.android.systemui.shared.system.WindowManagerWrapper;
@@ -408,7 +408,7 @@ public class StatusBar extends SystemUI implements DemoMode,
protected NotificationPanelViewController mNotificationPanelViewController;
// settings
- private QSPanel mQSPanel;
+ private QSPanelController mQSPanelController;
KeyguardIndicationController mKeyguardIndicationController;
@@ -1200,8 +1200,8 @@ public class StatusBar extends SystemUI implements DemoMode,
fragmentHostManager.addTagListener(QS.TAG, (tag, f) -> {
QS qs = (QS) f;
if (qs instanceof QSFragment) {
- mQSPanel = ((QSFragment) qs).getQsPanel();
- mQSPanel.setBrightnessMirror(mBrightnessMirrorController);
+ mQSPanelController = ((QSFragment) qs).getQSPanelController();
+ mQSPanelController.setBrightnessMirror(mBrightnessMirrorController);
}
});
}
@@ -1593,19 +1593,19 @@ public class StatusBar extends SystemUI implements DemoMode,
}
public void addQsTile(ComponentName tile) {
- if (mQSPanel != null && mQSPanel.getHost() != null) {
- mQSPanel.getHost().addTile(tile);
+ if (mQSPanelController != null && mQSPanelController.getHost() != null) {
+ mQSPanelController.getHost().addTile(tile);
}
}
public void remQsTile(ComponentName tile) {
- if (mQSPanel != null && mQSPanel.getHost() != null) {
- mQSPanel.getHost().removeTile(tile);
+ if (mQSPanelController != null && mQSPanelController.getHost() != null) {
+ mQSPanelController.getHost().removeTile(tile);
}
}
public void clickTile(ComponentName tile) {
- mQSPanel.clickTile(tile);
+ mQSPanelController.clickTile(tile);
}
/**
@@ -2197,7 +2197,7 @@ public class StatusBar extends SystemUI implements DemoMode,
if (!mUserSetup) return;
if (subPanel != null) {
- mQSPanel.openDetails(subPanel);
+ mQSPanelController.openDetails(subPanel);
}
mNotificationPanelViewController.expandWithQs();
@@ -2845,7 +2845,7 @@ public class StatusBar extends SystemUI implements DemoMode,
resetUserExpandedStates();
}
else if (DevicePolicyManager.ACTION_SHOW_DEVICE_MONITORING_DIALOG.equals(action)) {
- mQSPanel.showDeviceMonitoringDialog();
+ mQSPanelController.showDeviceMonitoringDialog();
}
Trace.endSection();
}
@@ -2936,8 +2936,8 @@ public class StatusBar extends SystemUI implements DemoMode,
*/
void updateResources() {
// Update the quick setting tiles
- if (mQSPanel != null) {
- mQSPanel.updateResources();
+ if (mQSPanelController != null) {
+ mQSPanelController.updateResources();
}
if (mStatusBarWindowController != null) {
@@ -3402,8 +3402,8 @@ public class StatusBar extends SystemUI implements DemoMode,
// Keyguard state has changed, but QS is not listening anymore. Make sure to update the tile
// visibilities so next time we open the panel we know the correct height already.
- if (mQSPanel != null) {
- mQSPanel.refreshAllTiles();
+ if (mQSPanelController != null) {
+ mQSPanelController.refreshAllTiles();
}
mHandler.removeMessages(MSG_LAUNCH_TRANSITION_TIMEOUT);
releaseGestureWakeLock();
@@ -3987,7 +3987,8 @@ public class StatusBar extends SystemUI implements DemoMode,
PackageManager pm = mContext.getPackageManager();
ResolveInfo resolveInfo = pm.resolveActivity(emergencyIntent, /*flags=*/0);
if (resolveInfo == null) {
- Log.wtf(TAG, "Couldn't find an app to process the emergency intent.");
+ // TODO(b/171084088) Upgrade log to wtf when we have default app in main branch.
+ Log.d(TAG, "Couldn't find an app to process the emergency intent.");
return;
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/MobileSignalController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/MobileSignalController.java
index eb2d9bce6c4e..6b991f8ec521 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/MobileSignalController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/MobileSignalController.java
@@ -23,7 +23,6 @@ import android.os.Handler;
import android.os.Looper;
import android.provider.Settings.Global;
import android.telephony.Annotation;
-import android.telephony.CdmaEriInformation;
import android.telephony.CellSignalStrength;
import android.telephony.CellSignalStrengthCdma;
import android.telephony.PhoneStateListener;
@@ -427,11 +426,8 @@ public class MobileSignalController extends SignalController<
if (isCarrierNetworkChangeActive()) {
return false;
}
- if (isCdma() && mServiceState != null) {
- final int iconMode = mPhone.getCdmaEriInformation().getEriIconMode();
- return mPhone.getCdmaEriInformation().getEriIconIndex() != CdmaEriInformation.ERI_OFF
- && (iconMode == CdmaEriInformation.ERI_ICON_MODE_NORMAL
- || iconMode == CdmaEriInformation.ERI_ICON_MODE_FLASH);
+ if (isCdma()) {
+ return mPhone.getCdmaEnhancedRoamingIndicatorIconIndex() != TelephonyManager.ERI_OFF;
} else {
return mServiceState != null && mServiceState.getRoaming();
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/RemoteInputView.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/RemoteInputView.java
index 9c3395f9332d..c84589a9e142 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/RemoteInputView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/RemoteInputView.java
@@ -18,11 +18,13 @@ package com.android.systemui.statusbar.policy;
import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
+import android.annotation.NonNull;
import android.annotation.Nullable;
import android.app.ActivityManager;
import android.app.Notification;
import android.app.PendingIntent;
import android.app.RemoteInput;
+import android.content.ClipData;
import android.content.ClipDescription;
import android.content.Context;
import android.content.Intent;
@@ -43,6 +45,7 @@ import android.util.Log;
import android.view.KeyEvent;
import android.view.LayoutInflater;
import android.view.MotionEvent;
+import android.view.OnReceiveContentCallback;
import android.view.View;
import android.view.ViewAnimationUtils;
import android.view.ViewGroup;
@@ -57,9 +60,6 @@ import android.widget.LinearLayout;
import android.widget.ProgressBar;
import android.widget.TextView;
-import androidx.core.view.inputmethod.InputConnectionCompat;
-import androidx.core.view.inputmethod.InputContentInfoCompat;
-
import com.android.internal.logging.MetricsLogger;
import com.android.internal.logging.nano.MetricsProto;
import com.android.internal.statusbar.IStatusBarService;
@@ -73,7 +73,9 @@ import com.android.systemui.statusbar.notification.row.wrapper.NotificationViewW
import com.android.systemui.statusbar.notification.stack.StackStateAnimator;
import com.android.systemui.statusbar.phone.LightBarController;
+import java.util.Collections;
import java.util.HashMap;
+import java.util.Set;
import java.util.function.Consumer;
/**
@@ -313,6 +315,7 @@ public class RemoteInputView extends LinearLayout implements View.OnClickListene
mRemoteInputs = remoteInputs;
mRemoteInput = remoteInput;
mEditText.setHint(mRemoteInput.getLabel());
+ mEditText.mSupportedMimeTypes = remoteInput.getAllowedDataTypes();
mEntry.editedSuggestionInfo = editedSuggestionInfo;
if (editedSuggestionInfo != null) {
@@ -571,6 +574,7 @@ public class RemoteInputView extends LinearLayout implements View.OnClickListene
boolean mShowImeOnInputConnection;
private LightBarController mLightBarController;
UserHandle mUser;
+ private Set<String> mSupportedMimeTypes;
public RemoteEditText(Context context, AttributeSet attrs) {
super(context, attrs);
@@ -578,6 +582,40 @@ public class RemoteInputView extends LinearLayout implements View.OnClickListene
mLightBarController = Dependency.get(LightBarController.class);
}
+ @Override
+ protected void onFinishInflate() {
+ super.onFinishInflate();
+ setOnReceiveContentCallback(new OnReceiveContentCallback<View>() {
+ @Override
+ public boolean onReceiveContent(@NonNull View view, @NonNull Payload payload) {
+ ClipData clip = payload.getClip();
+ if (clip.getItemCount() == 0) {
+ return false;
+ }
+ Uri contentUri = clip.getItemAt(0).getUri();
+ ClipDescription description = clip.getDescription();
+ String mimeType = null;
+ if (description.getMimeTypeCount() > 0) {
+ mimeType = description.getMimeType(0);
+ }
+ if (mimeType != null) {
+ Intent dataIntent = mRemoteInputView
+ .prepareRemoteInputFromData(mimeType, contentUri);
+ mRemoteInputView.sendRemoteInput(dataIntent);
+ }
+ return true;
+ }
+
+ @NonNull
+ @Override
+ public Set<String> getSupportedMimeTypes(@NonNull View view) {
+ return mSupportedMimeTypes != null
+ ? mSupportedMimeTypes
+ : Collections.emptySet();
+ }
+ });
+ }
+
private void defocusIfNeeded(boolean animate) {
if (mRemoteInputView != null && mRemoteInputView.mEntry.getRow().isChangingPosition()
|| isTemporarilyDetached()) {
@@ -670,36 +708,7 @@ public class RemoteInputView extends LinearLayout implements View.OnClickListene
@Override
public InputConnection onCreateInputConnection(EditorInfo outAttrs) {
- // TODO: Pass RemoteInput data types to allow image insertion.
- // String[] allowedDataTypes = mRemoteInputView.mRemoteInput.getAllowedDataTypes()
- // .toArray(new String[0]);
- // EditorInfoCompat.setContentMimeTypes(outAttrs, allowedDataTypes);
- final InputConnection inputConnection = super.onCreateInputConnection(outAttrs);
-
- final InputConnectionCompat.OnCommitContentListener callback =
- new InputConnectionCompat.OnCommitContentListener() {
- @Override
- public boolean onCommitContent(
- InputContentInfoCompat inputContentInfoCompat, int i,
- Bundle bundle) {
- Uri contentUri = inputContentInfoCompat.getContentUri();
- ClipDescription description = inputContentInfoCompat.getDescription();
- String mimeType = null;
- if (description != null && description.getMimeTypeCount() > 0) {
- mimeType = description.getMimeType(0);
- }
- if (mimeType != null) {
- Intent dataIntent = mRemoteInputView.prepareRemoteInputFromData(
- mimeType, contentUri);
- mRemoteInputView.sendRemoteInput(dataIntent);
- }
- return true;
- }
- };
-
- InputConnection ic = inputConnection == null ? null :
- InputConnectionCompat.createWrapper(inputConnection, outAttrs, callback);
-
+ final InputConnection ic = super.onCreateInputConnection(outAttrs);
Context userContext = null;
try {
userContext = mContext.createPackageContextAsUser(
@@ -747,7 +756,6 @@ public class RemoteInputView extends LinearLayout implements View.OnClickListene
} else {
setBackground(null);
}
-
}
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/tuner/TunerService.java b/packages/SystemUI/src/com/android/systemui/tuner/TunerService.java
index 70bba263ab90..b67574d1c4de 100644
--- a/packages/SystemUI/src/com/android/systemui/tuner/TunerService.java
+++ b/packages/SystemUI/src/com/android/systemui/tuner/TunerService.java
@@ -32,6 +32,7 @@ import com.android.systemui.statusbar.phone.SystemUIDialog;
public abstract class TunerService {
public static final String ACTION_CLEAR = "com.android.systemui.action.CLEAR_TUNER";
+ private final Context mContext;
public abstract void clearAll();
public abstract void destroy();
@@ -50,6 +51,10 @@ public abstract class TunerService {
void onTuningChanged(String key, String newValue);
}
+ public TunerService(Context context) {
+ mContext = context;
+ }
+
private static Context userContext(Context context, UserHandle user) {
try {
return context.createPackageContextAsUser(context.getPackageName(), 0, user);
@@ -58,6 +63,11 @@ public abstract class TunerService {
}
}
+ /** Enables or disables the tuner for the supplied user. */
+ public void setTunerEnabled(UserHandle user, boolean enabled) {
+ setTunerEnabled(mContext, user, enabled);
+ }
+
public static final void setTunerEnabled(Context context, UserHandle user, boolean enabled) {
userContext(context, user).getPackageManager().setComponentEnabledSetting(
new ComponentName(context, TunerActivity.class),
@@ -66,6 +76,11 @@ public abstract class TunerService {
PackageManager.DONT_KILL_APP);
}
+ /** Returns true if the tuner is enabled for the supplied user. */
+ public boolean isTunerEnabled(UserHandle user) {
+ return isTunerEnabled(mContext, user);
+ }
+
public static final boolean isTunerEnabled(Context context, UserHandle user) {
return userContext(context, user).getPackageManager().getComponentEnabledSetting(
new ComponentName(context, TunerActivity.class))
@@ -81,6 +96,11 @@ public abstract class TunerService {
}
}
+ /** */
+ public void showResetRequest(UserHandle user, final Runnable onDisabled) {
+ showResetRequest(mContext, user, onDisabled);
+ }
+
public static final void showResetRequest(final Context context, UserHandle user,
final Runnable onDisabled) {
SystemUIDialog dialog = new SystemUIDialog(context);
diff --git a/packages/SystemUI/src/com/android/systemui/tuner/TunerServiceImpl.java b/packages/SystemUI/src/com/android/systemui/tuner/TunerServiceImpl.java
index 22f03e074b06..027c282ba352 100644
--- a/packages/SystemUI/src/com/android/systemui/tuner/TunerServiceImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/tuner/TunerServiceImpl.java
@@ -94,6 +94,7 @@ public class TunerServiceImpl extends TunerService {
DemoModeController demoModeController,
BroadcastDispatcher broadcastDispatcher,
UserTracker userTracker) {
+ super(context);
mContext = context;
mContentResolver = mContext.getContentResolver();
mLeakDetector = leakDetector;
diff --git a/packages/SystemUI/src/com/android/systemui/tv/TvGlobalRootComponent.java b/packages/SystemUI/src/com/android/systemui/tv/TvGlobalRootComponent.java
index df741a0e98ff..89ab23b50cd8 100644
--- a/packages/SystemUI/src/com/android/systemui/tv/TvGlobalRootComponent.java
+++ b/packages/SystemUI/src/com/android/systemui/tv/TvGlobalRootComponent.java
@@ -42,6 +42,12 @@ public interface TvGlobalRootComponent extends GlobalRootComponent {
TvGlobalRootComponent build();
}
+ /**
+ * Builder for a WMComponent.
+ */
+ @Override
+ TvWMComponent.Builder getWMComponentBuilder();
+
@Override
TvSysUIComponent.Builder getSysUIComponent();
}
diff --git a/packages/SystemUI/src/com/android/systemui/tv/TvSysUIComponentModule.java b/packages/SystemUI/src/com/android/systemui/tv/TvSysUIComponentModule.java
index 334bb013ae69..9621e5f5f1a0 100644
--- a/packages/SystemUI/src/com/android/systemui/tv/TvSysUIComponentModule.java
+++ b/packages/SystemUI/src/com/android/systemui/tv/TvSysUIComponentModule.java
@@ -19,7 +19,7 @@ package com.android.systemui.tv;
import dagger.Module;
/**
- * Dagger module for including the WMComponent.
+ * Dagger module for including the SysUIComponent.
*/
@Module(subcomponents = {TvSysUIComponent.class})
public abstract class TvSysUIComponentModule {
diff --git a/packages/SystemUI/src/com/android/systemui/tv/TvSystemUIBinder.java b/packages/SystemUI/src/com/android/systemui/tv/TvSystemUIBinder.java
index bde88b1b5533..2c3ea4f452bb 100644
--- a/packages/SystemUI/src/com/android/systemui/tv/TvSystemUIBinder.java
+++ b/packages/SystemUI/src/com/android/systemui/tv/TvSystemUIBinder.java
@@ -22,7 +22,7 @@ import com.android.systemui.wmshell.TvPipModule;
import dagger.Binds;
import dagger.Module;
-@Module(includes = TvPipModule.class)
+@Module
interface TvSystemUIBinder {
@Binds
GlobalRootComponent bindGlobalRootComponent(TvGlobalRootComponent globalRootComponent);
diff --git a/packages/SystemUI/src/com/android/systemui/tv/TvSystemUIModule.java b/packages/SystemUI/src/com/android/systemui/tv/TvSystemUIModule.java
index c5bb9c1b6f48..8ffc7cf568ff 100644
--- a/packages/SystemUI/src/com/android/systemui/tv/TvSystemUIModule.java
+++ b/packages/SystemUI/src/com/android/systemui/tv/TvSystemUIModule.java
@@ -62,7 +62,6 @@ import com.android.systemui.statusbar.policy.ConfigurationController;
import com.android.systemui.statusbar.policy.DeviceProvisionedController;
import com.android.systemui.statusbar.policy.DeviceProvisionedControllerImpl;
import com.android.systemui.statusbar.policy.HeadsUpManager;
-import com.android.systemui.wmshell.TvWMShellModule;
import javax.inject.Named;
@@ -75,8 +74,7 @@ import dagger.Provides;
* overridden by the System UI implementation.
*/
@Module(includes = {
- QSModule.class,
- TvWMShellModule.class,
+ QSModule.class
},
subcomponents = {
})
diff --git a/packages/SystemUI/src/com/android/systemui/tv/TvWMComponent.java b/packages/SystemUI/src/com/android/systemui/tv/TvWMComponent.java
new file mode 100644
index 000000000000..f678513f2ce6
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/tv/TvWMComponent.java
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.tv;
+
+import com.android.systemui.dagger.WMComponent;
+import com.android.systemui.dagger.WMSingleton;
+import com.android.systemui.wmshell.TvWMShellModule;
+
+import dagger.Subcomponent;
+
+
+/**
+ * Dagger Subcomponent for WindowManager.
+ */
+@WMSingleton
+@Subcomponent(modules = {TvWMShellModule.class})
+public interface TvWMComponent extends WMComponent {
+
+ /**
+ * Builder for a SysUIComponent.
+ */
+ @Subcomponent.Builder
+ interface Builder extends WMComponent.Builder {
+ TvWMComponent build();
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/util/DeviceConfigProxy.java b/packages/SystemUI/src/com/android/systemui/util/DeviceConfigProxy.java
index 66f8f74c7cab..6b5556b3ea91 100644
--- a/packages/SystemUI/src/com/android/systemui/util/DeviceConfigProxy.java
+++ b/packages/SystemUI/src/com/android/systemui/util/DeviceConfigProxy.java
@@ -23,13 +23,19 @@ import android.content.Context;
import android.provider.DeviceConfig;
import android.provider.Settings;
+import com.android.systemui.dagger.SysUISingleton;
+
import java.util.concurrent.Executor;
+import javax.inject.Inject;
+
/**
* Wrapper around DeviceConfig useful for testing.
*/
+@SysUISingleton
public class DeviceConfigProxy {
+ @Inject
public DeviceConfigProxy() {
}
diff --git a/packages/SystemUI/src/com/android/systemui/util/InjectionInflationController.java b/packages/SystemUI/src/com/android/systemui/util/InjectionInflationController.java
index 344f0d2f5506..e79d432b3b15 100644
--- a/packages/SystemUI/src/com/android/systemui/util/InjectionInflationController.java
+++ b/packages/SystemUI/src/com/android/systemui/util/InjectionInflationController.java
@@ -24,7 +24,6 @@ import android.view.LayoutInflater;
import android.view.View;
import com.android.systemui.dagger.SysUISingleton;
-import com.android.systemui.qs.QSFooterImpl;
import com.android.systemui.qs.QSPanel;
import com.android.systemui.qs.QuickQSPanel;
import com.android.systemui.qs.customize.QSCustomizer;
@@ -92,11 +91,6 @@ public class InjectionInflationController {
}
/**
- * Creates the QSFooterImpl.
- */
- QSFooterImpl createQsFooter();
-
- /**
* Creates the NotificationStackScrollLayout.
*/
NotificationStackScrollLayout createNotificationStackScrollLayout();
diff --git a/packages/SystemUI/src/com/android/systemui/util/ViewController.java b/packages/SystemUI/src/com/android/systemui/util/ViewController.java
index c7aa780fcacb..3dbc6f101a90 100644
--- a/packages/SystemUI/src/com/android/systemui/util/ViewController.java
+++ b/packages/SystemUI/src/com/android/systemui/util/ViewController.java
@@ -16,6 +16,8 @@
package com.android.systemui.util;
+import android.content.Context;
+import android.content.res.Resources;
import android.view.View;
import android.view.View.OnAttachStateChangeListener;
@@ -75,6 +77,14 @@ public abstract class ViewController<T extends View> {
}
}
+ protected Context getContext() {
+ return mView.getContext();
+ }
+
+ protected Resources getResources() {
+ return mView.getResources();
+ }
+
/**
* Called when the view is attached and a call to {@link #init()} has been made in either order.
*/
diff --git a/packages/SystemUI/src/com/android/systemui/wmshell/TvPipModule.java b/packages/SystemUI/src/com/android/systemui/wmshell/TvPipModule.java
index 28343ed5d1f6..5310b3f2c8bb 100644
--- a/packages/SystemUI/src/com/android/systemui/wmshell/TvPipModule.java
+++ b/packages/SystemUI/src/com/android/systemui/wmshell/TvPipModule.java
@@ -20,7 +20,7 @@ import android.content.Context;
import android.os.Handler;
import android.view.LayoutInflater;
-import com.android.systemui.dagger.SysUISingleton;
+import com.android.systemui.dagger.WMSingleton;
import com.android.wm.shell.ShellTaskOrganizer;
import com.android.wm.shell.WindowManagerShellWrapper;
import com.android.wm.shell.common.DisplayController;
@@ -46,7 +46,7 @@ import dagger.Provides;
*/
@Module
public abstract class TvPipModule {
- @SysUISingleton
+ @WMSingleton
@Provides
static Optional<Pip> providePip(
Context context,
@@ -61,7 +61,7 @@ public abstract class TvPipModule {
windowManagerShellWrapper));
}
- @SysUISingleton
+ @WMSingleton
@Provides
static PipControlsViewController providePipControlsViewController(
PipControlsView pipControlsView, PipController pipController,
@@ -70,32 +70,33 @@ public abstract class TvPipModule {
handler);
}
- @SysUISingleton
+ @WMSingleton
@Provides
static PipControlsView providePipControlsView(Context context) {
return new PipControlsView(context, null);
}
- @SysUISingleton
+ @WMSingleton
@Provides
static PipNotification providePipNotification(Context context,
PipController pipController) {
return new PipNotification(context, pipController);
}
- @SysUISingleton
+ @WMSingleton
@Provides
- static PipBoundsHandler providePipBoundsHandler(Context context) {
- return new PipBoundsHandler(context);
+ static PipBoundsHandler providePipBoundsHandler(Context context,
+ PipBoundsState pipBoundsState) {
+ return new PipBoundsHandler(context, pipBoundsState);
}
- @SysUISingleton
+ @WMSingleton
@Provides
static PipBoundsState providePipBoundsState() {
return new PipBoundsState();
}
- @SysUISingleton
+ @WMSingleton
@Provides
static PipTaskOrganizer providePipTaskOrganizer(Context context,
PipBoundsState pipBoundsState,
diff --git a/packages/SystemUI/src/com/android/systemui/wmshell/TvWMShellModule.java b/packages/SystemUI/src/com/android/systemui/wmshell/TvWMShellModule.java
index 7e1a2e830660..294c749a2abe 100644
--- a/packages/SystemUI/src/com/android/systemui/wmshell/TvWMShellModule.java
+++ b/packages/SystemUI/src/com/android/systemui/wmshell/TvWMShellModule.java
@@ -20,7 +20,7 @@ import android.content.Context;
import android.os.Handler;
import android.view.IWindowManager;
-import com.android.systemui.dagger.SysUISingleton;
+import com.android.systemui.dagger.WMSingleton;
import com.android.systemui.dagger.qualifiers.Main;
import com.android.wm.shell.ShellTaskOrganizer;
import com.android.wm.shell.common.DisplayController;
@@ -40,10 +40,9 @@ import dagger.Provides;
* Provides dependencies from {@link com.android.wm.shell} which could be customized among different
* branches of SystemUI.
*/
-// TODO(b/162923491): Move most of these dependencies into WMSingleton scope.
@Module(includes = {WMShellBaseModule.class, TvPipModule.class})
public class TvWMShellModule {
- @SysUISingleton
+ @WMSingleton
@Provides
static DisplayImeController provideDisplayImeController(IWindowManager wmService,
DisplayController displayController, @Main Executor mainExecutor,
@@ -52,7 +51,7 @@ public class TvWMShellModule {
transactionPool);
}
- @SysUISingleton
+ @WMSingleton
@Provides
static SplitScreen provideSplitScreen(Context context,
DisplayController displayController, SystemWindows systemWindows,
diff --git a/packages/SystemUI/src/com/android/systemui/wmshell/WMShell.java b/packages/SystemUI/src/com/android/systemui/wmshell/WMShell.java
index 3c4c3fcdf4f4..89ea9e24ea51 100644
--- a/packages/SystemUI/src/com/android/systemui/wmshell/WMShell.java
+++ b/packages/SystemUI/src/com/android/systemui/wmshell/WMShell.java
@@ -65,7 +65,6 @@ import com.android.systemui.statusbar.policy.UserInfoController;
import com.android.systemui.tracing.ProtoTracer;
import com.android.systemui.tracing.nano.SystemUiTraceProto;
import com.android.wm.shell.ShellTaskOrganizer;
-import com.android.wm.shell.common.DisplayImeController;
import com.android.wm.shell.nano.WmShellTraceProto;
import com.android.wm.shell.onehanded.OneHanded;
import com.android.wm.shell.onehanded.OneHandedEvents;
@@ -101,19 +100,18 @@ public final class WMShell extends SystemUI
private final CommandQueue mCommandQueue;
private final ConfigurationController mConfigurationController;
- private final DisplayImeController mDisplayImeController;
private final InputConsumerController mInputConsumerController;
private final KeyguardUpdateMonitor mKeyguardUpdateMonitor;
private final TaskStackChangeListeners mTaskStackChangeListeners;
private final NavigationModeController mNavigationModeController;
private final ScreenLifecycle mScreenLifecycle;
private final SysUiState mSysUiState;
+ // TODO: This is only here because we need to dump state. Remove and replace with a dumper
+ // interface.
+ private final ShellTaskOrganizer mShellTaskOrganizer;
private final Optional<Pip> mPipOptional;
private final Optional<SplitScreen> mSplitScreenOptional;
private final Optional<OneHanded> mOneHandedOptional;
- // Inject the organizer directly in case the optionals aren't loaded to depend on it. There
- // are non-optional windowing features like FULLSCREEN.
- private final ShellTaskOrganizer mShellTaskOrganizer;
private final ProtoTracer mProtoTracer;
private boolean mIsSysUiStateValid;
private KeyguardUpdateMonitorCallback mSplitScreenKeyguardCallback;
@@ -126,7 +124,6 @@ public final class WMShell extends SystemUI
InputConsumerController inputConsumerController,
KeyguardUpdateMonitor keyguardUpdateMonitor,
TaskStackChangeListeners taskStackChangeListeners,
- DisplayImeController displayImeController,
NavigationModeController navigationModeController,
ScreenLifecycle screenLifecycle,
SysUiState sysUiState,
@@ -141,7 +138,6 @@ public final class WMShell extends SystemUI
mInputConsumerController = inputConsumerController;
mKeyguardUpdateMonitor = keyguardUpdateMonitor;
mTaskStackChangeListeners = taskStackChangeListeners;
- mDisplayImeController = displayImeController;
mNavigationModeController = navigationModeController;
mScreenLifecycle = screenLifecycle;
mSysUiState = sysUiState;
@@ -156,10 +152,6 @@ public final class WMShell extends SystemUI
@Override
public void start() {
mCommandQueue.addCallback(this);
- // This is to prevent circular init problem by separating registration step out of its
- // constructor. And make sure the initialization of DisplayImeController won't depend on
- // specific feature anymore.
- mDisplayImeController.startMonitorDisplays();
mPipOptional.ifPresent(this::initPip);
mSplitScreenOptional.ifPresent(this::initSplitScreen);
mOneHandedOptional.ifPresent(this::initOneHanded);
@@ -201,6 +193,7 @@ public final class WMShell extends SystemUI
}
});
+ // TODO: Move this into the shell
// Handle for system task stack changes.
mTaskStackChangeListeners.registerTaskStackListener(
new TaskStackChangeListener() {
@@ -417,6 +410,11 @@ public final class WMShell extends SystemUI
return;
}
// Dump WMShell stuff here if no commands were handled
+ mShellTaskOrganizer.dump(pw, "");
+ pw.println();
+ pw.println();
+ mPipOptional.ifPresent(pip -> pip.dump(pw));
+ mSplitScreenOptional.ifPresent(splitScreen -> splitScreen.dump(pw));
mOneHandedOptional.ifPresent(oneHanded -> oneHanded.dump(pw));
}
diff --git a/packages/SystemUI/src/com/android/systemui/wmshell/WMShellBaseModule.java b/packages/SystemUI/src/com/android/systemui/wmshell/WMShellBaseModule.java
index ac6e5ded3de3..b333f8b36226 100644
--- a/packages/SystemUI/src/com/android/systemui/wmshell/WMShellBaseModule.java
+++ b/packages/SystemUI/src/com/android/systemui/wmshell/WMShellBaseModule.java
@@ -20,21 +20,16 @@ import android.app.IActivityManager;
import android.content.Context;
import android.content.pm.PackageManager;
import android.os.Handler;
-import android.util.DisplayMetrics;
import android.view.IWindowManager;
import com.android.internal.logging.UiEventLogger;
import com.android.systemui.bubbles.Bubbles;
-import com.android.systemui.dagger.SysUISingleton;
+import com.android.systemui.dagger.WMSingleton;
import com.android.systemui.dagger.qualifiers.Main;
import com.android.systemui.shared.system.InputConsumerController;
-import com.android.systemui.util.DeviceConfigProxy;
import com.android.wm.shell.ShellTaskOrganizer;
-import com.android.wm.shell.WindowManagerShellWrapper;
-import com.android.wm.shell.animation.FlingAnimationUtils;
import com.android.wm.shell.common.AnimationThread;
import com.android.wm.shell.common.DisplayController;
-import com.android.wm.shell.common.FloatingContentCoordinator;
import com.android.wm.shell.common.HandlerExecutor;
import com.android.wm.shell.common.SyncTransactionQueue;
import com.android.wm.shell.common.SystemWindows;
@@ -58,41 +53,28 @@ import dagger.Provides;
* Provides basic dependencies from {@link com.android.wm.shell}, the dependencies declared here
* should be shared among different branches of SystemUI.
*/
-// TODO(b/162923491): Move most of these dependencies into WMSingleton scope.
@Module
public abstract class WMShellBaseModule {
- @SysUISingleton
+ @WMSingleton
@Provides
static TransactionPool provideTransactionPool() {
return new TransactionPool();
}
- @SysUISingleton
+ @WMSingleton
@Provides
static DisplayController provideDisplayController(Context context, @Main Handler handler,
IWindowManager wmService) {
return new DisplayController(context, handler, wmService);
}
- @SysUISingleton
- @Provides
- static DeviceConfigProxy provideDeviceConfigProxy() {
- return new DeviceConfigProxy();
- }
-
- @SysUISingleton
+ @WMSingleton
@Provides
static InputConsumerController provideInputConsumerController() {
return InputConsumerController.getPipInputConsumer();
}
- @SysUISingleton
- @Provides
- static FloatingContentCoordinator provideFloatingContentCoordinator() {
- return new FloatingContentCoordinator();
- }
-
- @SysUISingleton
+ @WMSingleton
@Provides
static PipAppOpsListener providePipAppOpsListener(Context context,
IActivityManager activityManager,
@@ -100,61 +82,46 @@ public abstract class WMShellBaseModule {
return new PipAppOpsListener(context, activityManager, pipTouchHandler.getMotionHelper());
}
- @SysUISingleton
+ @WMSingleton
@Provides
static PipMediaController providePipMediaController(Context context,
IActivityManager activityManager) {
return new PipMediaController(context, activityManager);
}
- @SysUISingleton
+ @WMSingleton
@Provides
static PipUiEventLogger providePipUiEventLogger(UiEventLogger uiEventLogger,
PackageManager packageManager) {
return new PipUiEventLogger(uiEventLogger, packageManager);
}
- @SysUISingleton
+ @WMSingleton
@Provides
static PipSurfaceTransactionHelper providePipSurfaceTransactionHelper(Context context) {
return new PipSurfaceTransactionHelper(context);
}
- @SysUISingleton
+ @WMSingleton
@Provides
static SystemWindows provideSystemWindows(DisplayController displayController,
IWindowManager wmService) {
return new SystemWindows(displayController, wmService);
}
- @SysUISingleton
+ @WMSingleton
@Provides
static SyncTransactionQueue provideSyncTransactionQueue(@Main Handler handler,
TransactionPool pool) {
return new SyncTransactionQueue(pool, handler);
}
- @SysUISingleton
+ @WMSingleton
@Provides
static ShellTaskOrganizer provideShellTaskOrganizer(SyncTransactionQueue syncQueue,
@Main Handler handler, TransactionPool transactionPool) {
- ShellTaskOrganizer organizer = new ShellTaskOrganizer(syncQueue, transactionPool,
+ return new ShellTaskOrganizer(syncQueue, transactionPool,
new HandlerExecutor(handler), AnimationThread.instance().getExecutor());
- organizer.registerOrganizer();
- return organizer;
- }
-
- @SysUISingleton
- @Provides
- static WindowManagerShellWrapper provideWindowManagerShellWrapper() {
- return new WindowManagerShellWrapper();
- }
-
- @SysUISingleton
- @Provides
- static FlingAnimationUtils.Builder provideFlingAnimationUtilsBuilder(
- DisplayMetrics displayMetrics) {
- return new FlingAnimationUtils.Builder(displayMetrics);
}
@BindsOptionalOf
@@ -163,7 +130,7 @@ public abstract class WMShellBaseModule {
@BindsOptionalOf
abstract Bubbles optionalBubbles();
- @SysUISingleton
+ @WMSingleton
@Provides
static Optional<OneHanded> provideOneHandedController(Context context,
DisplayController displayController) {
diff --git a/packages/SystemUI/src/com/android/systemui/wmshell/WMShellModule.java b/packages/SystemUI/src/com/android/systemui/wmshell/WMShellModule.java
index 81cb1f487ed8..a6fe72850716 100644
--- a/packages/SystemUI/src/com/android/systemui/wmshell/WMShellModule.java
+++ b/packages/SystemUI/src/com/android/systemui/wmshell/WMShellModule.java
@@ -20,7 +20,7 @@ import android.content.Context;
import android.os.Handler;
import android.view.IWindowManager;
-import com.android.systemui.dagger.SysUISingleton;
+import com.android.systemui.dagger.WMSingleton;
import com.android.systemui.dagger.qualifiers.Main;
import com.android.wm.shell.ShellTaskOrganizer;
import com.android.wm.shell.WindowManagerShellWrapper;
@@ -54,10 +54,9 @@ import dagger.Provides;
* Provides dependencies from {@link com.android.wm.shell} which could be customized among different
* branches of SystemUI.
*/
-// TODO(b/162923491): Move most of these dependencies into WMSingleton scope.
@Module(includes = WMShellBaseModule.class)
public class WMShellModule {
- @SysUISingleton
+ @WMSingleton
@Provides
static DisplayImeController provideDisplayImeController(IWindowManager wmService,
DisplayController displayController, @Main Executor mainExecutor,
@@ -66,7 +65,7 @@ public class WMShellModule {
transactionPool);
}
- @SysUISingleton
+ @WMSingleton
@Provides
static SplitScreen provideSplitScreen(Context context,
DisplayController displayController, SystemWindows systemWindows,
@@ -77,7 +76,7 @@ public class WMShellModule {
displayImeController, handler, transactionPool, shellTaskOrganizer, syncQueue);
}
- @SysUISingleton
+ @WMSingleton
@Provides
static Optional<Pip> providePip(Context context, DisplayController displayController,
PipAppOpsListener pipAppOpsListener, PipBoundsHandler pipBoundsHandler,
@@ -90,26 +89,27 @@ public class WMShellModule {
windowManagerShellWrapper));
}
- @SysUISingleton
+ @WMSingleton
@Provides
static PipBoundsState providePipBoundsState() {
return new PipBoundsState();
}
- @SysUISingleton
+ @WMSingleton
@Provides
- static PipBoundsHandler providePipBoundsHandler(Context context) {
- return new PipBoundsHandler(context);
+ static PipBoundsHandler providesPipBoundsHandler(Context context,
+ PipBoundsState pipBoundsState) {
+ return new PipBoundsHandler(context, pipBoundsState);
}
- @SysUISingleton
+ @WMSingleton
@Provides
static PipMenuActivityController providePipMenuActivityController(Context context,
PipMediaController pipMediaController, PipTaskOrganizer pipTaskOrganizer) {
return new PipMenuActivityController(context, pipMediaController, pipTaskOrganizer);
}
- @SysUISingleton
+ @WMSingleton
@Provides
static PipTouchHandler providePipTouchHandler(Context context,
PipMenuActivityController menuActivityController, PipBoundsHandler pipBoundsHandler,
@@ -121,7 +121,7 @@ public class WMShellModule {
pipBoundsState, pipTaskOrganizer, floatingContentCoordinator, pipUiEventLogger);
}
- @SysUISingleton
+ @WMSingleton
@Provides
static PipTaskOrganizer providePipTaskOrganizer(Context context,
PipBoundsState pipBoundsState,
diff --git a/packages/SystemUI/tests/src/com/android/systemui/SysuiTestCase.java b/packages/SystemUI/tests/src/com/android/systemui/SysuiTestCase.java
index 86b1e61d76b1..4f3266d0db44 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/SysuiTestCase.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/SysuiTestCase.java
@@ -30,6 +30,7 @@ import android.testing.TestableLooper;
import android.util.Log;
import androidx.test.InstrumentationRegistry;
+import androidx.test.uiautomator.UiDevice;
import com.android.keyguard.KeyguardUpdateMonitor;
import com.android.settingslib.bluetooth.LocalBluetoothManager;
@@ -72,7 +73,7 @@ public abstract class SysuiTestCase {
@Before
public void SysuiSetup() throws Exception {
- SystemUIFactory.createFromConfig(mContext);
+ SystemUIFactory.createFromConfig(mContext, true);
mDependency = new TestableDependency(
SystemUIFactory.getInstance().getSysUIComponent().createDependency());
Dependency.setInstance(mDependency);
@@ -149,6 +150,10 @@ public abstract class SysuiTestCase {
return mContext;
}
+ protected UiDevice getUiDevice() {
+ return UiDevice.getInstance(mRealInstrumentation);
+ }
+
protected void runShellCommand(String command) throws IOException {
ParcelFileDescriptor pfd = mRealInstrumentation.getUiAutomation()
.executeShellCommand(command);
diff --git a/packages/SystemUI/tests/src/com/android/systemui/bubbles/BubbleControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/bubbles/BubbleControllerTest.java
index b082d17e58ca..d9e9a8b26f0f 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/bubbles/BubbleControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/bubbles/BubbleControllerTest.java
@@ -45,6 +45,9 @@ import android.app.INotificationManager;
import android.app.Notification;
import android.app.PendingIntent;
import android.content.pm.LauncherApps;
+import android.content.res.Configuration;
+import android.graphics.Insets;
+import android.graphics.Rect;
import android.hardware.display.AmbientDisplayConfiguration;
import android.hardware.face.FaceManager;
import android.os.Handler;
@@ -80,10 +83,8 @@ import com.android.systemui.statusbar.notification.collection.NotificationEntry;
import com.android.systemui.statusbar.notification.collection.legacy.NotificationGroupManagerLegacy;
import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
import com.android.systemui.statusbar.notification.row.NotificationTestHelper;
-import com.android.systemui.statusbar.notification.row.dagger.NotificationShelfComponent;
import com.android.systemui.statusbar.phone.DozeParameters;
import com.android.systemui.statusbar.phone.KeyguardBypassController;
-import com.android.systemui.statusbar.phone.LockscreenLockIconController;
import com.android.systemui.statusbar.phone.NotificationShadeWindowControllerImpl;
import com.android.systemui.statusbar.phone.NotificationShadeWindowView;
import com.android.systemui.statusbar.phone.ShadeController;
@@ -178,8 +179,6 @@ public class BubbleControllerTest extends SysuiTestCase {
@Mock
private ShadeController mShadeController;
@Mock
- private NotificationShelfComponent mNotificationShelfComponent;
- @Mock
private NotifPipeline mNotifPipeline;
@Mock
private FeatureFlags mFeatureFlagsOldPipeline;
@@ -191,11 +190,12 @@ public class BubbleControllerTest extends SysuiTestCase {
private IStatusBarService mStatusBarService;
@Mock
private LauncherApps mLauncherApps;
- @Mock private LockscreenLockIconController mLockIconController;
-
- @Mock private WindowManagerShellWrapper mWindowManagerShellWrapper;
-
- @Mock private BubbleLogger mBubbleLogger;
+ @Mock
+ private WindowManagerShellWrapper mWindowManagerShellWrapper;
+ @Mock
+ private BubbleLogger mBubbleLogger;
+ @Mock
+ private BubblePositioner mPositioner;
private BubbleData mBubbleData;
@@ -210,7 +210,6 @@ public class BubbleControllerTest extends SysuiTestCase {
mContext.addMockSystemService(FaceManager.class, mFaceManager);
when(mColorExtractor.getNeutralColors()).thenReturn(mGradientColors);
- // Bubbles get added to status bar window view
mNotificationShadeWindowController = new NotificationShadeWindowControllerImpl(mContext,
mWindowManager, mActivityManager, mDozeParameters, mStatusBarStateController,
mConfigurationController, mKeyguardViewMediator, mKeyguardBypassController,
@@ -241,6 +240,13 @@ public class BubbleControllerTest extends SysuiTestCase {
mSysUiStateBubblesExpanded =
(sysUiFlags & QuickStepContract.SYSUI_STATE_BUBBLES_EXPANDED) != 0);
+ mBubbleData = new BubbleData(mContext, mBubbleLogger);
+
+ Rect availableRect = new Rect(0, 0, 1000, 5000);
+ when(mPositioner.getAvailableRect()).thenReturn(availableRect);
+ when(mPositioner.getOrientation()).thenReturn(Configuration.ORIENTATION_PORTRAIT);
+ when(mPositioner.getInsets()).thenReturn(Insets.of(0, 0, 0, 0));
+
TestableNotificationInterruptStateProviderImpl interruptionStateProvider =
new TestableNotificationInterruptStateProviderImpl(mContext.getContentResolver(),
mock(PowerManager.class),
@@ -252,7 +258,6 @@ public class BubbleControllerTest extends SysuiTestCase {
mock(HeadsUpManager.class),
mock(Handler.class)
);
- mBubbleData = new BubbleData(mContext, mBubbleLogger);
when(mFeatureFlagsOldPipeline.isNewNotifPipelineRenderingEnabled()).thenReturn(false);
mBubbleController = new TestableBubbleController(
mContext,
@@ -279,7 +284,8 @@ public class BubbleControllerTest extends SysuiTestCase {
mLauncherApps,
mBubbleLogger,
mock(Handler.class),
- mock(ShellTaskOrganizer.class));
+ mock(ShellTaskOrganizer.class),
+ mPositioner);
mBubbleController.setExpandListener(mBubbleExpandListener);
// Get a reference to the BubbleController's entry listener
diff --git a/packages/SystemUI/tests/src/com/android/systemui/bubbles/MultiWindowTaskListenerTest.java b/packages/SystemUI/tests/src/com/android/systemui/bubbles/MultiWindowTaskListenerTest.java
deleted file mode 100644
index e7bf86e6b919..000000000000
--- a/packages/SystemUI/tests/src/com/android/systemui/bubbles/MultiWindowTaskListenerTest.java
+++ /dev/null
@@ -1,181 +0,0 @@
-/*
- * Copyright (C) 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.systemui.bubbles;
-
-import static com.android.wm.shell.ShellTaskOrganizer.TASK_LISTENER_TYPE_MULTI_WINDOW;
-
-import static org.mockito.ArgumentMatchers.any;
-import static org.mockito.ArgumentMatchers.anyBoolean;
-import static org.mockito.ArgumentMatchers.eq;
-import static org.mockito.Mockito.never;
-import static org.mockito.Mockito.reset;
-import static org.mockito.Mockito.verify;
-
-import android.app.ActivityManager;
-import android.os.Binder;
-import android.os.Handler;
-import android.testing.AndroidTestingRunner;
-import android.testing.TestableLooper;
-import android.view.SurfaceControl;
-import android.window.WindowContainerToken;
-
-import androidx.test.filters.SmallTest;
-
-import com.android.systemui.SysuiTestCase;
-import com.android.wm.shell.ShellTaskOrganizer;
-
-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(setAsMainLooper = true)
-// TODO: Place in com.android.wm.shell vs. com.android.wm.shell.bubbles on shell migration.
-public class MultiWindowTaskListenerTest extends SysuiTestCase {
-
- @Mock
- ShellTaskOrganizer mOrganizer;
- @Mock
- MultiWindowTaskListener.Listener mPendingListener;
- @Mock
- SurfaceControl mLeash;
- @Mock
- ActivityManager.RunningTaskInfo mTaskInfo;
- @Mock
- WindowContainerToken mToken;
-
- Handler mHandler;
- MultiWindowTaskListener mTaskListener;
- TestableLooper mTestableLooper;
-
- @Before
- public void setUp() {
- MockitoAnnotations.initMocks(this);
-
- mTestableLooper = TestableLooper.get(this);
- mHandler = new Handler(mTestableLooper.getLooper());
-
- mTaskInfo = new ActivityManager.RunningTaskInfo();
- mTaskInfo.token = mToken;
-
- mTaskListener = new MultiWindowTaskListener(mHandler, mOrganizer);
- }
-
- private void addTaskAndVerify() {
- final Binder cookie = new Binder();
- mTaskInfo.addLaunchCookie(cookie);
- mTaskListener.setPendingLaunchCookieListener(cookie, mPendingListener);
- mTaskListener.onTaskAppeared(mTaskInfo, mLeash);
- mTestableLooper.processAllMessages();
- verify(mPendingListener).onTaskAppeared(eq(mTaskInfo), eq(mLeash));
- }
-
- @Test
- public void testListenForMultiWindowMode() {
- mTaskListener = new MultiWindowTaskListener(mHandler, mOrganizer);
- verify(mOrganizer).addListener(eq(mTaskListener), eq(TASK_LISTENER_TYPE_MULTI_WINDOW));
- }
-
- @Test
- public void testRemovePendingListener() {
- addTaskAndVerify();
- reset(mPendingListener);
-
- mTaskListener.removeListener(mPendingListener);
-
- // If it was removed, our pendingListener shouldn't get triggered:
- mTaskListener.onTaskAppeared(mTaskInfo, mLeash);
- mTaskListener.onTaskInfoChanged(mTaskInfo);
- mTaskListener.onBackPressedOnTaskRoot(mTaskInfo);
- mTaskListener.onTaskVanished(mTaskInfo);
-
- mTestableLooper.processAllMessages();
- verify(mPendingListener, never()).onTaskAppeared(any(), any());
- verify(mPendingListener, never()).onTaskInfoChanged(any());
- verify(mPendingListener, never()).onBackPressedOnTaskRoot(any());
- verify(mPendingListener, never()).onTaskVanished(any());
- }
-
- @Test
- public void testOnTaskAppeared() {
- addTaskAndVerify();
- verify(mOrganizer).setInterceptBackPressedOnTaskRoot(eq(mToken), eq(true));
- }
-
- @Test
- public void testOnTaskAppeared_nullListener() {
- mTaskListener.onTaskAppeared(mTaskInfo, mLeash);
- mTestableLooper.processAllMessages();
-
- verify(mOrganizer, never()).setInterceptBackPressedOnTaskRoot(any(), anyBoolean());
- verify(mPendingListener, never()).onTaskAppeared(any(), any());
- }
-
- @Test
- public void testOnTaskVanished() {
- addTaskAndVerify();
- mTaskListener.onTaskVanished(mTaskInfo);
- mTestableLooper.processAllMessages();
-
- verify(mPendingListener).onTaskVanished(eq(mTaskInfo));
- }
-
- @Test
- public void testOnTaskVanished_neverAdded() {
- mTaskListener.onTaskVanished(mTaskInfo);
- mTestableLooper.processAllMessages();
-
- verify(mPendingListener, never()).onTaskVanished(any());
- }
-
- @Test
- public void testOnTaskInfoChanged() {
- addTaskAndVerify();
- mTaskListener.onTaskInfoChanged(mTaskInfo);
- mTestableLooper.processAllMessages();
-
- verify(mPendingListener).onTaskInfoChanged(eq(mTaskInfo));
- }
-
- @Test
- public void testOnTaskInfoChanged_neverAdded() {
- mTaskListener.onTaskInfoChanged(mTaskInfo);
- mTestableLooper.processAllMessages();
-
- verify(mPendingListener, never()).onTaskInfoChanged(any());
- }
-
- @Test
- public void testOnBackPressedOnTaskRoot() {
- addTaskAndVerify();
- mTaskListener.onBackPressedOnTaskRoot(mTaskInfo);
- mTestableLooper.processAllMessages();
-
- verify(mPendingListener).onBackPressedOnTaskRoot(eq(mTaskInfo));
- }
-
- @Test
- public void testOnBackPressedOnTaskRoot_neverAdded() {
- mTaskListener.onBackPressedOnTaskRoot(mTaskInfo);
- mTestableLooper.processAllMessages();
-
- verify(mPendingListener, never()).onBackPressedOnTaskRoot(any());
- }
-}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/bubbles/NewNotifPipelineBubbleControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/bubbles/NewNotifPipelineBubbleControllerTest.java
index cbacd5393ccf..b9394ff3f26a 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/bubbles/NewNotifPipelineBubbleControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/bubbles/NewNotifPipelineBubbleControllerTest.java
@@ -42,7 +42,9 @@ import android.app.INotificationManager;
import android.app.Notification;
import android.app.PendingIntent;
import android.content.pm.LauncherApps;
-import android.content.res.Resources;
+import android.content.res.Configuration;
+import android.graphics.Insets;
+import android.graphics.Rect;
import android.hardware.display.AmbientDisplayConfiguration;
import android.hardware.face.FaceManager;
import android.os.Handler;
@@ -170,8 +172,6 @@ public class NewNotifPipelineBubbleControllerTest extends SysuiTestCase {
@Mock
ColorExtractor.GradientColors mGradientColors;
@Mock
- private Resources mResources;
- @Mock
private ShadeController mShadeController;
@Mock
private NotificationShelfComponent mNotificationShelfComponent;
@@ -191,6 +191,8 @@ public class NewNotifPipelineBubbleControllerTest extends SysuiTestCase {
private WindowManagerShellWrapper mWindowManagerShellWrapper;
@Mock
private BubbleLogger mBubbleLogger;
+ @Mock
+ private BubblePositioner mPositioner;
private BubbleData mBubbleData;
@@ -223,7 +225,6 @@ public class NewNotifPipelineBubbleControllerTest extends SysuiTestCase {
},
mLockIconController);
- // Bubbles get added to status bar window view
mNotificationShadeWindowController = new NotificationShadeWindowControllerImpl(mContext,
mWindowManager, mActivityManager, mDozeParameters, mStatusBarStateController,
mConfigurationController, mKeyguardViewMediator, mKeyguardBypassController,
@@ -243,6 +244,13 @@ public class NewNotifPipelineBubbleControllerTest extends SysuiTestCase {
mZenModeConfig.suppressedVisualEffects = 0;
when(mZenModeController.getConfig()).thenReturn(mZenModeConfig);
+ mBubbleData = new BubbleData(mContext, mBubbleLogger);
+
+ Rect availableRect = new Rect(0, 0, 1000, 5000);
+ when(mPositioner.getAvailableRect()).thenReturn(availableRect);
+ when(mPositioner.getOrientation()).thenReturn(Configuration.ORIENTATION_PORTRAIT);
+ when(mPositioner.getInsets()).thenReturn(Insets.of(0, 0, 0, 0));
+
TestableNotificationInterruptStateProviderImpl interruptionStateProvider =
new TestableNotificationInterruptStateProviderImpl(mContext.getContentResolver(),
mock(PowerManager.class),
@@ -254,7 +262,6 @@ public class NewNotifPipelineBubbleControllerTest extends SysuiTestCase {
mock(HeadsUpManager.class),
mock(Handler.class)
);
- mBubbleData = new BubbleData(mContext, mBubbleLogger);
when(mFeatureFlagsNewPipeline.isNewNotifPipelineRenderingEnabled()).thenReturn(true);
mBubbleController = new TestableBubbleController(
mContext,
@@ -281,7 +288,8 @@ public class NewNotifPipelineBubbleControllerTest extends SysuiTestCase {
mLauncherApps,
mBubbleLogger,
mock(Handler.class),
- mock(ShellTaskOrganizer.class));
+ mock(ShellTaskOrganizer.class),
+ mPositioner);
mBubbleController.addNotifCallback(mNotifCallback);
mBubbleController.setExpandListener(mBubbleExpandListener);
diff --git a/packages/SystemUI/tests/src/com/android/systemui/bubbles/TaskViewTest.java b/packages/SystemUI/tests/src/com/android/systemui/bubbles/TaskViewTest.java
index 63d60f91e48a..b13c6fc0cad4 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/bubbles/TaskViewTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/bubbles/TaskViewTest.java
@@ -25,6 +25,7 @@ import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyBoolean;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.doAnswer;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.reset;
@@ -35,6 +36,7 @@ import android.app.ActivityManager;
import android.app.ActivityOptions;
import android.app.PendingIntent;
import android.content.Context;
+import android.os.Handler;
import android.testing.AndroidTestingRunner;
import android.testing.TestableLooper;
import android.view.SurfaceControl;
@@ -46,6 +48,7 @@ import androidx.test.filters.SmallTest;
import com.android.systemui.SysuiTestCase;
import com.android.wm.shell.ShellTaskOrganizer;
+import com.android.wm.shell.common.HandlerExecutor;
import org.junit.After;
import org.junit.Before;
@@ -53,6 +56,7 @@ import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
+import org.mockito.invocation.InvocationOnMock;
@SmallTest
@RunWith(AndroidTestingRunner.class)
@@ -69,7 +73,7 @@ public class TaskViewTest extends SysuiTestCase {
@Mock
ShellTaskOrganizer mOrganizer;
@Mock
- MultiWindowTaskListener mTaskListener;
+ HandlerExecutor mExecutor;
SurfaceSession mSession;
SurfaceControl mLeash;
@@ -86,13 +90,18 @@ public class TaskViewTest extends SysuiTestCase {
mContext = getContext();
- when(mTaskListener.getTaskOrganizer()).thenReturn(mOrganizer);
mTaskInfo = new ActivityManager.RunningTaskInfo();
mTaskInfo.token = mToken;
mTaskInfo.taskId = 314;
mTaskInfo.taskDescription = mock(ActivityManager.TaskDescription.class);
- mTaskView = new TaskView(mContext, mTaskListener);
+ doAnswer((InvocationOnMock invocationOnMock) -> {
+ final Runnable r = invocationOnMock.getArgument(0);
+ r.run();
+ return null;
+ }).when(mExecutor).execute(any());
+
+ mTaskView = new TaskView(mContext, mOrganizer, mExecutor);
mTaskView.setListener(mViewListener);
}
@@ -105,7 +114,7 @@ public class TaskViewTest extends SysuiTestCase {
@Test
public void testSetPendingListener_throwsException() {
- TaskView taskView = new TaskView(mContext, mTaskListener);
+ TaskView taskView = new TaskView(mContext, mOrganizer, mExecutor);
taskView.setListener(mViewListener);
try {
taskView.setListener(mViewListener);
@@ -121,7 +130,7 @@ public class TaskViewTest extends SysuiTestCase {
ActivityOptions options = ActivityOptions.makeBasic();
mTaskView.startActivity(mock(PendingIntent.class), null, options);
- verify(mTaskListener).setPendingLaunchCookieListener(any(), eq(mTaskView));
+ verify(mOrganizer).setPendingLaunchCookieListener(any(), eq(mTaskView));
assertThat(options.getLaunchWindowingMode()).isEqualTo(WINDOWING_MODE_MULTI_WINDOW);
assertThat(options.getTaskAlwaysOnTop()).isTrue();
}
@@ -189,7 +198,7 @@ public class TaskViewTest extends SysuiTestCase {
mTaskView.surfaceCreated(mock(SurfaceHolder.class));
mTaskView.release();
- verify(mTaskListener).removeListener(eq(mTaskView));
+ verify(mOrganizer).removeListener(eq(mTaskView));
verify(mViewListener).onReleased();
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/bubbles/TestableBubbleController.java b/packages/SystemUI/tests/src/com/android/systemui/bubbles/TestableBubbleController.java
index 27c6fc147772..aaeee16dc1fd 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/bubbles/TestableBubbleController.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/bubbles/TestableBubbleController.java
@@ -70,7 +70,8 @@ public class TestableBubbleController extends BubbleController {
LauncherApps launcherApps,
BubbleLogger bubbleLogger,
Handler mainHandler,
- ShellTaskOrganizer shellTaskOrganizer) {
+ ShellTaskOrganizer shellTaskOrganizer,
+ BubblePositioner positioner) {
super(context,
notificationShadeWindowController, statusBarStateController, shadeController,
data, Runnable::run, configurationController, interruptionStateProvider,
@@ -78,7 +79,7 @@ public class TestableBubbleController extends BubbleController {
notifPipeline, featureFlags, dumpManager, floatingContentCoordinator,
dataRepository, sysUiState, notificationManager, statusBarService,
windowManager, windowManagerShellWrapper, launcherApps, bubbleLogger,
- mainHandler, shellTaskOrganizer);
+ mainHandler, shellTaskOrganizer, positioner);
setInflateSynchronously(true);
}
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/bubbles/animation/ExpandedAnimationControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/bubbles/animation/ExpandedAnimationControllerTest.java
index 6a1486382eac..a5bb8ea23559 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/bubbles/animation/ExpandedAnimationControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/bubbles/animation/ExpandedAnimationControllerTest.java
@@ -17,26 +17,30 @@
package com.android.systemui.bubbles.animation;
import static org.junit.Assert.assertEquals;
+import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verify;
+import android.annotation.SuppressLint;
import android.content.res.Configuration;
import android.content.res.Resources;
-import android.graphics.Point;
+import android.graphics.Insets;
import android.graphics.PointF;
+import android.graphics.Rect;
import android.testing.AndroidTestingRunner;
import android.view.View;
+import android.view.WindowManager;
import android.widget.FrameLayout;
import androidx.dynamicanimation.animation.DynamicAnimation;
import androidx.test.filters.SmallTest;
import com.android.systemui.R;
+import com.android.systemui.bubbles.BubblePositioner;
import org.junit.Before;
import org.junit.Ignore;
import org.junit.Test;
import org.junit.runner.RunWith;
-import org.mockito.Mockito;
import org.mockito.Spy;
@SmallTest
@@ -46,47 +50,45 @@ public class ExpandedAnimationControllerTest extends PhysicsAnimationLayoutTestC
private int mDisplayWidth = 500;
private int mDisplayHeight = 1000;
private int mExpandedViewPadding = 10;
- private int mOrientation = Configuration.ORIENTATION_PORTRAIT;
- private float mLauncherGridDiff = 30f;
-
- private Runnable mOnBubbleAnimatedOutAction = Mockito.mock(Runnable.class);
+ private Runnable mOnBubbleAnimatedOutAction = mock(Runnable.class);
@Spy
- private ExpandedAnimationController mExpandedController =
- new ExpandedAnimationController(
- new Point(mDisplayWidth, mDisplayHeight) /* displaySize */,
- mExpandedViewPadding, mOrientation, mOnBubbleAnimatedOutAction);
+ ExpandedAnimationController mExpandedController;
private int mStackOffset;
- private float mBubblePaddingTop;
- private float mBubbleSize;
-
private PointF mExpansionPoint;
+ @SuppressLint("VisibleForTests")
@Before
public void setUp() throws Exception {
super.setUp();
+
+ BubblePositioner positioner = new BubblePositioner(getContext(), mock(WindowManager.class));
+ positioner.update(Configuration.ORIENTATION_PORTRAIT,
+ Insets.of(0, 0, 0, 0),
+ new Rect(0, 0, mDisplayWidth, mDisplayHeight));
+ mExpandedController = new ExpandedAnimationController(positioner, mExpandedViewPadding,
+ mOnBubbleAnimatedOutAction);
+
addOneMoreThanBubbleLimitBubbles();
mLayout.setActiveController(mExpandedController);
Resources res = mLayout.getResources();
mStackOffset = res.getDimensionPixelSize(R.dimen.bubble_stack_offset);
- mBubblePaddingTop = res.getDimensionPixelSize(R.dimen.bubble_padding_top);
- mBubbleSize = res.getDimensionPixelSize(R.dimen.individual_bubble_size);
mExpansionPoint = new PointF(100, 100);
}
@Test
@Ignore
public void testExpansionAndCollapse() throws InterruptedException {
- Runnable afterExpand = Mockito.mock(Runnable.class);
+ Runnable afterExpand = mock(Runnable.class);
mExpandedController.expandFromStack(afterExpand);
waitForPropertyAnimations(DynamicAnimation.TRANSLATION_X, DynamicAnimation.TRANSLATION_Y);
testBubblesInCorrectExpandedPositions();
verify(afterExpand).run();
- Runnable afterCollapse = Mockito.mock(Runnable.class);
+ Runnable afterCollapse = mock(Runnable.class);
mExpandedController.collapseBackToStack(mExpansionPoint, afterCollapse);
waitForPropertyAnimations(DynamicAnimation.TRANSLATION_X, DynamicAnimation.TRANSLATION_Y);
@@ -121,7 +123,7 @@ public class ExpandedAnimationControllerTest extends PhysicsAnimationLayoutTestC
/** Expand the stack and wait for animations to finish. */
private void expand() throws InterruptedException {
- mExpandedController.expandFromStack(Mockito.mock(Runnable.class));
+ mExpandedController.expandFromStack(mock(Runnable.class));
waitForPropertyAnimations(DynamicAnimation.TRANSLATION_X, DynamicAnimation.TRANSLATION_Y);
}
@@ -141,51 +143,12 @@ public class ExpandedAnimationControllerTest extends PhysicsAnimationLayoutTestC
private void testBubblesInCorrectExpandedPositions() {
// Check all the visible bubbles to see if they're in the right place.
for (int i = 0; i < mLayout.getChildCount(); i++) {
- assertEquals(getBubbleLeft(i),
+ float expectedPosition = mExpandedController.getBubbleXOrYForOrientation(i);
+ assertEquals(expectedPosition,
mLayout.getChildAt(i).getTranslationX(),
2f);
- assertEquals(mExpandedController.getExpandedY(),
+ assertEquals(expectedPosition,
mLayout.getChildAt(i).getTranslationY(), 2f);
}
}
-
- /**
- * @param index Bubble index in row.
- * @return Bubble left x from left edge of screen.
- */
- public float getBubbleLeft(int index) {
- final float bubbleLeft = index * (mBubbleSize + getSpaceBetweenBubbles());
- return getRowLeft() + bubbleLeft;
- }
-
- private float getRowLeft() {
- if (mLayout == null) {
- return 0;
- }
- int bubbleCount = mLayout.getChildCount();
- final float totalBubbleWidth = bubbleCount * mBubbleSize;
- final float totalGapWidth = (bubbleCount - 1) * getSpaceBetweenBubbles();
- final float rowWidth = totalGapWidth + totalBubbleWidth;
-
- final float centerScreen = mDisplayWidth / 2f;
- final float halfRow = rowWidth / 2f;
- final float rowLeft = centerScreen - halfRow;
-
- return rowLeft;
- }
-
- /**
- * @return Space between bubbles in row above expanded view.
- */
- private float getSpaceBetweenBubbles() {
- final float rowMargins = (mExpandedViewPadding + mLauncherGridDiff) * 2;
- final float maxRowWidth = mDisplayWidth - rowMargins;
-
- final float totalBubbleWidth = mMaxBubbles * mBubbleSize;
- final float totalGapWidth = maxRowWidth - totalBubbleWidth;
-
- final int gapCount = mMaxBubbles - 1;
- final float gapWidth = totalGapWidth / gapCount;
- return gapWidth;
- }
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/bubbles/animation/StackAnimationControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/bubbles/animation/StackAnimationControllerTest.java
index 9242ce940bcd..7d0abec79de1 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/bubbles/animation/StackAnimationControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/bubbles/animation/StackAnimationControllerTest.java
@@ -18,6 +18,7 @@ package com.android.systemui.bubbles.animation;
import static org.junit.Assert.assertEquals;
import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.times;
@@ -33,6 +34,7 @@ import androidx.dynamicanimation.animation.SpringForce;
import androidx.test.filters.SmallTest;
import com.android.systemui.R;
+import com.android.systemui.bubbles.BubblePositioner;
import com.android.wm.shell.common.FloatingContentCoordinator;
import org.junit.Before;
@@ -40,7 +42,6 @@ import org.junit.Ignore;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
-import org.mockito.Mockito;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
@@ -67,7 +68,7 @@ public class StackAnimationControllerTest extends PhysicsAnimationLayoutTestCase
public int getAsInt() {
return mLayout.getChildCount();
}
- }, Mockito.mock(Runnable.class)));
+ }, mock(Runnable.class)));
mLayout.setActiveController(mStackController);
addOneMoreThanBubbleLimitBubbles();
mStackOffset = mLayout.getResources().getDimensionPixelSize(R.dimen.bubble_stack_offset);
@@ -306,7 +307,10 @@ public class StackAnimationControllerTest extends PhysicsAnimationLayoutTestCase
FloatingContentCoordinator floatingContentCoordinator,
IntSupplier bubbleCountSupplier,
Runnable onBubbleAnimatedOutAction) {
- super(floatingContentCoordinator, bubbleCountSupplier, onBubbleAnimatedOutAction);
+ super(floatingContentCoordinator,
+ bubbleCountSupplier,
+ onBubbleAnimatedOutAction,
+ mock(BubblePositioner.class));
}
@Override
diff --git a/packages/SystemUI/tests/src/com/android/systemui/globalactions/GlobalActionsDialogTest.java b/packages/SystemUI/tests/src/com/android/systemui/globalactions/GlobalActionsDialogTest.java
index b4af786c5579..78ee5936fe0b 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/globalactions/GlobalActionsDialogTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/globalactions/GlobalActionsDialogTest.java
@@ -53,6 +53,9 @@ import android.view.WindowManagerPolicyConstants;
import android.widget.FrameLayout;
import androidx.test.filters.SmallTest;
+import androidx.test.uiautomator.By;
+import androidx.test.uiautomator.UiObject2;
+import androidx.test.uiautomator.Until;
import com.android.internal.colorextraction.ColorExtractor;
import com.android.internal.logging.MetricsLogger;
@@ -86,11 +89,16 @@ import org.mockito.MockitoAnnotations;
import java.util.List;
import java.util.concurrent.Executor;
+import java.util.regex.Pattern;
@SmallTest
@RunWith(AndroidTestingRunner.class)
@TestableLooper.RunWithLooper(setAsMainLooper = true)
public class GlobalActionsDialogTest extends SysuiTestCase {
+ private static final long UI_TIMEOUT_MILLIS = 5000; // 5 sec
+ private static final Pattern CANCEL_BUTTON =
+ Pattern.compile("cancel", Pattern.CASE_INSENSITIVE);
+
private GlobalActionsDialog mGlobalActionsDialog;
@Mock private GlobalActions.GlobalActionsManager mWindowManagerFuncs;
@@ -240,6 +248,13 @@ public class GlobalActionsDialogTest extends SysuiTestCase {
mGlobalActionsDialog.makeScreenshotActionForTesting();
screenshotAction.onLongPress();
verifyLogPosted(GlobalActionsDialog.GlobalActionsEvent.GA_SCREENSHOT_LONG_PRESS);
+
+ // Dismiss ScreenRecordDialog opened by the long press above.
+ final UiObject2 cancelButton = getUiDevice().wait(
+ Until.findObject(By.text(CANCEL_BUTTON)), UI_TIMEOUT_MILLIS);
+ if (cancelButton != null) {
+ cancelButton.click();
+ }
}
@Test
diff --git a/packages/SystemUI/tests/src/com/android/systemui/media/SeekBarViewModelTest.kt b/packages/SystemUI/tests/src/com/android/systemui/media/SeekBarViewModelTest.kt
index b81ab74458ce..1f9862c07a4c 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/media/SeekBarViewModelTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/media/SeekBarViewModelTest.kt
@@ -654,4 +654,21 @@ public class SeekBarViewModelTest : SysuiTestCase() {
fakeExecutor.runAllReady()
verify(mockController).unregisterCallback(any())
}
+
+ @Test
+ fun nullPlaybackStateUnregistersCallback() {
+ viewModel.updateController(mockController)
+ val captor = ArgumentCaptor.forClass(MediaController.Callback::class.java)
+ verify(mockController).registerCallback(captor.capture())
+ val callback = captor.value
+ // WHEN the callback receives a null state
+ callback.onPlaybackStateChanged(null)
+ with(fakeExecutor) {
+ advanceClockToNext()
+ runAllReady()
+ }
+ // THEN we unregister callback (as a result of clearing the controller)
+ fakeExecutor.runAllReady()
+ verify(mockController).unregisterCallback(any())
+ }
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/media/dialog/MediaOutputAdapterTest.java b/packages/SystemUI/tests/src/com/android/systemui/media/dialog/MediaOutputAdapterTest.java
index 2d460aa0c9c1..521888658d68 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/media/dialog/MediaOutputAdapterTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/media/dialog/MediaOutputAdapterTest.java
@@ -25,7 +25,7 @@ import static org.mockito.Mockito.when;
import android.graphics.drawable.Icon;
import android.testing.AndroidTestingRunner;
import android.view.View;
-import android.widget.FrameLayout;
+import android.widget.LinearLayout;
import androidx.core.graphics.drawable.IconCompat;
import androidx.test.filters.SmallTest;
@@ -66,7 +66,7 @@ public class MediaOutputAdapterTest extends SysuiTestCase {
public void setUp() {
mMediaOutputAdapter = new MediaOutputAdapter(mMediaOutputController);
mViewHolder = (MediaOutputAdapter.MediaDeviceViewHolder) mMediaOutputAdapter
- .onCreateViewHolder(new FrameLayout(mContext), 0);
+ .onCreateViewHolder(new LinearLayout(mContext), 0);
when(mMediaOutputController.getMediaDevices()).thenReturn(mMediaDevices);
when(mMediaOutputController.hasAdjustVolumeUserRestriction()).thenReturn(false);
@@ -75,6 +75,7 @@ public class MediaOutputAdapterTest extends SysuiTestCase {
when(mMediaOutputController.getDeviceIconCompat(mMediaDevice1)).thenReturn(mIconCompat);
when(mMediaOutputController.getDeviceIconCompat(mMediaDevice2)).thenReturn(mIconCompat);
when(mMediaOutputController.getCurrentConnectedMediaDevice()).thenReturn(mMediaDevice1);
+ when(mMediaOutputController.isActiveRemoteDevice(mMediaDevice1)).thenReturn(true);
when(mIconCompat.toIcon(mContext)).thenReturn(mIcon);
when(mMediaDevice1.getName()).thenReturn(TEST_DEVICE_NAME_1);
when(mMediaDevice1.getId()).thenReturn(TEST_DEVICE_ID_1);
@@ -107,6 +108,11 @@ public class MediaOutputAdapterTest extends SysuiTestCase {
assertThat(mViewHolder.mTitleText.getVisibility()).isEqualTo(View.VISIBLE);
assertThat(mViewHolder.mTwoLineLayout.getVisibility()).isEqualTo(View.GONE);
+ assertThat(mViewHolder.mProgressBar.getVisibility()).isEqualTo(View.GONE);
+ assertThat(mViewHolder.mDivider.getVisibility()).isEqualTo(View.GONE);
+ assertThat(mViewHolder.mAddIcon.getVisibility()).isEqualTo(View.GONE);
+ assertThat(mViewHolder.mCheckBox.getVisibility()).isEqualTo(View.GONE);
+ assertThat(mViewHolder.mBottomDivider.getVisibility()).isEqualTo(View.GONE);
assertThat(mViewHolder.mTitleText.getText()).isEqualTo(mContext.getText(
R.string.media_output_dialog_pairing_new));
}
@@ -118,19 +124,41 @@ public class MediaOutputAdapterTest extends SysuiTestCase {
assertThat(mViewHolder.mTitleText.getVisibility()).isEqualTo(View.GONE);
assertThat(mViewHolder.mSubTitleText.getVisibility()).isEqualTo(View.GONE);
assertThat(mViewHolder.mProgressBar.getVisibility()).isEqualTo(View.GONE);
+ assertThat(mViewHolder.mCheckBox.getVisibility()).isEqualTo(View.GONE);
+ assertThat(mViewHolder.mBottomDivider.getVisibility()).isEqualTo(View.GONE);
assertThat(mViewHolder.mTwoLineTitleText.getVisibility()).isEqualTo(View.VISIBLE);
assertThat(mViewHolder.mSeekBar.getVisibility()).isEqualTo(View.VISIBLE);
+ assertThat(mViewHolder.mDivider.getVisibility()).isEqualTo(View.VISIBLE);
+ assertThat(mViewHolder.mAddIcon.getVisibility()).isEqualTo(View.VISIBLE);
assertThat(mViewHolder.mTwoLineTitleText.getText()).isEqualTo(TEST_DEVICE_NAME_1);
}
@Test
+ public void onBindViewHolder_bindNonActiveConnectedDevice_verifyView() {
+ mMediaOutputAdapter.onBindViewHolder(mViewHolder, 1);
+
+ assertThat(mViewHolder.mDivider.getVisibility()).isEqualTo(View.GONE);
+ assertThat(mViewHolder.mAddIcon.getVisibility()).isEqualTo(View.GONE);
+ assertThat(mViewHolder.mTwoLineLayout.getVisibility()).isEqualTo(View.GONE);
+ assertThat(mViewHolder.mProgressBar.getVisibility()).isEqualTo(View.GONE);
+ assertThat(mViewHolder.mCheckBox.getVisibility()).isEqualTo(View.GONE);
+ assertThat(mViewHolder.mBottomDivider.getVisibility()).isEqualTo(View.GONE);
+ assertThat(mViewHolder.mTitleText.getVisibility()).isEqualTo(View.VISIBLE);
+ assertThat(mViewHolder.mTitleText.getText().toString()).isEqualTo(TEST_DEVICE_NAME_2);
+ }
+
+ @Test
public void onBindViewHolder_bindDisconnectedBluetoothDevice_verifyView() {
when(mMediaDevice2.getDeviceType()).thenReturn(
MediaDevice.MediaDeviceType.TYPE_BLUETOOTH_DEVICE);
when(mMediaDevice2.isConnected()).thenReturn(false);
mMediaOutputAdapter.onBindViewHolder(mViewHolder, 1);
+ assertThat(mViewHolder.mDivider.getVisibility()).isEqualTo(View.GONE);
+ assertThat(mViewHolder.mAddIcon.getVisibility()).isEqualTo(View.GONE);
assertThat(mViewHolder.mTwoLineLayout.getVisibility()).isEqualTo(View.GONE);
+ assertThat(mViewHolder.mProgressBar.getVisibility()).isEqualTo(View.GONE);
+ assertThat(mViewHolder.mBottomDivider.getVisibility()).isEqualTo(View.GONE);
assertThat(mViewHolder.mTitleText.getVisibility()).isEqualTo(View.VISIBLE);
assertThat(mViewHolder.mTitleText.getText().toString()).isEqualTo(
mContext.getString(R.string.media_output_dialog_disconnected, TEST_DEVICE_NAME_2));
@@ -142,9 +170,13 @@ public class MediaOutputAdapterTest extends SysuiTestCase {
LocalMediaManager.MediaDeviceState.STATE_CONNECTING_FAILED);
mMediaOutputAdapter.onBindViewHolder(mViewHolder, 1);
+ assertThat(mViewHolder.mDivider.getVisibility()).isEqualTo(View.GONE);
+ assertThat(mViewHolder.mAddIcon.getVisibility()).isEqualTo(View.GONE);
assertThat(mViewHolder.mTitleText.getVisibility()).isEqualTo(View.GONE);
assertThat(mViewHolder.mSeekBar.getVisibility()).isEqualTo(View.GONE);
assertThat(mViewHolder.mProgressBar.getVisibility()).isEqualTo(View.GONE);
+ assertThat(mViewHolder.mCheckBox.getVisibility()).isEqualTo(View.GONE);
+ assertThat(mViewHolder.mBottomDivider.getVisibility()).isEqualTo(View.GONE);
assertThat(mViewHolder.mSubTitleText.getVisibility()).isEqualTo(View.VISIBLE);
assertThat(mViewHolder.mTwoLineTitleText.getVisibility()).isEqualTo(View.VISIBLE);
assertThat(mViewHolder.mSubTitleText.getText()).isEqualTo(mContext.getText(
@@ -162,7 +194,11 @@ public class MediaOutputAdapterTest extends SysuiTestCase {
assertThat(mViewHolder.mTitleText.getVisibility()).isEqualTo(View.GONE);
assertThat(mViewHolder.mSeekBar.getVisibility()).isEqualTo(View.GONE);
assertThat(mViewHolder.mSubTitleText.getVisibility()).isEqualTo(View.GONE);
+ assertThat(mViewHolder.mCheckBox.getVisibility()).isEqualTo(View.GONE);
+ assertThat(mViewHolder.mBottomDivider.getVisibility()).isEqualTo(View.GONE);
assertThat(mViewHolder.mProgressBar.getVisibility()).isEqualTo(View.VISIBLE);
+ assertThat(mViewHolder.mDivider.getVisibility()).isEqualTo(View.VISIBLE);
+ assertThat(mViewHolder.mAddIcon.getVisibility()).isEqualTo(View.VISIBLE);
assertThat(mViewHolder.mTwoLineTitleText.getVisibility()).isEqualTo(View.VISIBLE);
assertThat(mViewHolder.mTwoLineTitleText.getText()).isEqualTo(TEST_DEVICE_NAME_1);
}
@@ -174,8 +210,13 @@ public class MediaOutputAdapterTest extends SysuiTestCase {
LocalMediaManager.MediaDeviceState.STATE_CONNECTING);
mMediaOutputAdapter.onBindViewHolder(mViewHolder, 0);
- assertThat(mViewHolder.mTitleText.getVisibility()).isEqualTo(View.VISIBLE);
assertThat(mViewHolder.mTwoLineLayout.getVisibility()).isEqualTo(View.GONE);
+ assertThat(mViewHolder.mProgressBar.getVisibility()).isEqualTo(View.GONE);
+ assertThat(mViewHolder.mCheckBox.getVisibility()).isEqualTo(View.GONE);
+ assertThat(mViewHolder.mBottomDivider.getVisibility()).isEqualTo(View.GONE);
+ assertThat(mViewHolder.mTitleText.getVisibility()).isEqualTo(View.VISIBLE);
+ assertThat(mViewHolder.mDivider.getVisibility()).isEqualTo(View.VISIBLE);
+ assertThat(mViewHolder.mAddIcon.getVisibility()).isEqualTo(View.VISIBLE);
assertThat(mViewHolder.mTitleText.getText()).isEqualTo(TEST_DEVICE_NAME_1);
}
@@ -183,7 +224,7 @@ public class MediaOutputAdapterTest extends SysuiTestCase {
public void onItemClick_clickPairNew_verifyLaunchBluetoothPairing() {
when(mMediaOutputController.isZeroMode()).thenReturn(true);
mMediaOutputAdapter.onBindViewHolder(mViewHolder, 2);
- mViewHolder.mFrameLayout.performClick();
+ mViewHolder.mContainerLayout.performClick();
verify(mMediaOutputController).launchBluetoothPairing();
}
@@ -194,7 +235,7 @@ public class MediaOutputAdapterTest extends SysuiTestCase {
LocalMediaManager.MediaDeviceState.STATE_DISCONNECTED);
mMediaOutputAdapter.onBindViewHolder(mViewHolder, 0);
mMediaOutputAdapter.onBindViewHolder(mViewHolder, 1);
- mViewHolder.mFrameLayout.performClick();
+ mViewHolder.mContainerLayout.performClick();
verify(mMediaOutputController).connectDevice(mMediaDevice2);
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/media/dialog/MediaOutputBaseDialogTest.java b/packages/SystemUI/tests/src/com/android/systemui/media/dialog/MediaOutputBaseDialogTest.java
index 27b5b7fda684..4639dcbb1685 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/media/dialog/MediaOutputBaseDialogTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/media/dialog/MediaOutputBaseDialogTest.java
@@ -68,7 +68,7 @@ public class MediaOutputBaseDialogTest extends SysuiTestCase {
@Before
public void setUp() {
- mMediaOutputController = new MediaOutputController(mContext, TEST_PACKAGE,
+ mMediaOutputController = new MediaOutputController(mContext, TEST_PACKAGE, false,
mMediaSessionManager, mLocalBluetoothManager, mShadeController, mStarter);
mMediaOutputBaseDialogImpl = new MediaOutputBaseDialogImpl(mContext,
mMediaOutputController);
diff --git a/packages/SystemUI/tests/src/com/android/systemui/media/dialog/MediaOutputControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/media/dialog/MediaOutputControllerTest.java
index 0dcdecfdaadb..0576667484df 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/media/dialog/MediaOutputControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/media/dialog/MediaOutputControllerTest.java
@@ -34,6 +34,7 @@ import android.media.RoutingSessionInfo;
import android.media.session.MediaController;
import android.media.session.MediaSessionManager;
import android.testing.AndroidTestingRunner;
+import android.text.TextUtils;
import androidx.test.filters.SmallTest;
@@ -60,6 +61,9 @@ public class MediaOutputControllerTest extends SysuiTestCase {
private static final String TEST_PACKAGE_NAME = "com.test.package.name";
private static final String TEST_DEVICE_1_ID = "test_device_1_id";
private static final String TEST_DEVICE_2_ID = "test_device_2_id";
+ private static final String TEST_DEVICE_3_ID = "test_device_3_id";
+ private static final String TEST_DEVICE_4_ID = "test_device_4_id";
+ private static final String TEST_DEVICE_5_ID = "test_device_5_id";
private static final String TEST_ARTIST = "test_artist";
private static final String TEST_SONG = "test_song";
private static final String TEST_SESSION_ID = "test_session_id";
@@ -96,7 +100,7 @@ public class MediaOutputControllerTest extends SysuiTestCase {
MediaSessionManager.class);
when(mLocalBluetoothManager.getCachedDeviceManager()).thenReturn(
mCachedBluetoothDeviceManager);
- mMediaOutputController = new MediaOutputController(mSpyContext, TEST_PACKAGE_NAME,
+ mMediaOutputController = new MediaOutputController(mSpyContext, TEST_PACKAGE_NAME, false,
mMediaSessionManager, mLocalBluetoothManager, mShadeController, mStarter);
mLocalMediaManager = spy(mMediaOutputController.mLocalMediaManager);
mMediaOutputController.mLocalMediaManager = mLocalMediaManager;
@@ -139,8 +143,8 @@ public class MediaOutputControllerTest extends SysuiTestCase {
@Test
public void start_withoutPackageName_verifyMediaControllerInit() {
- mMediaOutputController = new MediaOutputController(mSpyContext, null, mMediaSessionManager,
- mLocalBluetoothManager, mShadeController, mStarter);
+ mMediaOutputController = new MediaOutputController(mSpyContext, null, false,
+ mMediaSessionManager, mLocalBluetoothManager, mShadeController, mStarter);
mMediaOutputController.start(mCb);
@@ -159,8 +163,8 @@ public class MediaOutputControllerTest extends SysuiTestCase {
@Test
public void stop_withoutPackageName_verifyMediaControllerDeinit() {
- mMediaOutputController = new MediaOutputController(mSpyContext, null, mMediaSessionManager,
- mLocalBluetoothManager, mShadeController, mStarter);
+ mMediaOutputController = new MediaOutputController(mSpyContext, null, false,
+ mMediaSessionManager, mLocalBluetoothManager, mShadeController, mStarter);
mMediaOutputController.start(mCb);
mMediaOutputController.stop();
@@ -345,4 +349,78 @@ public class MediaOutputControllerTest extends SysuiTestCase {
assertThat(mMediaOutputController.isZeroMode()).isFalse();
}
+
+ @Test
+ public void getGroupMediaDevices_differentDeviceOrder_showingSameOrder() {
+ final MediaDevice selectedMediaDevice1 = mock(MediaDevice.class);
+ final MediaDevice selectedMediaDevice2 = mock(MediaDevice.class);
+ final MediaDevice selectableMediaDevice1 = mock(MediaDevice.class);
+ final MediaDevice selectableMediaDevice2 = mock(MediaDevice.class);
+ final List<MediaDevice> selectedMediaDevices = new ArrayList<>();
+ final List<MediaDevice> selectableMediaDevices = new ArrayList<>();
+ when(selectedMediaDevice1.getId()).thenReturn(TEST_DEVICE_1_ID);
+ when(selectedMediaDevice2.getId()).thenReturn(TEST_DEVICE_2_ID);
+ when(selectableMediaDevice1.getId()).thenReturn(TEST_DEVICE_3_ID);
+ when(selectableMediaDevice2.getId()).thenReturn(TEST_DEVICE_4_ID);
+ selectedMediaDevices.add(selectedMediaDevice1);
+ selectedMediaDevices.add(selectedMediaDevice2);
+ selectableMediaDevices.add(selectableMediaDevice1);
+ selectableMediaDevices.add(selectableMediaDevice2);
+ doReturn(selectedMediaDevices).when(mLocalMediaManager).getSelectedMediaDevice();
+ doReturn(selectableMediaDevices).when(mLocalMediaManager).getSelectableMediaDevice();
+ final List<MediaDevice> groupMediaDevices = mMediaOutputController.getGroupMediaDevices();
+ // Reset order
+ selectedMediaDevices.clear();
+ selectedMediaDevices.add(selectedMediaDevice2);
+ selectedMediaDevices.add(selectedMediaDevice1);
+ selectableMediaDevices.clear();
+ selectableMediaDevices.add(selectableMediaDevice2);
+ selectableMediaDevices.add(selectableMediaDevice1);
+ final List<MediaDevice> newDevices = mMediaOutputController.getGroupMediaDevices();
+
+ assertThat(newDevices.size()).isEqualTo(groupMediaDevices.size());
+ for (int i = 0; i < groupMediaDevices.size(); i++) {
+ assertThat(TextUtils.equals(groupMediaDevices.get(i).getId(),
+ newDevices.get(i).getId())).isTrue();
+ }
+ }
+
+ @Test
+ public void getGroupMediaDevices_newDevice_verifyDeviceOrder() {
+ final MediaDevice selectedMediaDevice1 = mock(MediaDevice.class);
+ final MediaDevice selectedMediaDevice2 = mock(MediaDevice.class);
+ final MediaDevice selectableMediaDevice1 = mock(MediaDevice.class);
+ final MediaDevice selectableMediaDevice2 = mock(MediaDevice.class);
+ final MediaDevice selectableMediaDevice3 = mock(MediaDevice.class);
+ final List<MediaDevice> selectedMediaDevices = new ArrayList<>();
+ final List<MediaDevice> selectableMediaDevices = new ArrayList<>();
+ when(selectedMediaDevice1.getId()).thenReturn(TEST_DEVICE_1_ID);
+ when(selectedMediaDevice2.getId()).thenReturn(TEST_DEVICE_2_ID);
+ when(selectableMediaDevice1.getId()).thenReturn(TEST_DEVICE_3_ID);
+ when(selectableMediaDevice2.getId()).thenReturn(TEST_DEVICE_4_ID);
+ when(selectableMediaDevice3.getId()).thenReturn(TEST_DEVICE_5_ID);
+ selectedMediaDevices.add(selectedMediaDevice1);
+ selectedMediaDevices.add(selectedMediaDevice2);
+ selectableMediaDevices.add(selectableMediaDevice1);
+ selectableMediaDevices.add(selectableMediaDevice2);
+ doReturn(selectedMediaDevices).when(mLocalMediaManager).getSelectedMediaDevice();
+ doReturn(selectableMediaDevices).when(mLocalMediaManager).getSelectableMediaDevice();
+ final List<MediaDevice> groupMediaDevices = mMediaOutputController.getGroupMediaDevices();
+ // Reset order
+ selectedMediaDevices.clear();
+ selectedMediaDevices.add(selectedMediaDevice2);
+ selectedMediaDevices.add(selectedMediaDevice1);
+ selectableMediaDevices.clear();
+ selectableMediaDevices.add(selectableMediaDevice3);
+ selectableMediaDevices.add(selectableMediaDevice2);
+ selectableMediaDevices.add(selectableMediaDevice1);
+ final List<MediaDevice> newDevices = mMediaOutputController.getGroupMediaDevices();
+
+ assertThat(newDevices.size()).isEqualTo(5);
+ for (int i = 0; i < groupMediaDevices.size(); i++) {
+ assertThat(TextUtils.equals(groupMediaDevices.get(i).getId(),
+ newDevices.get(i).getId())).isTrue();
+ }
+ assertThat(newDevices.get(4).getId()).isEqualTo(TEST_DEVICE_5_ID);
+ }
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/media/dialog/MediaOutputDialogTest.java b/packages/SystemUI/tests/src/com/android/systemui/media/dialog/MediaOutputDialogTest.java
index 9ebb587d3d85..8648d918d006 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/media/dialog/MediaOutputDialogTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/media/dialog/MediaOutputDialogTest.java
@@ -65,7 +65,7 @@ public class MediaOutputDialogTest extends SysuiTestCase {
@Before
public void setUp() {
- mMediaOutputController = new MediaOutputController(mContext, TEST_PACKAGE,
+ mMediaOutputController = new MediaOutputController(mContext, TEST_PACKAGE, false,
mMediaSessionManager, mLocalBluetoothManager, mShadeController, mStarter);
mMediaOutputController.mLocalMediaManager = mLocalMediaManager;
mMediaOutputDialog = new MediaOutputDialog(mContext, false, mMediaOutputController);
diff --git a/packages/SystemUI/tests/src/com/android/systemui/media/dialog/MediaOutputGroupAdapterTest.java b/packages/SystemUI/tests/src/com/android/systemui/media/dialog/MediaOutputGroupAdapterTest.java
new file mode 100644
index 000000000000..1f85112dfb74
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/media/dialog/MediaOutputGroupAdapterTest.java
@@ -0,0 +1,248 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.media.dialog;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import android.graphics.drawable.Icon;
+import android.testing.AndroidTestingRunner;
+import android.view.View;
+import android.widget.LinearLayout;
+
+import androidx.core.graphics.drawable.IconCompat;
+import androidx.test.filters.SmallTest;
+
+import com.android.settingslib.media.MediaDevice;
+import com.android.systemui.R;
+import com.android.systemui.SysuiTestCase;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.util.ArrayList;
+import java.util.List;
+
+@SmallTest
+@RunWith(AndroidTestingRunner.class)
+public class MediaOutputGroupAdapterTest extends SysuiTestCase {
+
+ private static final String TEST_DEVICE_NAME_1 = "test_device_name_1";
+ private static final String TEST_DEVICE_NAME_2 = "test_device_name_2";
+ private static final String TEST_DEVICE_ID_1 = "test_device_id_1";
+ private static final String TEST_DEVICE_ID_2 = "test_device_id_2";
+ private static final int TEST_VOLUME = 10;
+ private static final int TEST_MAX_VOLUME = 50;
+
+ // Mock
+ private MediaOutputController mMediaOutputController = mock(MediaOutputController.class);
+ private MediaDevice mMediaDevice1 = mock(MediaDevice.class);
+ private MediaDevice mMediaDevice2 = mock(MediaDevice.class);
+ private Icon mIcon = mock(Icon.class);
+ private IconCompat mIconCompat = mock(IconCompat.class);
+
+ private MediaOutputGroupAdapter mGroupAdapter;
+ private MediaOutputGroupAdapter.GroupViewHolder mGroupViewHolder;
+ private List<MediaDevice> mGroupMediaDevices = new ArrayList<>();
+ private List<MediaDevice> mSelectableMediaDevices = new ArrayList<>();
+ private List<MediaDevice> mSelectedMediaDevices = new ArrayList<>();
+ private List<MediaDevice> mDeselectableMediaDevices = new ArrayList<>();
+
+ @Before
+ public void setUp() {
+ when(mMediaOutputController.getGroupMediaDevices()).thenReturn(mGroupMediaDevices);
+ when(mMediaOutputController.getDeviceIconCompat(mMediaDevice1)).thenReturn(mIconCompat);
+ when(mMediaOutputController.getDeviceIconCompat(mMediaDevice2)).thenReturn(mIconCompat);
+ when(mMediaOutputController.getSelectableMediaDevice()).thenReturn(mSelectableMediaDevices);
+ when(mMediaOutputController.getSelectedMediaDevice()).thenReturn(mSelectedMediaDevices);
+ when(mMediaOutputController.getDeselectableMediaDevice()).thenReturn(
+ mDeselectableMediaDevices);
+ when(mIconCompat.toIcon(mContext)).thenReturn(mIcon);
+ when(mMediaDevice1.getName()).thenReturn(TEST_DEVICE_NAME_1);
+ when(mMediaDevice1.getId()).thenReturn(TEST_DEVICE_ID_1);
+ when(mMediaDevice2.getName()).thenReturn(TEST_DEVICE_NAME_2);
+ when(mMediaDevice2.getId()).thenReturn(TEST_DEVICE_ID_2);
+ mGroupMediaDevices.add(mMediaDevice1);
+ mGroupMediaDevices.add(mMediaDevice2);
+ mSelectedMediaDevices.add(mMediaDevice1);
+ mSelectableMediaDevices.add(mMediaDevice2);
+ mDeselectableMediaDevices.add(mMediaDevice1);
+
+ mGroupAdapter = new MediaOutputGroupAdapter(mMediaOutputController);
+ mGroupViewHolder = (MediaOutputGroupAdapter.GroupViewHolder) mGroupAdapter
+ .onCreateViewHolder(new LinearLayout(mContext), 0);
+ }
+
+ @Test
+ public void onBindViewHolder_verifyGroupItem() {
+ mGroupAdapter.onBindViewHolder(mGroupViewHolder, 0);
+
+ assertThat(mGroupViewHolder.mTitleText.getVisibility()).isEqualTo(View.GONE);
+ assertThat(mGroupViewHolder.mCheckBox.getVisibility()).isEqualTo(View.GONE);
+ assertThat(mGroupViewHolder.mSubTitleText.getVisibility()).isEqualTo(View.GONE);
+ assertThat(mGroupViewHolder.mProgressBar.getVisibility()).isEqualTo(View.GONE);
+ assertThat(mGroupViewHolder.mDivider.getVisibility()).isEqualTo(View.GONE);
+ assertThat(mGroupViewHolder.mAddIcon.getVisibility()).isEqualTo(View.GONE);
+ assertThat(mGroupViewHolder.mBottomDivider.getVisibility()).isEqualTo(View.VISIBLE);
+ assertThat(mGroupViewHolder.mSeekBar.getVisibility()).isEqualTo(View.VISIBLE);
+ assertThat(mGroupViewHolder.mTwoLineTitleText.getVisibility()).isEqualTo(View.VISIBLE);
+ assertThat(mGroupViewHolder.mTwoLineTitleText.getText()).isEqualTo(mContext.getText(
+ R.string.media_output_dialog_group));
+ }
+
+ @Test
+ public void onBindViewHolder_singleSelectedDevice_verifyView() {
+ mGroupAdapter.onBindViewHolder(mGroupViewHolder, 1);
+
+ assertThat(mGroupViewHolder.mTitleText.getVisibility()).isEqualTo(View.GONE);
+ assertThat(mGroupViewHolder.mProgressBar.getVisibility()).isEqualTo(View.GONE);
+ assertThat(mGroupViewHolder.mDivider.getVisibility()).isEqualTo(View.GONE);
+ assertThat(mGroupViewHolder.mAddIcon.getVisibility()).isEqualTo(View.GONE);
+ assertThat(mGroupViewHolder.mBottomDivider.getVisibility()).isEqualTo(View.GONE);
+ assertThat(mGroupViewHolder.mSubTitleText.getVisibility()).isEqualTo(View.GONE);
+ assertThat(mGroupViewHolder.mSeekBar.getVisibility()).isEqualTo(View.VISIBLE);
+ assertThat(mGroupViewHolder.mTwoLineTitleText.getVisibility()).isEqualTo(View.VISIBLE);
+ assertThat(mGroupViewHolder.mTwoLineTitleText.getText()).isEqualTo(TEST_DEVICE_NAME_1);
+ assertThat(mGroupViewHolder.mCheckBox.getVisibility()).isEqualTo(View.VISIBLE);
+ assertThat(mGroupViewHolder.mCheckBox.isChecked()).isTrue();
+ // Disabled checkBox
+ assertThat(mGroupViewHolder.mCheckBox.isEnabled()).isFalse();
+ }
+
+ @Test
+ public void onBindViewHolder_multipleSelectedDevice_verifyView() {
+ mSelectedMediaDevices.clear();
+ mSelectedMediaDevices.add(mMediaDevice1);
+ mSelectedMediaDevices.add(mMediaDevice2);
+ mDeselectableMediaDevices.clear();
+ mDeselectableMediaDevices.add(mMediaDevice1);
+ mDeselectableMediaDevices.add(mMediaDevice2);
+ mSelectableMediaDevices.clear();
+
+ mGroupAdapter.onBindViewHolder(mGroupViewHolder, 1);
+
+ assertThat(mGroupViewHolder.mTitleText.getVisibility()).isEqualTo(View.GONE);
+ assertThat(mGroupViewHolder.mProgressBar.getVisibility()).isEqualTo(View.GONE);
+ assertThat(mGroupViewHolder.mDivider.getVisibility()).isEqualTo(View.GONE);
+ assertThat(mGroupViewHolder.mAddIcon.getVisibility()).isEqualTo(View.GONE);
+ assertThat(mGroupViewHolder.mBottomDivider.getVisibility()).isEqualTo(View.GONE);
+ assertThat(mGroupViewHolder.mSubTitleText.getVisibility()).isEqualTo(View.GONE);
+ assertThat(mGroupViewHolder.mSeekBar.getVisibility()).isEqualTo(View.VISIBLE);
+ assertThat(mGroupViewHolder.mTwoLineTitleText.getVisibility()).isEqualTo(View.VISIBLE);
+ assertThat(mGroupViewHolder.mTwoLineTitleText.getText()).isEqualTo(TEST_DEVICE_NAME_1);
+ assertThat(mGroupViewHolder.mCheckBox.getVisibility()).isEqualTo(View.VISIBLE);
+ assertThat(mGroupViewHolder.mCheckBox.isChecked()).isTrue();
+ // Enabled checkBox
+ assertThat(mGroupViewHolder.mCheckBox.isEnabled()).isTrue();
+ }
+
+ @Test
+ public void onBindViewHolder_notDeselectedDevice_verifyView() {
+ mSelectedMediaDevices.clear();
+ mSelectedMediaDevices.add(mMediaDevice1);
+ mSelectedMediaDevices.add(mMediaDevice2);
+ mDeselectableMediaDevices.clear();
+ mDeselectableMediaDevices.add(mMediaDevice1);
+ mSelectableMediaDevices.clear();
+
+ mGroupAdapter.onBindViewHolder(mGroupViewHolder, 2);
+
+ assertThat(mGroupViewHolder.mTitleText.getVisibility()).isEqualTo(View.GONE);
+ assertThat(mGroupViewHolder.mProgressBar.getVisibility()).isEqualTo(View.GONE);
+ assertThat(mGroupViewHolder.mDivider.getVisibility()).isEqualTo(View.GONE);
+ assertThat(mGroupViewHolder.mAddIcon.getVisibility()).isEqualTo(View.GONE);
+ assertThat(mGroupViewHolder.mBottomDivider.getVisibility()).isEqualTo(View.GONE);
+ assertThat(mGroupViewHolder.mSubTitleText.getVisibility()).isEqualTo(View.GONE);
+ assertThat(mGroupViewHolder.mSeekBar.getVisibility()).isEqualTo(View.VISIBLE);
+ assertThat(mGroupViewHolder.mTwoLineTitleText.getVisibility()).isEqualTo(View.VISIBLE);
+ assertThat(mGroupViewHolder.mTwoLineTitleText.getText()).isEqualTo(TEST_DEVICE_NAME_2);
+ assertThat(mGroupViewHolder.mCheckBox.getVisibility()).isEqualTo(View.VISIBLE);
+ assertThat(mGroupViewHolder.mCheckBox.isChecked()).isTrue();
+ // Disabled checkBox
+ assertThat(mGroupViewHolder.mCheckBox.isEnabled()).isFalse();
+ }
+
+ @Test
+ public void onBindViewHolder_selectableDevice_verifyCheckBox() {
+ mGroupAdapter.onBindViewHolder(mGroupViewHolder, 2);
+
+ assertThat(mGroupViewHolder.mTitleText.getVisibility()).isEqualTo(View.GONE);
+ assertThat(mGroupViewHolder.mProgressBar.getVisibility()).isEqualTo(View.GONE);
+ assertThat(mGroupViewHolder.mDivider.getVisibility()).isEqualTo(View.GONE);
+ assertThat(mGroupViewHolder.mAddIcon.getVisibility()).isEqualTo(View.GONE);
+ assertThat(mGroupViewHolder.mBottomDivider.getVisibility()).isEqualTo(View.GONE);
+ assertThat(mGroupViewHolder.mSubTitleText.getVisibility()).isEqualTo(View.GONE);
+ assertThat(mGroupViewHolder.mSeekBar.getVisibility()).isEqualTo(View.VISIBLE);
+ assertThat(mGroupViewHolder.mTwoLineTitleText.getVisibility()).isEqualTo(View.VISIBLE);
+ assertThat(mGroupViewHolder.mTwoLineTitleText.getText()).isEqualTo(TEST_DEVICE_NAME_2);
+ assertThat(mGroupViewHolder.mCheckBox.getVisibility()).isEqualTo(View.VISIBLE);
+ assertThat(mGroupViewHolder.mCheckBox.isChecked()).isFalse();
+ // Enabled checkBox
+ assertThat(mGroupViewHolder.mCheckBox.isEnabled()).isTrue();
+ }
+
+ @Test
+ public void onBindViewHolder_verifySessionVolume() {
+ when(mMediaOutputController.getSessionVolume()).thenReturn(TEST_VOLUME);
+ when(mMediaOutputController.getSessionVolumeMax()).thenReturn(TEST_MAX_VOLUME);
+
+ mGroupAdapter.onBindViewHolder(mGroupViewHolder, 0);
+
+ assertThat(mGroupViewHolder.mSeekBar.getProgress()).isEqualTo(TEST_VOLUME);
+ assertThat(mGroupViewHolder.mSeekBar.getMax()).isEqualTo(TEST_MAX_VOLUME);
+ }
+
+ @Test
+ public void onBindViewHolder_verifyDeviceVolume() {
+ when(mMediaDevice1.getCurrentVolume()).thenReturn(TEST_VOLUME);
+ when(mMediaDevice1.getMaxVolume()).thenReturn(TEST_MAX_VOLUME);
+
+ mGroupAdapter.onBindViewHolder(mGroupViewHolder, 1);
+
+ assertThat(mGroupViewHolder.mSeekBar.getProgress()).isEqualTo(TEST_VOLUME);
+ assertThat(mGroupViewHolder.mSeekBar.getMax()).isEqualTo(TEST_MAX_VOLUME);
+ }
+
+ @Test
+ public void clickSelectedDevice_verifyRemoveDeviceFromPlayMedia() {
+ mSelectedMediaDevices.clear();
+ mSelectedMediaDevices.add(mMediaDevice1);
+ mSelectedMediaDevices.add(mMediaDevice2);
+ mDeselectableMediaDevices.clear();
+ mDeselectableMediaDevices.add(mMediaDevice1);
+ mDeselectableMediaDevices.add(mMediaDevice2);
+ mSelectableMediaDevices.clear();
+
+ mGroupAdapter.onBindViewHolder(mGroupViewHolder, 1);
+ mGroupViewHolder.mCheckBox.performClick();
+
+ verify(mMediaOutputController).removeDeviceFromPlayMedia(mMediaDevice1);
+ }
+
+ @Test
+ public void clickSelectabelDevice_verifyAddDeviceToPlayMedia() {
+ mGroupAdapter.onBindViewHolder(mGroupViewHolder, 2);
+
+ mGroupViewHolder.mCheckBox.performClick();
+
+ verify(mMediaOutputController).addDeviceToPlayMedia(mMediaDevice2);
+ }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/media/dialog/MediaOutputGroupDialogTest.java b/packages/SystemUI/tests/src/com/android/systemui/media/dialog/MediaOutputGroupDialogTest.java
new file mode 100644
index 000000000000..10f2bd5e4699
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/media/dialog/MediaOutputGroupDialogTest.java
@@ -0,0 +1,104 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.media.dialog;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+import android.media.session.MediaSessionManager;
+import android.testing.AndroidTestingRunner;
+import android.testing.TestableLooper;
+import android.view.View;
+
+import androidx.test.filters.SmallTest;
+
+import com.android.settingslib.bluetooth.LocalBluetoothManager;
+import com.android.settingslib.media.LocalMediaManager;
+import com.android.settingslib.media.MediaDevice;
+import com.android.systemui.R;
+import com.android.systemui.SysuiTestCase;
+import com.android.systemui.plugins.ActivityStarter;
+import com.android.systemui.statusbar.phone.ShadeController;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.util.ArrayList;
+import java.util.List;
+
+@SmallTest
+@RunWith(AndroidTestingRunner.class)
+@TestableLooper.RunWithLooper
+public class MediaOutputGroupDialogTest extends SysuiTestCase {
+
+ private static final String TEST_PACKAGE = "test_package";
+
+ // Mock
+ private MediaSessionManager mMediaSessionManager = mock(MediaSessionManager.class);
+ private LocalBluetoothManager mLocalBluetoothManager = mock(LocalBluetoothManager.class);
+ private ShadeController mShadeController = mock(ShadeController.class);
+ private ActivityStarter mStarter = mock(ActivityStarter.class);
+ private LocalMediaManager mLocalMediaManager = mock(LocalMediaManager.class);
+ private MediaDevice mMediaDevice = mock(MediaDevice.class);
+ private MediaDevice mMediaDevice1 = mock(MediaDevice.class);
+
+ private MediaOutputGroupDialog mMediaOutputGroupDialog;
+ private MediaOutputController mMediaOutputController;
+ private List<MediaDevice> mMediaDevices = new ArrayList<>();
+
+ @Before
+ public void setUp() {
+ mMediaOutputController = new MediaOutputController(mContext, TEST_PACKAGE, false,
+ mMediaSessionManager, mLocalBluetoothManager, mShadeController, mStarter);
+ mMediaOutputController.mLocalMediaManager = mLocalMediaManager;
+ mMediaOutputGroupDialog = new MediaOutputGroupDialog(mContext, false,
+ mMediaOutputController);
+ when(mLocalMediaManager.getSelectedMediaDevice()).thenReturn(mMediaDevices);
+ }
+
+ @After
+ public void tearDown() {
+ mMediaOutputGroupDialog.dismissDialog();
+ }
+
+ @Test
+ public void getStopButtonVisibility_returnVisible() {
+ assertThat(mMediaOutputGroupDialog.getStopButtonVisibility()).isEqualTo(View.VISIBLE);
+ }
+
+ @Test
+ public void getHeaderSubtitle_singleDevice_verifyTitle() {
+ mMediaDevices.add(mMediaDevice);
+
+ assertThat(mMediaOutputGroupDialog.getHeaderSubtitle()).isEqualTo(
+ mContext.getText(R.string.media_output_dialog_single_device));
+ }
+
+ @Test
+ public void getHeaderSubtitle_multipleDevices_verifyTitle() {
+ mMediaDevices.add(mMediaDevice);
+ mMediaDevices.add(mMediaDevice1);
+
+ assertThat(mMediaOutputGroupDialog.getHeaderSubtitle()).isEqualTo(mContext.getString(
+ R.string.media_output_dialog_multiple_devices, mMediaDevices.size()));
+ }
+
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/privacy/PrivacyItemControllerFlagsTest.kt b/packages/SystemUI/tests/src/com/android/systemui/privacy/PrivacyItemControllerFlagsTest.kt
index cb17829ddaf8..cd94f8444c45 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/privacy/PrivacyItemControllerFlagsTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/privacy/PrivacyItemControllerFlagsTest.kt
@@ -54,6 +54,7 @@ class PrivacyItemControllerFlagsTest : SysuiTestCase() {
private const val ALL_INDICATORS =
SystemUiDeviceConfigFlags.PROPERTY_PERMISSIONS_HUB_ENABLED
private const val MIC_CAMERA = SystemUiDeviceConfigFlags.PROPERTY_MIC_CAMERA_ENABLED
+ private const val LOCATION = SystemUiDeviceConfigFlags.PROPERTY_LOCATION_INDICATORS_ENABLED
}
@Mock
@@ -116,6 +117,15 @@ class PrivacyItemControllerFlagsTest : SysuiTestCase() {
}
@Test
+ fun testLocationChanged() {
+ changeLocation(true)
+ executor.runAllReady()
+
+ verify(callback).onFlagLocationChanged(true)
+ assertTrue(privacyItemController.locationAvailable)
+ }
+
+ @Test
fun testAllChanged() {
changeAll(true)
executor.runAllReady()
@@ -158,6 +168,14 @@ class PrivacyItemControllerFlagsTest : SysuiTestCase() {
}
@Test
+ fun testLocation_listening() {
+ changeLocation(true)
+ executor.runAllReady()
+
+ verify(appOpsController).addCallback(eq(PrivacyItemController.OPS), any())
+ }
+
+ @Test
@Ignore // TODO(b/168209929)
fun testAllFalse_notListening() {
changeAll(true)
@@ -205,6 +223,7 @@ class PrivacyItemControllerFlagsTest : SysuiTestCase() {
}
private fun changeMicCamera(value: Boolean?) = changeProperty(MIC_CAMERA, value)
+ private fun changeLocation(value: Boolean?) = changeProperty(LOCATION, value)
private fun changeAll(value: Boolean?) = changeProperty(ALL_INDICATORS, value)
private fun changeProperty(name: String, value: Boolean?) {
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/QSDetailTest.java b/packages/SystemUI/tests/src/com/android/systemui/qs/QSDetailTest.java
index 353efeeb21f6..803919200150 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/QSDetailTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/QSDetailTest.java
@@ -70,7 +70,7 @@ public class QSDetailTest extends SysuiTestCase {
mQsDetail = (QSDetail) LayoutInflater.from(mContext).inflate(R.layout.qs_detail, null);
mQsPanel = mock(QSPanel.class);
mQuickHeader = mock(QuickStatusBarHeader.class);
- mQsDetail.setQsPanel(mQsPanel, mQuickHeader, mock(View.class));
+ mQsDetail.setQsPanel(mQsPanel, mQuickHeader, mock(QSFooter.class));
mMockDetailAdapter = mock(DetailAdapter.class);
when(mMockDetailAdapter.createDetailView(any(), any(), any()))
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/QSFooterImplTest.java b/packages/SystemUI/tests/src/com/android/systemui/qs/QSFooterImplTest.java
deleted file mode 100644
index 99f2d8042547..000000000000
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/QSFooterImplTest.java
+++ /dev/null
@@ -1,109 +0,0 @@
-/*
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file
- * except in compliance with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software distributed under the
- * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the specific language governing
- * permissions and limitations under the License.
- */
-
-package com.android.systemui.qs;
-
-import static com.google.common.truth.Truth.assertThat;
-
-import static org.mockito.ArgumentMatchers.any;
-import static org.mockito.ArgumentMatchers.anyBoolean;
-import static org.mockito.Mockito.never;
-import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.when;
-
-import android.content.ClipData;
-import android.content.ClipboardManager;
-import android.testing.AndroidTestingRunner;
-import android.testing.TestableLooper;
-import android.testing.TestableLooper.RunWithLooper;
-import android.view.LayoutInflater;
-import android.view.View;
-import android.widget.TextView;
-
-import androidx.test.filters.SmallTest;
-
-import com.android.systemui.R;
-import com.android.systemui.R.id;
-import com.android.systemui.plugins.ActivityStarter;
-import com.android.systemui.settings.UserTracker;
-import com.android.systemui.statusbar.policy.DeviceProvisionedController;
-import com.android.systemui.statusbar.policy.UserInfoController;
-import com.android.systemui.utils.leaks.LeakCheckedTest;
-
-import org.junit.Before;
-import org.junit.Ignore;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.mockito.ArgumentCaptor;
-import org.mockito.Mock;
-import org.mockito.MockitoAnnotations;
-
-@RunWith(AndroidTestingRunner.class)
-@RunWithLooper
-@SmallTest
-public class QSFooterImplTest extends LeakCheckedTest {
-
- private QSFooterImpl mFooter;
- private ActivityStarter mActivityStarter;
- private DeviceProvisionedController mDeviceProvisionedController;
- private UserInfoController mUserInfoController;
- private UserTracker mUserTracker;
- @Mock
- private ClipboardManager mClipboardManager;
-
- @Before
- public void setup() throws Exception {
- MockitoAnnotations.initMocks(this);
-
- injectLeakCheckedDependencies(ALL_SUPPORTED_CLASSES);
- mActivityStarter = mDependency.injectMockDependency(ActivityStarter.class);
- mDeviceProvisionedController = mDependency.injectMockDependency(
- DeviceProvisionedController.class);
- mUserInfoController = mDependency.injectMockDependency(UserInfoController.class);
- mUserTracker = mDependency.injectMockDependency(UserTracker.class);
-
- mContext.addMockSystemService(ClipboardManager.class, mClipboardManager);
-
- when(mUserTracker.getUserContext()).thenReturn(mContext);
-
- TestableLooper.get(this).runWithLooper(
- () -> mFooter = (QSFooterImpl) LayoutInflater.from(mContext).inflate(
- R.layout.qs_footer_impl, null));
- }
-
- @Test
- public void testBuildTextCopy() {
- TextView buildTextView = mFooter.requireViewById(R.id.build);
- CharSequence buildText = "TEST";
- buildTextView.setText(buildText);
- buildTextView.setLongClickable(true);
-
- buildTextView.performLongClick();
-
- ArgumentCaptor<ClipData> captor = ArgumentCaptor.forClass(ClipData.class);
- verify(mClipboardManager).setPrimaryClip(captor.capture());
- assertThat(captor.getValue().getItemAt(0).getText()).isEqualTo(buildText);
- }
-
- @Test
- @Ignore("failing")
- public void testSettings_UserNotSetup() {
- View settingsButton = mFooter.findViewById(id.settings_button);
- when(mDeviceProvisionedController.isCurrentUserSetup()).thenReturn(false);
-
- mFooter.onClick(settingsButton);
- // Verify Settings wasn't launched.
- verify(mActivityStarter, never()).startActivity(any(), anyBoolean());
- }
-}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/QSFooterViewControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/qs/QSFooterViewControllerTest.java
new file mode 100644
index 000000000000..065f236d19b3
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/QSFooterViewControllerTest.java
@@ -0,0 +1,144 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.qs;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyBoolean;
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import android.content.ClipData;
+import android.content.ClipboardManager;
+import android.os.UserManager;
+import android.testing.AndroidTestingRunner;
+import android.testing.TestableLooper;
+import android.view.View;
+import android.widget.TextView;
+
+import androidx.test.filters.SmallTest;
+
+import com.android.internal.logging.MetricsLogger;
+import com.android.internal.logging.testing.FakeMetricsLogger;
+import com.android.systemui.Dependency;
+import com.android.systemui.R;
+import com.android.systemui.plugins.ActivityStarter;
+import com.android.systemui.settings.UserTracker;
+import com.android.systemui.statusbar.phone.SettingsButton;
+import com.android.systemui.statusbar.policy.DeviceProvisionedController;
+import com.android.systemui.statusbar.policy.UserInfoController;
+import com.android.systemui.tuner.TunerService;
+import com.android.systemui.utils.leaks.FakeTunerService;
+import com.android.systemui.utils.leaks.LeakCheckedTest;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.ArgumentCaptor;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+
+@RunWith(AndroidTestingRunner.class)
+@TestableLooper.RunWithLooper
+@SmallTest
+public class QSFooterViewControllerTest extends LeakCheckedTest {
+
+ @Mock
+ private QSFooterView mView;
+ @Mock
+ private UserManager mUserManager;
+ @Mock
+ private ActivityStarter mActivityStarter;
+ @Mock
+ private DeviceProvisionedController mDeviceProvisionedController;
+ @Mock
+ private UserInfoController mUserInfoController;
+ @Mock
+ private UserTracker mUserTracker;
+ @Mock
+ private QSPanelController mQSPanelController;
+ @Mock
+ private ClipboardManager mClipboardManager;
+ private FakeTunerService mFakeTunerService;
+ private MetricsLogger mMetricsLogger = new FakeMetricsLogger();
+
+ @Mock
+ private SettingsButton mSettingsButton;
+ @Mock
+ private TextView mBuildText;
+ @Mock
+ private View mEdit;
+
+ private QSFooterViewController mController;
+
+ @Before
+ public void setup() throws Exception {
+ MockitoAnnotations.initMocks(this);
+
+ injectLeakCheckedDependencies(ALL_SUPPORTED_CLASSES);
+
+ mFakeTunerService = (FakeTunerService) Dependency.get(TunerService.class);
+
+ mContext.addMockSystemService(ClipboardManager.class, mClipboardManager);
+
+ when(mView.getContext()).thenReturn(mContext);
+ when(mView.getResources()).thenReturn(mContext.getResources());
+ when(mUserTracker.getUserContext()).thenReturn(mContext);
+
+ when(mView.isAttachedToWindow()).thenReturn(true);
+ when(mView.findViewById(R.id.settings_button)).thenReturn(mSettingsButton);
+ when(mView.findViewById(R.id.build)).thenReturn(mBuildText);
+ when(mView.findViewById(android.R.id.edit)).thenReturn(mEdit);
+
+ mController = new QSFooterViewController(mView, mUserManager, mUserInfoController,
+ mActivityStarter, mDeviceProvisionedController, mUserTracker, mQSPanelController,
+ mFakeTunerService, mMetricsLogger);
+
+ mController.init();
+ }
+
+ @Test
+ public void testBuildTextCopy() {
+ String text = "TEST";
+ ArgumentCaptor<View.OnLongClickListener> onLongClickCaptor =
+ ArgumentCaptor.forClass(View.OnLongClickListener.class);
+
+ verify(mBuildText).setOnLongClickListener(onLongClickCaptor.capture());
+
+ when(mBuildText.getText()).thenReturn(text);
+ onLongClickCaptor.getValue().onLongClick(mBuildText);
+
+ ArgumentCaptor<ClipData> captor = ArgumentCaptor.forClass(ClipData.class);
+ verify(mClipboardManager).setPrimaryClip(captor.capture());
+ assertThat(captor.getValue().getItemAt(0).getText()).isEqualTo(text);
+ }
+
+ @Test
+ public void testSettings_UserNotSetup() {
+ ArgumentCaptor<View.OnClickListener> onClickCaptor =
+ ArgumentCaptor.forClass(View.OnClickListener.class);
+ verify(mSettingsButton).setOnClickListener(onClickCaptor.capture());
+
+ when(mDeviceProvisionedController.isCurrentUserSetup()).thenReturn(false);
+
+ onClickCaptor.getValue().onClick(mSettingsButton);
+ // Verify Settings wasn't launched.
+ verify(mActivityStarter, never()).startActivity(any(), anyBoolean());
+ }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/QSFragmentTest.java b/packages/SystemUI/tests/src/com/android/systemui/qs/QSFragmentTest.java
index e472cb22ed6b..90609ccb48d6 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/QSFragmentTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/QSFragmentTest.java
@@ -16,7 +16,9 @@ package com.android.systemui.qs;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
+import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
import android.app.Fragment;
import android.content.Context;
@@ -42,6 +44,7 @@ import com.android.systemui.SysuiBaseFragmentTest;
import com.android.systemui.broadcast.BroadcastDispatcher;
import com.android.systemui.dump.DumpManager;
import com.android.systemui.plugins.statusbar.StatusBarStateController;
+import com.android.systemui.qs.dagger.QSFragmentComponent;
import com.android.systemui.qs.logging.QSLogger;
import com.android.systemui.qs.tileimpl.QSFactoryImpl;
import com.android.systemui.settings.UserTracker;
@@ -61,6 +64,8 @@ import org.junit.Before;
import org.junit.Ignore;
import org.junit.Test;
import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
import java.util.Optional;
@@ -71,6 +76,12 @@ import java.util.Optional;
public class QSFragmentTest extends SysuiBaseFragmentTest {
private MetricsLogger mMockMetricsLogger;
+ @Mock
+ private QSFragmentComponent.Factory mQsComponentFactory;
+ @Mock
+ private QSFragmentComponent mQsFragmentComponent;
+ @Mock
+ private QSPanelController mQSPanelController;
public QSFragmentTest() {
super(QSFragment.class);
@@ -80,6 +91,10 @@ public class QSFragmentTest extends SysuiBaseFragmentTest {
@Before
@Ignore("failing")
public void addLeakCheckDependencies() {
+ MockitoAnnotations.initMocks(this);
+ when(mQsComponentFactory.create(any(QSFragment.class))).thenReturn(mQsFragmentComponent);
+ when(mQsFragmentComponent.getQSPanelController()).thenReturn(mQSPanelController);
+
mMockMetricsLogger = mDependency.injectMockDependency(MetricsLogger.class);
mContext.addMockSystemService(Context.LAYOUT_INFLATER_SERVICE,
new LayoutInflaterBuilder(mContext)
@@ -152,6 +167,6 @@ public class QSFragmentTest extends SysuiBaseFragmentTest {
mock(QSTileHost.class),
mock(StatusBarStateController.class),
commandQueue,
- mock(QSContainerImplController.Builder.class));
+ mQsComponentFactory);
}
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/QSPanelControllerBaseTest.java b/packages/SystemUI/tests/src/com/android/systemui/qs/QSPanelControllerBaseTest.java
new file mode 100644
index 000000000000..bf0e0841de9a
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/QSPanelControllerBaseTest.java
@@ -0,0 +1,141 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.qs;
+
+import static org.junit.Assert.assertEquals;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyBoolean;
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.doAnswer;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import android.testing.AndroidTestingRunner;
+import android.testing.TestableLooper.RunWithLooper;
+
+import androidx.test.filters.SmallTest;
+
+import com.android.internal.logging.MetricsLogger;
+import com.android.internal.logging.UiEventLogger;
+import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
+import com.android.internal.logging.testing.UiEventLoggerFake;
+import com.android.systemui.SysuiTestCase;
+import com.android.systemui.dump.DumpManager;
+import com.android.systemui.media.MediaHost;
+import com.android.systemui.plugins.qs.QSTileView;
+import com.android.systemui.qs.tileimpl.QSTileImpl;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+
+import java.io.FileDescriptor;
+import java.io.PrintWriter;
+import java.io.StringWriter;
+import java.util.Collections;
+
+@RunWith(AndroidTestingRunner.class)
+@RunWithLooper
+@SmallTest
+public class QSPanelControllerBaseTest extends SysuiTestCase {
+
+ @Mock
+ private QSPanel mQSPanel;
+ @Mock
+ private QSTileHost mQSTileHost;
+ @Mock
+ private MediaHost mMediaHost;
+ @Mock
+ private MetricsLogger mMetricsLogger;
+ private UiEventLoggerFake mUiEventLogger = new UiEventLoggerFake();
+ private DumpManager mDumpManager = new DumpManager();
+ @Mock
+ QSTileImpl mQSTile;
+ @Mock
+ QSTileView mQSTileView;
+
+ private QSPanelControllerBase<QSPanel> mController;
+
+ /** Implementation needed to ensure we have a reflectively-available class name. */
+ private static class TestableQSPanelControllerBase extends QSPanelControllerBase<QSPanel> {
+ protected TestableQSPanelControllerBase(QSPanel view, QSTileHost host,
+ MetricsLogger metricsLogger,
+ UiEventLogger uiEventLogger, DumpManager dumpManager) {
+ super(view, host, metricsLogger, uiEventLogger, dumpManager);
+ }
+ }
+
+ @Before
+ public void setup() throws Exception {
+ MockitoAnnotations.initMocks(this);
+
+ when(mQSPanel.getMediaHost()).thenReturn(mMediaHost);
+ when(mQSPanel.isAttachedToWindow()).thenReturn(true);
+ when(mQSPanel.getDumpableTag()).thenReturn("QSPanel");
+ when(mQSPanel.openPanelEvent()).thenReturn(QSEvent.QS_PANEL_EXPANDED);
+ when(mQSPanel.closePanelEvent()).thenReturn(QSEvent.QS_PANEL_COLLAPSED);
+ when(mQSTileHost.getTiles()).thenReturn(Collections.singleton(mQSTile));
+ when(mQSTileHost.createTileView(eq(mQSTile), anyBoolean())).thenReturn(mQSTileView);
+
+ mController = new TestableQSPanelControllerBase(mQSPanel, mQSTileHost,
+ mMetricsLogger, mUiEventLogger, mDumpManager);
+
+ mController.init();
+ }
+
+ @Test
+ public void testSetExpanded_Metrics() {
+ mController.setExpanded(true);
+ verify(mMetricsLogger).visibility(eq(MetricsEvent.QS_PANEL), eq(true));
+ assertEquals(1, mUiEventLogger.numLogs());
+ assertEquals(QSEvent.QS_PANEL_EXPANDED.getId(), mUiEventLogger.eventId(0));
+ mUiEventLogger.getLogs().clear();
+
+ mController.setExpanded(false);
+ verify(mMetricsLogger).visibility(eq(MetricsEvent.QS_PANEL), eq(false));
+ assertEquals(1, mUiEventLogger.numLogs());
+ assertEquals(QSEvent.QS_PANEL_COLLAPSED.getId(), mUiEventLogger.eventId(0));
+ mUiEventLogger.getLogs().clear();
+
+ }
+
+ @Test
+ public void testDump() {
+ String mockTileViewString = "Mock Tile View";
+ String mockTileString = "Mock Tile";
+ doAnswer(invocation -> {
+ PrintWriter pw = invocation.getArgument(1);
+ pw.println(mockTileString);
+ return null;
+ }).when(mQSTile).dump(any(FileDescriptor.class), any(PrintWriter.class),
+ any(String[].class));
+ when(mQSTileView.toString()).thenReturn(mockTileViewString);
+
+ StringWriter w = new StringWriter();
+ PrintWriter pw = new PrintWriter(w);
+ mController.dump(mock(FileDescriptor.class), pw, new String[]{});
+ String expected = "TestableQSPanelControllerBase:\n"
+ + " Tile records:\n"
+ + " " + mockTileString + "\n"
+ + " " + mockTileViewString + "\n";
+ assertEquals(expected, w.getBuffer().toString());
+ }
+
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/QSPanelControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/qs/QSPanelControllerTest.java
new file mode 100644
index 000000000000..0ba0214d2173
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/QSPanelControllerTest.java
@@ -0,0 +1,106 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.qs;
+
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyBoolean;
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import android.testing.AndroidTestingRunner;
+import android.testing.TestableLooper.RunWithLooper;
+
+import androidx.test.filters.SmallTest;
+
+import com.android.internal.logging.MetricsLogger;
+import com.android.internal.logging.UiEventLogger;
+import com.android.internal.logging.testing.UiEventLoggerFake;
+import com.android.systemui.SysuiTestCase;
+import com.android.systemui.dump.DumpManager;
+import com.android.systemui.media.MediaHost;
+import com.android.systemui.plugins.qs.QSTileView;
+import com.android.systemui.qs.tileimpl.QSTileImpl;
+import com.android.systemui.settings.BrightnessController;
+import com.android.systemui.settings.ToggleSlider;
+import com.android.systemui.tuner.TunerService;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+
+import java.util.Collections;
+
+@RunWith(AndroidTestingRunner.class)
+@RunWithLooper
+@SmallTest
+public class QSPanelControllerTest extends SysuiTestCase {
+
+ @Mock
+ private QSPanel mQSPanel;
+ @Mock
+ private QSTileHost mQSTileHost;
+ @Mock
+ private MediaHost mMediaHost;
+ @Mock
+ private MetricsLogger mMetricsLogger;
+ private UiEventLogger mUiEventLogger = new UiEventLoggerFake();
+ private DumpManager mDumpManager = new DumpManager();
+ @Mock
+ private TunerService mTunerService;
+ @Mock
+ private QSSecurityFooter mQSSecurityFooter;
+ @Mock
+ private BrightnessController.Factory mBrightnessControllerFactory;
+ @Mock
+ private BrightnessController mBrightnessController;
+ @Mock
+ QSTileImpl mQSTile;
+ @Mock
+ QSTileView mQSTileView;
+
+ private QSPanelController mController;
+
+ @Before
+ public void setup() throws Exception {
+ MockitoAnnotations.initMocks(this);
+
+ when(mQSPanel.getMediaHost()).thenReturn(mMediaHost);
+ when(mQSPanel.isAttachedToWindow()).thenReturn(true);
+ when(mQSPanel.getDumpableTag()).thenReturn("QSPanel");
+ when(mQSTileHost.getTiles()).thenReturn(Collections.singleton(mQSTile));
+ when(mQSTileHost.createTileView(eq(mQSTile), anyBoolean())).thenReturn(mQSTileView);
+ when(mBrightnessControllerFactory.create(any(ToggleSlider.class)))
+ .thenReturn(mBrightnessController);
+
+ mController = new QSPanelController(mQSPanel, mQSSecurityFooter, mTunerService,
+ mQSTileHost, mDumpManager, mMetricsLogger, mUiEventLogger,
+ mBrightnessControllerFactory);
+
+ mController.init();
+ }
+
+ @Test
+ public void testOpenDetailsWithNonExistingTile_NoException() {
+ mController.openDetails("none");
+
+ verify(mQSPanel, never()).openDetails(any());
+ }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/QSPanelTest.java b/packages/SystemUI/tests/src/com/android/systemui/qs/QSPanelTest.java
index 4b7a26870308..e38d54b90f69 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/QSPanelTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/QSPanelTest.java
@@ -14,12 +14,9 @@
package com.android.systemui.qs;
-import static org.junit.Assert.assertEquals;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyBoolean;
import static org.mockito.ArgumentMatchers.anyInt;
-import static org.mockito.ArgumentMatchers.eq;
-import static org.mockito.Mockito.doAnswer;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.verify;
@@ -36,19 +33,15 @@ import android.widget.FrameLayout;
import androidx.test.filters.SmallTest;
import com.android.internal.logging.MetricsLogger;
-import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
import com.android.internal.logging.testing.UiEventLoggerFake;
import com.android.systemui.Dependency;
import com.android.systemui.SysuiTestCase;
-import com.android.systemui.broadcast.BroadcastDispatcher;
-import com.android.systemui.dump.DumpManager;
import com.android.systemui.media.MediaHost;
import com.android.systemui.plugins.ActivityStarter;
import com.android.systemui.plugins.qs.QSTileView;
import com.android.systemui.qs.customize.QSCustomizer;
import com.android.systemui.qs.logging.QSLogger;
import com.android.systemui.qs.tileimpl.QSTileImpl;
-import com.android.systemui.settings.UserTracker;
import com.android.systemui.statusbar.policy.SecurityController;
import com.android.systemui.util.animation.DisappearParameters;
import com.android.systemui.util.animation.UniqueObjectHostView;
@@ -59,9 +52,6 @@ import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
-import java.io.FileDescriptor;
-import java.io.PrintWriter;
-import java.io.StringWriter;
import java.util.Collections;
@RunWith(AndroidTestingRunner.class)
@@ -79,9 +69,9 @@ public class QSPanelTest extends SysuiTestCase {
@Mock
private QSTileImpl dndTile;
@Mock
- private BroadcastDispatcher mBroadcastDispatcher;
+ private QSTileImpl mNonTile;
@Mock
- private DumpManager mDumpManager;
+ private QSPanelControllerBase.TileRecord mDndTileRecord;
@Mock
private QSLogger mQSLogger;
private ViewGroup mParentView;
@@ -93,9 +83,8 @@ public class QSPanelTest extends SysuiTestCase {
private MediaHost mMediaHost;
@Mock
private ActivityStarter mActivityStarter;
- @Mock(stubOnly = true)
- private UserTracker mUserTracker;
private UiEventLoggerFake mUiEventLogger;
+ private String mCachedSpecs = "";
@Before
public void setup() throws Exception {
@@ -109,12 +98,13 @@ public class QSPanelTest extends SysuiTestCase {
mContext.addMockSystemService(Context.USER_SERVICE, mock(UserManager.class));
when(mMediaHost.getHostView()).thenReturn(new UniqueObjectHostView(getContext()));
when(mMediaHost.getDisappearParameters()).thenReturn(new DisappearParameters());
+ mDndTileRecord.tile = dndTile;
+ mDndTileRecord.tileView = mQSTileView;
mUiEventLogger = new UiEventLoggerFake();
mTestableLooper.runWithLooper(() -> {
mMetricsLogger = mDependency.injectMockDependency(MetricsLogger.class);
- mQsPanel = new QSPanel(mContext, null, mDumpManager, mBroadcastDispatcher,
- mQSLogger, mMediaHost, mUiEventLogger, mUserTracker);
+ mQsPanel = new QSPanel(mContext, null, mQSLogger, mMediaHost, mUiEventLogger);
mQsPanel.onFinishInflate();
// Provides a parent with non-zero size for QSPanel
mParentView = new FrameLayout(mContext);
@@ -124,8 +114,8 @@ public class QSPanelTest extends SysuiTestCase {
when(mHost.getTiles()).thenReturn(Collections.emptyList());
when(mHost.createTileView(any(), anyBoolean())).thenReturn(mQSTileView);
- mQsPanel.setHost(mHost, mCustomizer);
- mQsPanel.addTile(dndTile, true);
+ mQsPanel.setCustomizer(mCustomizer);
+ mQsPanel.addTile(mDndTileRecord);
mQsPanel.setCallback(mCallback);
});
}
@@ -133,25 +123,16 @@ public class QSPanelTest extends SysuiTestCase {
@Test
public void testSetExpanded_Metrics() {
mQsPanel.setExpanded(true);
- verify(mMetricsLogger).visibility(eq(MetricsEvent.QS_PANEL), eq(true));
verify(mQSLogger).logPanelExpanded(true, mQsPanel.getDumpableTag());
- assertEquals(1, mUiEventLogger.numLogs());
- assertEquals(QSEvent.QS_PANEL_EXPANDED.getId(), mUiEventLogger.eventId(0));
- mUiEventLogger.getLogs().clear();
mQsPanel.setExpanded(false);
- verify(mMetricsLogger).visibility(eq(MetricsEvent.QS_PANEL), eq(false));
verify(mQSLogger).logPanelExpanded(false, mQsPanel.getDumpableTag());
- assertEquals(1, mUiEventLogger.numLogs());
- assertEquals(QSEvent.QS_PANEL_COLLAPSED.getId(), mUiEventLogger.eventId(0));
- mUiEventLogger.getLogs().clear();
-
}
@Test
public void testOpenDetailsWithExistingTile_NoException() {
mTestableLooper.processAllMessages();
- mQsPanel.openDetails("dnd");
+ mQsPanel.openDetails(dndTile);
mTestableLooper.processAllMessages();
verify(mCallback).onShowingDetail(any(), anyInt(), anyInt());
@@ -159,53 +140,19 @@ public class QSPanelTest extends SysuiTestCase {
@Test
public void setListening() {
- when(dndTile.getTileSpec()).thenReturn("dnd");
-
- mQsPanel.setListening(true);
+ mQsPanel.setListening(true, "dnd");
verify(mQSLogger).logAllTilesChangeListening(true, mQsPanel.getDumpableTag(), "dnd");
- mQsPanel.setListening(false);
+ mQsPanel.setListening(false, "dnd");
verify(mQSLogger).logAllTilesChangeListening(false, mQsPanel.getDumpableTag(), "dnd");
}
-/* @Test
+ @Test
public void testOpenDetailsWithNullParameter_NoException() {
mTestableLooper.processAllMessages();
mQsPanel.openDetails(null);
mTestableLooper.processAllMessages();
verify(mCallback, never()).onShowingDetail(any(), anyInt(), anyInt());
- }*/
-
- @Test
- public void testOpenDetailsWithNonExistingTile_NoException() {
- mTestableLooper.processAllMessages();
- mQsPanel.openDetails("invalid-name");
- mTestableLooper.processAllMessages();
-
- verify(mCallback, never()).onShowingDetail(any(), anyInt(), anyInt());
- }
-
- @Test
- public void testDump() {
- String mockTileViewString = "Mock Tile View";
- String mockTileString = "Mock Tile";
- doAnswer(invocation -> {
- PrintWriter pw = invocation.getArgument(1);
- pw.println(mockTileString);
- return null;
- }).when(dndTile).dump(any(FileDescriptor.class), any(PrintWriter.class),
- any(String[].class));
- when(mQSTileView.toString()).thenReturn(mockTileViewString);
-
- StringWriter w = new StringWriter();
- PrintWriter pw = new PrintWriter(w);
- mQsPanel.dump(mock(FileDescriptor.class), pw, new String[]{});
- String expected = "QSPanel:\n"
- + " Tile records:\n"
- + " " + mockTileString + "\n"
- + " " + mockTileViewString + "\n";
- assertEquals(expected, w.getBuffer().toString());
}
-
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/TileLayoutTest.java b/packages/SystemUI/tests/src/com/android/systemui/qs/TileLayoutTest.java
index fef47bd6a392..6c7c20a15140 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/TileLayoutTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/TileLayoutTest.java
@@ -57,8 +57,8 @@ public class TileLayoutTest extends SysuiTestCase {
mContext.getResources().getDimensionPixelSize(R.dimen.qs_tile_margin_horizontal) * 3;
}
- private QSPanel.TileRecord createTileRecord() {
- QSPanel.TileRecord tileRecord = new QSPanel.TileRecord();
+ private QSPanelControllerBase.TileRecord createTileRecord() {
+ QSPanelControllerBase.TileRecord tileRecord = new QSPanelControllerBase.TileRecord();
tileRecord.tile = mock(QSTile.class);
tileRecord.tileView = spy(new QSTileView(mContext, new QSIconViewImpl(mContext)));
return tileRecord;
@@ -66,14 +66,14 @@ public class TileLayoutTest extends SysuiTestCase {
@Test
public void testAddTile_CallsSetListeningOnTile() {
- QSPanel.TileRecord tileRecord = createTileRecord();
+ QSPanelControllerBase.TileRecord tileRecord = createTileRecord();
mTileLayout.addTile(tileRecord);
verify(tileRecord.tile, times(1)).setListening(mTileLayout, false);
}
@Test
public void testSetListening_CallsSetListeningOnTile() {
- QSPanel.TileRecord tileRecord = createTileRecord();
+ QSPanelControllerBase.TileRecord tileRecord = createTileRecord();
mTileLayout.addTile(tileRecord);
mTileLayout.setListening(true);
verify(tileRecord.tile, times(1)).setListening(mTileLayout, true);
@@ -81,7 +81,7 @@ public class TileLayoutTest extends SysuiTestCase {
@Test
public void testSetListening_SameValueIsNoOp() {
- QSPanel.TileRecord tileRecord = createTileRecord();
+ QSPanelControllerBase.TileRecord tileRecord = createTileRecord();
mTileLayout.addTile(tileRecord);
mTileLayout.setListening(false);
verify(tileRecord.tile, times(1)).setListening(any(), anyBoolean());
@@ -89,7 +89,7 @@ public class TileLayoutTest extends SysuiTestCase {
@Test
public void testSetListening_ChangesValueForAddingFutureTiles() {
- QSPanel.TileRecord tileRecord = createTileRecord();
+ QSPanelControllerBase.TileRecord tileRecord = createTileRecord();
mTileLayout.setListening(true);
mTileLayout.addTile(tileRecord);
verify(tileRecord.tile, times(1)).setListening(mTileLayout, true);
@@ -97,7 +97,7 @@ public class TileLayoutTest extends SysuiTestCase {
@Test
public void testRemoveTile_CallsSetListeningFalseOnTile() {
- QSPanel.TileRecord tileRecord = createTileRecord();
+ QSPanelControllerBase.TileRecord tileRecord = createTileRecord();
mTileLayout.setListening(true);
mTileLayout.addTile(tileRecord);
mTileLayout.removeTile(tileRecord);
@@ -106,8 +106,8 @@ public class TileLayoutTest extends SysuiTestCase {
@Test
public void testRemoveAllViews_CallsSetListeningFalseOnAllTiles() {
- QSPanel.TileRecord tileRecord1 = createTileRecord();
- QSPanel.TileRecord tileRecord2 = createTileRecord();
+ QSPanelControllerBase.TileRecord tileRecord1 = createTileRecord();
+ QSPanelControllerBase.TileRecord tileRecord2 = createTileRecord();
mTileLayout.setListening(true);
mTileLayout.addTile(tileRecord1);
mTileLayout.addTile(tileRecord2);
@@ -118,7 +118,7 @@ public class TileLayoutTest extends SysuiTestCase {
@Test
public void testMeasureLayout_CallsLayoutOnTile() {
- QSPanel.TileRecord tileRecord = createTileRecord();
+ QSPanelControllerBase.TileRecord tileRecord = createTileRecord();
mTileLayout.addTile(tileRecord);
mTileLayout.measure(mLayoutSizeForOneTile, mLayoutSizeForOneTile);
mTileLayout.layout(0, 0, mLayoutSizeForOneTile, mLayoutSizeForOneTile);
@@ -127,8 +127,8 @@ public class TileLayoutTest extends SysuiTestCase {
@Test
public void testMeasureLayout_CallsLayoutOnTilesWithNeighboredBounds() {
- QSPanel.TileRecord tileRecord1 = createTileRecord();
- QSPanel.TileRecord tileRecord2 = createTileRecord();
+ QSPanelControllerBase.TileRecord tileRecord1 = createTileRecord();
+ QSPanelControllerBase.TileRecord tileRecord2 = createTileRecord();
mTileLayout.addTile(tileRecord1);
mTileLayout.addTile(tileRecord2);
mTileLayout.measure(mLayoutSizeForOneTile * 2, mLayoutSizeForOneTile * 2);
diff --git a/packages/SystemUI/tests/src/com/android/systemui/screenshot/ActionProxyReceiverTest.java b/packages/SystemUI/tests/src/com/android/systemui/screenshot/ActionProxyReceiverTest.java
index 4aaafbdaec1d..de176b84ac4c 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/screenshot/ActionProxyReceiverTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/screenshot/ActionProxyReceiverTest.java
@@ -16,9 +16,9 @@
package com.android.systemui.screenshot;
-import static com.android.systemui.screenshot.GlobalScreenshot.ACTION_TYPE_SHARE;
-import static com.android.systemui.screenshot.GlobalScreenshot.EXTRA_ID;
-import static com.android.systemui.screenshot.GlobalScreenshot.EXTRA_SMART_ACTIONS_ENABLED;
+import static com.android.systemui.screenshot.ScreenshotController.ACTION_TYPE_SHARE;
+import static com.android.systemui.screenshot.ScreenshotController.EXTRA_ID;
+import static com.android.systemui.screenshot.ScreenshotController.EXTRA_SMART_ACTIONS_ENABLED;
import static com.android.systemui.statusbar.phone.StatusBar.SYSTEM_DIALOG_REASON_SCREENSHOT;
import static org.mockito.ArgumentMatchers.any;
@@ -79,7 +79,7 @@ public class ActionProxyReceiverTest extends SysuiTestCase {
public void setup() throws InterruptedException, ExecutionException, TimeoutException {
MockitoAnnotations.initMocks(this);
mIntent = new Intent(mContext, ActionProxyReceiver.class)
- .putExtra(GlobalScreenshot.EXTRA_ACTION_INTENT, mMockPendingIntent);
+ .putExtra(ScreenshotController.EXTRA_ACTION_INTENT, mMockPendingIntent);
when(mMockActivityManagerWrapper.closeSystemWindows(anyString())).thenReturn(mMockFuture);
when(mMockFuture.get(anyLong(), any(TimeUnit.class))).thenReturn(null);
diff --git a/packages/SystemUI/tests/src/com/android/systemui/screenshot/DeleteScreenshotReceiverTest.java b/packages/SystemUI/tests/src/com/android/systemui/screenshot/DeleteScreenshotReceiverTest.java
index b9249131c191..14c76798e0ef 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/screenshot/DeleteScreenshotReceiverTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/screenshot/DeleteScreenshotReceiverTest.java
@@ -16,10 +16,10 @@
package com.android.systemui.screenshot;
-import static com.android.systemui.screenshot.GlobalScreenshot.ACTION_TYPE_DELETE;
-import static com.android.systemui.screenshot.GlobalScreenshot.EXTRA_ID;
-import static com.android.systemui.screenshot.GlobalScreenshot.EXTRA_SMART_ACTIONS_ENABLED;
-import static com.android.systemui.screenshot.GlobalScreenshot.SCREENSHOT_URI_ID;
+import static com.android.systemui.screenshot.ScreenshotController.ACTION_TYPE_DELETE;
+import static com.android.systemui.screenshot.ScreenshotController.EXTRA_ID;
+import static com.android.systemui.screenshot.ScreenshotController.EXTRA_SMART_ACTIONS_ENABLED;
+import static com.android.systemui.screenshot.ScreenshotController.SCREENSHOT_URI_ID;
import static junit.framework.Assert.assertEquals;
import static junit.framework.Assert.assertNotNull;
diff --git a/packages/SystemUI/tests/src/com/android/systemui/screenshot/ScreenshotNotificationSmartActionsTest.java b/packages/SystemUI/tests/src/com/android/systemui/screenshot/ScreenshotNotificationSmartActionsTest.java
index e23f92616565..2374b82aa9ff 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/screenshot/ScreenshotNotificationSmartActionsTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/screenshot/ScreenshotNotificationSmartActionsTest.java
@@ -169,8 +169,8 @@ public class ScreenshotNotificationSmartActionsTest extends SysuiTestCase {
Looper.prepare();
}
- GlobalScreenshot.SaveImageInBackgroundData
- data = new GlobalScreenshot.SaveImageInBackgroundData();
+ ScreenshotController.SaveImageInBackgroundData
+ data = new ScreenshotController.SaveImageInBackgroundData();
data.image = Bitmap.createBitmap(100, 100, Bitmap.Config.ARGB_8888);
data.finisher = null;
data.mActionsReadyListener = null;
@@ -183,9 +183,9 @@ public class ScreenshotNotificationSmartActionsTest extends SysuiTestCase {
Intent intent = shareAction.actionIntent.getIntent();
assertNotNull(intent);
Bundle bundle = intent.getExtras();
- assertTrue(bundle.containsKey(GlobalScreenshot.EXTRA_ID));
- assertTrue(bundle.containsKey(GlobalScreenshot.EXTRA_SMART_ACTIONS_ENABLED));
- assertEquals(GlobalScreenshot.ACTION_TYPE_SHARE, shareAction.title);
+ assertTrue(bundle.containsKey(ScreenshotController.EXTRA_ID));
+ assertTrue(bundle.containsKey(ScreenshotController.EXTRA_SMART_ACTIONS_ENABLED));
+ assertEquals(ScreenshotController.ACTION_TYPE_SHARE, shareAction.title);
assertEquals(Intent.ACTION_SEND, intent.getAction());
}
@@ -196,8 +196,8 @@ public class ScreenshotNotificationSmartActionsTest extends SysuiTestCase {
Looper.prepare();
}
- GlobalScreenshot.SaveImageInBackgroundData
- data = new GlobalScreenshot.SaveImageInBackgroundData();
+ ScreenshotController.SaveImageInBackgroundData
+ data = new ScreenshotController.SaveImageInBackgroundData();
data.image = Bitmap.createBitmap(100, 100, Bitmap.Config.ARGB_8888);
data.finisher = null;
data.mActionsReadyListener = null;
@@ -210,9 +210,9 @@ public class ScreenshotNotificationSmartActionsTest extends SysuiTestCase {
Intent intent = editAction.actionIntent.getIntent();
assertNotNull(intent);
Bundle bundle = intent.getExtras();
- assertTrue(bundle.containsKey(GlobalScreenshot.EXTRA_ID));
- assertTrue(bundle.containsKey(GlobalScreenshot.EXTRA_SMART_ACTIONS_ENABLED));
- assertEquals(GlobalScreenshot.ACTION_TYPE_EDIT, editAction.title);
+ assertTrue(bundle.containsKey(ScreenshotController.EXTRA_ID));
+ assertTrue(bundle.containsKey(ScreenshotController.EXTRA_SMART_ACTIONS_ENABLED));
+ assertEquals(ScreenshotController.ACTION_TYPE_EDIT, editAction.title);
assertEquals(Intent.ACTION_EDIT, intent.getAction());
}
@@ -223,8 +223,8 @@ public class ScreenshotNotificationSmartActionsTest extends SysuiTestCase {
Looper.prepare();
}
- GlobalScreenshot.SaveImageInBackgroundData
- data = new GlobalScreenshot.SaveImageInBackgroundData();
+ ScreenshotController.SaveImageInBackgroundData
+ data = new ScreenshotController.SaveImageInBackgroundData();
data.image = Bitmap.createBitmap(100, 100, Bitmap.Config.ARGB_8888);
data.finisher = null;
data.mActionsReadyListener = null;
@@ -238,9 +238,9 @@ public class ScreenshotNotificationSmartActionsTest extends SysuiTestCase {
Intent intent = deleteAction.actionIntent.getIntent();
assertNotNull(intent);
Bundle bundle = intent.getExtras();
- assertTrue(bundle.containsKey(GlobalScreenshot.EXTRA_ID));
- assertTrue(bundle.containsKey(GlobalScreenshot.EXTRA_SMART_ACTIONS_ENABLED));
- assertEquals(deleteAction.title, GlobalScreenshot.ACTION_TYPE_DELETE);
+ assertTrue(bundle.containsKey(ScreenshotController.EXTRA_ID));
+ assertTrue(bundle.containsKey(ScreenshotController.EXTRA_SMART_ACTIONS_ENABLED));
+ assertEquals(deleteAction.title, ScreenshotController.ACTION_TYPE_DELETE);
assertNull(intent.getAction());
}
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/screenshot/ScrollCaptureTest.java b/packages/SystemUI/tests/src/com/android/systemui/screenshot/ScrollCaptureTest.java
index e7ef64e6adad..2b3ca7c00a49 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/screenshot/ScrollCaptureTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/screenshot/ScrollCaptureTest.java
@@ -25,8 +25,8 @@ import android.os.RemoteException;
import android.testing.AndroidTestingRunner;
import android.util.Log;
import android.view.Display;
-import android.view.IScrollCaptureClient;
-import android.view.IScrollCaptureController;
+import android.view.IScrollCaptureCallbacks;
+import android.view.IScrollCaptureConnection;
import android.view.IWindowManager;
import android.view.WindowManagerGlobal;
@@ -65,19 +65,20 @@ public class ScrollCaptureTest extends SysuiTestCase {
final CountDownLatch latch = new CountDownLatch(1);
try {
wms.requestScrollCapture(Display.DEFAULT_DISPLAY, null, -1,
- new IScrollCaptureController.Stub() {
+ new IScrollCaptureCallbacks.Stub() {
@Override
- public void onClientConnected(
- IScrollCaptureClient client, Rect scrollBounds,
+ public void onConnected(
+ IScrollCaptureConnection connection, Rect scrollBounds,
Point positionInWindow) {
Log.d(TAG,
- "client connected: " + client + "[scrollBounds= " + scrollBounds
- + ", positionInWindow=" + positionInWindow + "]");
+ "client connected: " + connection + "[scrollBounds= "
+ + scrollBounds + ", "
+ + "positionInWindow=" + positionInWindow + "]");
latch.countDown();
}
@Override
- public void onClientUnavailable() {
+ public void onUnavailable() {
}
@Override
diff --git a/packages/SystemUI/tests/src/com/android/systemui/screenshot/SmartActionsReceiverTest.java b/packages/SystemUI/tests/src/com/android/systemui/screenshot/SmartActionsReceiverTest.java
index ce6f0736ec33..6f3a4a17a4a5 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/screenshot/SmartActionsReceiverTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/screenshot/SmartActionsReceiverTest.java
@@ -16,8 +16,8 @@
package com.android.systemui.screenshot;
-import static com.android.systemui.screenshot.GlobalScreenshot.EXTRA_ACTION_TYPE;
-import static com.android.systemui.screenshot.GlobalScreenshot.EXTRA_ID;
+import static com.android.systemui.screenshot.ScreenshotController.EXTRA_ACTION_TYPE;
+import static com.android.systemui.screenshot.ScreenshotController.EXTRA_ID;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.eq;
@@ -56,7 +56,7 @@ public class SmartActionsReceiverTest extends SysuiTestCase {
MockitoAnnotations.initMocks(this);
mSmartActionsReceiver = new SmartActionsReceiver(mMockScreenshotSmartActions);
mIntent = new Intent(mContext, SmartActionsReceiver.class)
- .putExtra(GlobalScreenshot.EXTRA_ACTION_INTENT, mMockPendingIntent);
+ .putExtra(ScreenshotController.EXTRA_ACTION_INTENT, mMockPendingIntent);
}
@Test
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRowTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRowTest.java
index 8f1d71c80e2d..891179c32315 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRowTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRowTest.java
@@ -96,8 +96,8 @@ public class ExpandableNotificationRowTest extends SysuiTestCase {
mGroupRow.setSensitive(true, true);
mGroupRow.setHideSensitive(true, false, 0, 0);
mGroupRow.setHideSensitive(false, true, 0, 0);
- assertTrue(mGroupRow.getChildrenContainer().getVisibleHeader().getVisibility()
- == View.VISIBLE);
+ assertEquals(View.VISIBLE, mGroupRow.getChildrenContainer().getVisibleWrapper()
+ .getNotificationHeader().getVisibility());
}
@Test
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationChildrenContainerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationChildrenContainerTest.java
index b9055ec0bb7b..7c41abba6176 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationChildrenContainerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationChildrenContainerTest.java
@@ -57,7 +57,7 @@ public class NotificationChildrenContainerTest extends SysuiTestCase {
public void testGetMaxAllowedVisibleChildren_lowPriority() {
mChildrenContainer.setIsLowPriority(true);
Assert.assertEquals(mChildrenContainer.getMaxAllowedVisibleChildren(),
- NotificationChildrenContainer.NUMBER_OF_CHILDREN_WHEN_SYSTEM_EXPANDED);
+ NotificationChildrenContainer.NUMBER_OF_CHILDREN_WHEN_SYSTEM_EXPANDED);
}
@Test
@@ -72,7 +72,7 @@ public class NotificationChildrenContainerTest extends SysuiTestCase {
mChildrenContainer.setIsLowPriority(true);
mChildrenContainer.setChildrenExpanded(true);
Assert.assertEquals(mChildrenContainer.getMaxAllowedVisibleChildren(),
- NotificationChildrenContainer.NUMBER_OF_CHILDREN_WHEN_SYSTEM_EXPANDED);
+ NotificationChildrenContainer.NUMBER_OF_CHILDREN_WHEN_SYSTEM_EXPANDED);
}
@Test
@@ -80,13 +80,13 @@ public class NotificationChildrenContainerTest extends SysuiTestCase {
mChildrenContainer.setIsLowPriority(true);
mChildrenContainer.setUserLocked(true);
Assert.assertEquals(mChildrenContainer.getMaxAllowedVisibleChildren(),
- NotificationChildrenContainer.NUMBER_OF_CHILDREN_WHEN_SYSTEM_EXPANDED);
+ NotificationChildrenContainer.NUMBER_OF_CHILDREN_WHEN_SYSTEM_EXPANDED);
}
@Test
public void testGetMaxAllowedVisibleChildren_likeCollapsed() {
Assert.assertEquals(mChildrenContainer.getMaxAllowedVisibleChildren(true),
- NotificationChildrenContainer.NUMBER_OF_CHILDREN_WHEN_COLLAPSED);
+ NotificationChildrenContainer.NUMBER_OF_CHILDREN_WHEN_COLLAPSED);
}
@@ -136,12 +136,13 @@ public class NotificationChildrenContainerTest extends SysuiTestCase {
@Test
public void testLowPriorityHeaderCleared() {
mGroup.setIsLowPriority(true);
- NotificationHeaderView lowPriorityHeaderView = mChildrenContainer.getLowPriorityHeaderView();
- Assert.assertTrue(lowPriorityHeaderView.getVisibility() == View.VISIBLE);
- Assert.assertTrue(lowPriorityHeaderView.getParent() == mChildrenContainer);
+ NotificationHeaderView lowPriorityHeaderView =
+ mChildrenContainer.getLowPriorityViewWrapper().getNotificationHeader();
+ Assert.assertEquals(View.VISIBLE, lowPriorityHeaderView.getVisibility());
+ Assert.assertSame(mChildrenContainer, lowPriorityHeaderView.getParent());
mGroup.setIsLowPriority(false);
- Assert.assertTrue(lowPriorityHeaderView.getParent() == null);
- Assert.assertTrue(mChildrenContainer.getLowPriorityHeaderView() == null);
+ Assert.assertNull(lowPriorityHeaderView.getParent());
+ Assert.assertNull(mChildrenContainer.getLowPriorityViewWrapper());
}
@Test
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerBaseTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerBaseTest.java
index 7db1b836f428..13cf679cc5d2 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerBaseTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerBaseTest.java
@@ -45,7 +45,6 @@ import android.net.wifi.WifiManager;
import android.os.Handler;
import android.provider.Settings;
import android.provider.Settings.Global;
-import android.telephony.CdmaEriInformation;
import android.telephony.CellSignalStrength;
import android.telephony.NetworkRegistrationInfo;
import android.telephony.PhoneStateListener;
@@ -121,8 +120,6 @@ public class NetworkControllerBaseTest extends SysuiTestCase {
private NetworkCapabilities mNetCapabilities;
private ConnectivityManager.NetworkCallback mNetworkCallback;
- private CdmaEriInformation mEriInformation;
-
@Rule
public TestWatcher failWatcher = new TestWatcher() {
@Override
@@ -184,11 +181,6 @@ public class NetworkControllerBaseTest extends SysuiTestCase {
doReturn(TelephonyManager.NETWORK_TYPE_LTE).when(mTelephonyDisplayInfo).getNetworkType();
doReturn(TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NONE).when(mTelephonyDisplayInfo)
.getOverrideNetworkType();
-
- mEriInformation = new CdmaEriInformation(CdmaEriInformation.ERI_OFF,
- CdmaEriInformation.ERI_ICON_MODE_NORMAL);
- when(mMockTm.getCdmaEriInformation()).thenReturn(mEriInformation);
-
mConfig = new Config();
mConfig.hspaDataDistinguishable = true;
mCallbackHandler = mock(CallbackHandler.class);
@@ -322,9 +314,8 @@ public class NetworkControllerBaseTest extends SysuiTestCase {
}
public void setCdmaRoaming(boolean isRoaming) {
- mEriInformation.setEriIconIndex(isRoaming ?
- CdmaEriInformation.ERI_ON : CdmaEriInformation.ERI_OFF);
- when(mMockTm.getCdmaEriInformation()).thenReturn(mEriInformation);
+ when(mMockTm.getCdmaEnhancedRoamingIndicatorIconIndex()).thenReturn(
+ isRoaming ? TelephonyManager.ERI_ON : TelephonyManager.ERI_OFF);
}
public void setVoiceRegState(int voiceRegState) {
diff --git a/packages/SystemUI/tests/src/com/android/systemui/utils/leaks/FakeTunerService.java b/packages/SystemUI/tests/src/com/android/systemui/utils/leaks/FakeTunerService.java
index 8db82e2a52fc..97d4aa7e4d19 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/utils/leaks/FakeTunerService.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/utils/leaks/FakeTunerService.java
@@ -14,7 +14,7 @@
package com.android.systemui.utils.leaks;
-import android.content.Context;
+import android.os.UserHandle;
import android.testing.LeakCheck;
import com.android.systemui.tuner.TunerService;
@@ -22,8 +22,10 @@ import com.android.systemui.tuner.TunerService;
public class FakeTunerService extends TunerService {
private final BaseLeakChecker<Tunable> mBaseLeakChecker;
+ private boolean mEnabled;
public FakeTunerService(LeakCheck test) {
+ super(null);
mBaseLeakChecker = new BaseLeakChecker<>(test, "tunable");
}
@@ -74,4 +76,14 @@ public class FakeTunerService extends TunerService {
public void setValue(String setting, int value) {
}
+
+ @Override
+ public void setTunerEnabled(UserHandle user, boolean enabled) {
+ mEnabled = enabled;
+ }
+
+ @Override
+ public boolean isTunerEnabled(UserHandle user) {
+ return mEnabled;
+ }
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/wmshell/WMShellTest.java b/packages/SystemUI/tests/src/com/android/systemui/wmshell/WMShellTest.java
index a58f1fdeb3f3..dd7f263f124a 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/wmshell/WMShellTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/wmshell/WMShellTest.java
@@ -27,6 +27,7 @@ import androidx.test.runner.AndroidJUnit4;
import com.android.keyguard.KeyguardUpdateMonitor;
import com.android.keyguard.KeyguardUpdateMonitorCallback;
+import com.android.systemui.SystemUIFactory;
import com.android.systemui.SysuiTestCase;
import com.android.systemui.keyguard.ScreenLifecycle;
import com.android.systemui.model.SysUiState;
@@ -53,6 +54,7 @@ import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import java.util.Optional;
+import java.util.concurrent.ExecutionException;
@SmallTest
@RunWith(AndroidJUnit4.class)
@@ -64,7 +66,6 @@ public class WMShellTest extends SysuiTestCase {
@Mock ConfigurationController mConfigurationController;
@Mock KeyguardUpdateMonitor mKeyguardUpdateMonitor;
@Mock TaskStackChangeListeners mTaskStackChangeListeners;
- @Mock DisplayImeController mDisplayImeController;
@Mock InputConsumerController mMockInputConsumerController;
@Mock NavigationModeController mNavigationModeController;
@Mock ScreenLifecycle mScreenLifecycle;
@@ -84,21 +85,13 @@ public class WMShellTest extends SysuiTestCase {
mWMShell = new WMShell(mContext, mCommandQueue, mConfigurationController,
mInputConsumerController, mKeyguardUpdateMonitor, mTaskStackChangeListeners,
- mDisplayImeController, mNavigationModeController, mScreenLifecycle, mSysUiState,
- Optional.of(mPip), Optional.of(mSplitScreen), Optional.of(mOneHanded),
- mTaskOrganizer, mProtoTracer);
+ mNavigationModeController, mScreenLifecycle, mSysUiState, Optional.of(mPip),
+ Optional.of(mSplitScreen), Optional.of(mOneHanded), mTaskOrganizer, mProtoTracer);
when(mPip.getPipTouchHandler()).thenReturn(mPipTouchHandler);
}
@Test
- public void start_startsMonitorDisplays() {
- mWMShell.start();
-
- verify(mDisplayImeController).startMonitorDisplays();
- }
-
- @Test
public void initPip_registersCommandQueueCallback() {
mWMShell.initPip(mPip);
diff --git a/packages/Tethering/src/com/android/networkstack/tethering/PrivateAddressCoordinator.java b/packages/Tethering/src/com/android/networkstack/tethering/PrivateAddressCoordinator.java
index 9fc1d7e5bcd0..4f616cdff086 100644
--- a/packages/Tethering/src/com/android/networkstack/tethering/PrivateAddressCoordinator.java
+++ b/packages/Tethering/src/com/android/networkstack/tethering/PrivateAddressCoordinator.java
@@ -80,11 +80,6 @@ public class PrivateAddressCoordinator {
private final SparseArray<LinkAddress> mCachedAddresses;
public PrivateAddressCoordinator(Context context, TetheringConfiguration config) {
- this(context, config, new ArrayList<>(Arrays.asList(new IpPrefix("192.168.0.0/16"))));
- }
-
- public PrivateAddressCoordinator(Context context, TetheringConfiguration config,
- List<IpPrefix> prefixPools) {
mDownstreams = new ArraySet<>();
mUpstreamPrefixMap = new ArrayMap<>();
mConnectivityMgr = (ConnectivityManager) context.getSystemService(
@@ -95,7 +90,11 @@ public class PrivateAddressCoordinator {
mCachedAddresses.put(TETHERING_BLUETOOTH, new LinkAddress(LEGACY_BLUETOOTH_IFACE_ADDRESS));
mCachedAddresses.put(TETHERING_WIFI_P2P, new LinkAddress(LEGACY_WIFI_P2P_IFACE_ADDRESS));
- mTetheringPrefixes = prefixPools;
+ mTetheringPrefixes = new ArrayList<>(Arrays.asList(new IpPrefix("192.168.0.0/16")));
+ if (config.isSelectAllPrefixRangeEnabled()) {
+ mTetheringPrefixes.add(new IpPrefix("172.16.0.0/12"));
+ mTetheringPrefixes.add(new IpPrefix("10.0.0.0/8"));
+ }
}
/**
diff --git a/packages/Tethering/src/com/android/networkstack/tethering/TetheringConfiguration.java b/packages/Tethering/src/com/android/networkstack/tethering/TetheringConfiguration.java
index 5783805861a3..799637c9b1c5 100644
--- a/packages/Tethering/src/com/android/networkstack/tethering/TetheringConfiguration.java
+++ b/packages/Tethering/src/com/android/networkstack/tethering/TetheringConfiguration.java
@@ -40,7 +40,6 @@ import java.util.Arrays;
import java.util.Collection;
import java.util.StringJoiner;
-
/**
* A utility class to encapsulate the various tethering configuration elements.
*
@@ -88,6 +87,13 @@ public class TetheringConfiguration {
"use_legacy_wifi_p2p_dedicated_ip";
/**
+ * Flag use to enable select all prefix ranges feature.
+ * TODO: Remove this flag if there are no problems after M-2020-12 rolls out.
+ */
+ public static final String TETHER_ENABLE_SELECT_ALL_PREFIX_RANGES =
+ "tether_enable_select_all_prefix_ranges";
+
+ /**
* Default value that used to periodic polls tether offload stats from tethering offload HAL
* to make the data warnings work.
*/
@@ -118,6 +124,8 @@ public class TetheringConfiguration {
private final boolean mEnableBpfOffload;
private final boolean mEnableWifiP2pDedicatedIp;
+ private final boolean mEnableSelectAllPrefixRange;
+
public TetheringConfiguration(Context ctx, SharedLog log, int id) {
final SharedLog configLog = log.forSubComponent("config");
@@ -164,6 +172,11 @@ public class TetheringConfiguration {
R.bool.config_tether_enable_legacy_wifi_p2p_dedicated_ip,
false /* defaultValue */);
+ // Flags should normally not be booleans, but this is a kill-switch flag that is only used
+ // to turn off the feature, so binary rollback problems do not apply.
+ mEnableSelectAllPrefixRange = getDeviceConfigBoolean(
+ TETHER_ENABLE_SELECT_ALL_PREFIX_RANGES, true /* defaultValue */);
+
configLog.log(toString());
}
@@ -249,6 +262,9 @@ public class TetheringConfiguration {
pw.print("enableWifiP2pDedicatedIp: ");
pw.println(mEnableWifiP2pDedicatedIp);
+
+ pw.print("mEnableSelectAllPrefixRange: ");
+ pw.println(mEnableSelectAllPrefixRange);
}
/** Returns the string representation of this object.*/
@@ -310,6 +326,10 @@ public class TetheringConfiguration {
return mEnableBpfOffload;
}
+ public boolean isSelectAllPrefixRangeEnabled() {
+ return mEnableSelectAllPrefixRange;
+ }
+
private static Collection<Integer> getUpstreamIfaceTypes(Resources res, boolean dunRequired) {
final int[] ifaceTypes = res.getIntArray(R.array.config_tether_upstream_types);
final ArrayList<Integer> upstreamIfaceTypes = new ArrayList<>(ifaceTypes.length);
diff --git a/packages/Tethering/tests/mts/Android.bp b/packages/Tethering/tests/mts/Android.bp
new file mode 100644
index 000000000000..f925b0a53f32
--- /dev/null
+++ b/packages/Tethering/tests/mts/Android.bp
@@ -0,0 +1,56 @@
+// Copyright (C) 2020 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+android_test {
+ // This tests for functionality that is not required for devices that
+ // don't use Tethering mainline module.
+ name: "MtsTetheringTest",
+
+ libs: [
+ "android.test.base",
+ ],
+
+ srcs: [
+ "src/**/*.java",
+ ],
+
+ static_libs: [
+ "androidx.test.rules",
+ // mockito-target-extended-minus-junit4 used in this lib have dependency with
+ // jni_libs libdexmakerjvmtiagent and libstaticjvmtiagent.
+ "cts-net-utils",
+ // This is needed for androidx.test.runner.AndroidJUnitRunner.
+ "ctstestrunner-axt",
+ "junit",
+ "junit-params",
+ ],
+
+ jni_libs: [
+ // For mockito extended which is pulled in from -net-utils -> net-tests-utils
+ // (mockito-target-extended-minus-junit4).
+ "libdexmakerjvmtiagent",
+ "libstaticjvmtiagent",
+ ],
+
+ platform_apis: true,
+
+ // Tag this module as a mts test artifact
+ test_suites: [
+ "general-tests",
+ "mts",
+ ],
+
+ // Include both the 32 and 64 bit versions
+ compile_multilib: "both",
+}
diff --git a/packages/Tethering/tests/mts/AndroidManifest.xml b/packages/Tethering/tests/mts/AndroidManifest.xml
new file mode 100644
index 000000000000..6d2abcad42a3
--- /dev/null
+++ b/packages/Tethering/tests/mts/AndroidManifest.xml
@@ -0,0 +1,34 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ -->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="android.tethering.mts">
+
+ <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
+ <uses-permission android:name="android.permission.INTERNET"/>
+
+ <application android:debuggable="true">
+ <uses-library android:name="android.test.runner" />
+ </application>
+ <instrumentation android:name="androidx.test.runner.AndroidJUnitRunner"
+ android:targetPackage="android.tethering.mts"
+ android:label="MTS tests of android.tethering">
+ <meta-data android:name="listener"
+ android:value="com.android.cts.runner.CtsTestRunListener" />
+ </instrumentation>
+
+</manifest>
diff --git a/packages/Tethering/tests/mts/AndroidTest.xml b/packages/Tethering/tests/mts/AndroidTest.xml
new file mode 100644
index 000000000000..80788dfa6f40
--- /dev/null
+++ b/packages/Tethering/tests/mts/AndroidTest.xml
@@ -0,0 +1,36 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2019 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<configuration description="Config for MTS Tethering test cases">
+ <option name="test-suite-tag" value="mts" />
+ <option name="config-descriptor:metadata" key="component" value="networking" />
+ <!-- Instant app do not have INTERNET permission. -->
+ <option name="config-descriptor:metadata" key="parameter" value="not_instant_app" />
+ <!-- Feature is not backed by native code. -->
+ <option name="config-descriptor:metadata" key="parameter" value="not_multi_abi" />
+ <!-- Allow running this against a secondary user. -->
+ <option name="config-descriptor:metadata" key="parameter" value="secondary_user" />
+ <target_preparer class="com.android.tradefed.targetprep.suite.SuiteApkInstaller">
+ <option name="cleanup-apks" value="true" />
+ <option name="test-file-name" value="MtsTetheringTest.apk" />
+ </target_preparer>
+ <test class="com.android.tradefed.testtype.AndroidJUnitTest" >
+ <option name="package" value="android.tethering.mts" />
+ </test>
+
+ <object type="module_controller" class="com.android.tradefed.testtype.suite.module.MainlineTestModuleController">
+ <option name="mainline-module-package-name" value="com.google.android.tethering" />
+ </object>
+</configuration>
diff --git a/packages/Tethering/tests/mts/src/android/tethering/mts/TetheringModuleTest.java b/packages/Tethering/tests/mts/src/android/tethering/mts/TetheringModuleTest.java
new file mode 100644
index 000000000000..7ffe37ad648d
--- /dev/null
+++ b/packages/Tethering/tests/mts/src/android/tethering/mts/TetheringModuleTest.java
@@ -0,0 +1,183 @@
+/*
+ * 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 android.tethering.mts;
+
+import static android.Manifest.permission.MANAGE_TEST_NETWORKS;
+import static android.Manifest.permission.NETWORK_SETTINGS;
+import static android.Manifest.permission.READ_DEVICE_CONFIG;
+import static android.Manifest.permission.TETHER_PRIVILEGED;
+import static android.Manifest.permission.WRITE_SETTINGS;
+import static android.net.cts.util.CtsTetheringUtils.isWifiTetheringSupported;
+import static android.provider.DeviceConfig.NAMESPACE_CONNECTIVITY;
+
+import static com.android.testutils.TestNetworkTrackerKt.initTestNetwork;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.fail;
+import static org.junit.Assume.assumeTrue;
+
+import android.app.UiAutomation;
+import android.content.Context;
+import android.net.IpPrefix;
+import android.net.LinkAddress;
+import android.net.TetheringManager;
+import android.net.cts.util.CtsTetheringUtils;
+import android.net.cts.util.CtsTetheringUtils.TestTetheringEventCallback;
+import android.provider.DeviceConfig;
+
+import androidx.annotation.NonNull;
+import androidx.test.InstrumentationRegistry;
+import androidx.test.runner.AndroidJUnit4;
+
+import com.android.testutils.TestNetworkTracker;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.net.InterfaceAddress;
+import java.net.NetworkInterface;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+@RunWith(AndroidJUnit4.class)
+public class TetheringModuleTest {
+ private Context mContext;
+ private TetheringManager mTm;
+ private CtsTetheringUtils mCtsTetheringUtils;
+
+ private UiAutomation mUiAutomation =
+ InstrumentationRegistry.getInstrumentation().getUiAutomation();
+
+ @Before
+ public void setUp() throws Exception {
+ mUiAutomation.adoptShellPermissionIdentity(MANAGE_TEST_NETWORKS, NETWORK_SETTINGS,
+ WRITE_SETTINGS, READ_DEVICE_CONFIG, TETHER_PRIVILEGED);
+ mContext = InstrumentationRegistry.getContext();
+ mTm = mContext.getSystemService(TetheringManager.class);
+ mCtsTetheringUtils = new CtsTetheringUtils(mContext);
+ }
+
+ @After
+ public void tearDown() throws Exception {
+ mUiAutomation.dropShellPermissionIdentity();
+ }
+
+ private static final String TETHER_ENABLE_SELECT_ALL_PREFIX_RANGES =
+ "tether_enable_select_all_prefix_ranges";
+ @Test
+ public void testSwitchBasePrefixRangeWhenConflict() throws Exception {
+ assumeTrue(isFeatureEnabled(TETHER_ENABLE_SELECT_ALL_PREFIX_RANGES, true));
+
+ addressConflictTest(true);
+ }
+
+ @Test
+ public void testSwitchPrefixRangeWhenConflict() throws Exception {
+ addressConflictTest(false);
+ }
+
+ private void addressConflictTest(final boolean wholeRangeConflict) throws Exception {
+ final TestTetheringEventCallback tetherEventCallback =
+ mCtsTetheringUtils.registerTetheringEventCallback();
+
+ TestNetworkTracker tnt = null;
+ try {
+ tetherEventCallback.assumeTetheringSupported();
+ assumeTrue(isWifiTetheringSupported(tetherEventCallback));
+
+ mCtsTetheringUtils.startWifiTethering(tetherEventCallback);
+
+ final List<String> tetheredIfaces = tetherEventCallback.getTetheredInterfaces();
+ assertEquals(1, tetheredIfaces.size());
+ final String wifiTetheringIface = tetheredIfaces.get(0);
+
+ NetworkInterface nif = NetworkInterface.getByName(wifiTetheringIface);
+ // Tethering downstream only have one ipv4 address.
+ final LinkAddress hotspotAddr = getFirstIpv4Address(nif);
+ assertNotNull(hotspotAddr);
+
+ final IpPrefix testPrefix = getConflictingPrefix(hotspotAddr, wholeRangeConflict);
+ assertNotNull(testPrefix);
+
+ tnt = setUpTestNetwork(
+ new LinkAddress(testPrefix.getAddress(), testPrefix.getPrefixLength()));
+
+ tetherEventCallback.expectTetheredInterfacesChanged(null);
+ final List<String> wifiRegexs =
+ tetherEventCallback.getTetheringInterfaceRegexps().getTetherableWifiRegexs();
+
+ tetherEventCallback.expectTetheredInterfacesChanged(wifiRegexs);
+ nif = NetworkInterface.getByName(wifiTetheringIface);
+ final LinkAddress newHotspotAddr = getFirstIpv4Address(nif);
+ assertNotNull(newHotspotAddr);
+
+ assertFalse(testPrefix.containsPrefix(
+ new IpPrefix(newHotspotAddr.getAddress(), newHotspotAddr.getPrefixLength())));
+
+ mCtsTetheringUtils.stopWifiTethering(tetherEventCallback);
+ } finally {
+ if (tnt != null) {
+ tnt.teardown();
+ }
+ mTm.stopAllTethering();
+ mCtsTetheringUtils.unregisterTetheringEventCallback(tetherEventCallback);
+ }
+ }
+
+ private LinkAddress getFirstIpv4Address(final NetworkInterface nif) {
+ for (InterfaceAddress ia : nif.getInterfaceAddresses()) {
+ final LinkAddress addr = new LinkAddress(ia.getAddress(), ia.getNetworkPrefixLength());
+ if (addr.isIpv4()) return addr;
+ }
+ return null;
+ }
+
+ @NonNull
+ private IpPrefix getConflictingPrefix(final LinkAddress address,
+ final boolean wholeRangeConflict) {
+ if (!wholeRangeConflict) {
+ return new IpPrefix(address.getAddress(), address.getPrefixLength());
+ }
+
+ final ArrayList<IpPrefix> prefixPool = new ArrayList<>(Arrays.asList(
+ new IpPrefix("192.168.0.0/16"),
+ new IpPrefix("172.16.0.0/12"),
+ new IpPrefix("10.0.0.0/8")));
+
+ for (IpPrefix prefix : prefixPool) {
+ if (prefix.contains(address.getAddress())) return prefix;
+ }
+
+ fail("Could not find sutiable conflict prefix");
+
+ // Never go here.
+ return null;
+ }
+
+ private TestNetworkTracker setUpTestNetwork(final LinkAddress address) throws Exception {
+ return initTestNetwork(mContext, address, 10_000L /* test timeout ms*/);
+
+ }
+
+ public static boolean isFeatureEnabled(final String name, final boolean defaultValue) {
+ return DeviceConfig.getBoolean(NAMESPACE_CONNECTIVITY, name, defaultValue);
+ }
+}
diff --git a/packages/Tethering/tests/unit/src/com/android/networkstack/tethering/PrivateAddressCoordinatorTest.java b/packages/Tethering/tests/unit/src/com/android/networkstack/tethering/PrivateAddressCoordinatorTest.java
index 8cb80bad809c..41d46e522ca4 100644
--- a/packages/Tethering/tests/unit/src/com/android/networkstack/tethering/PrivateAddressCoordinatorTest.java
+++ b/packages/Tethering/tests/unit/src/com/android/networkstack/tethering/PrivateAddressCoordinatorTest.java
@@ -99,9 +99,9 @@ public final class PrivateAddressCoordinatorTest {
when(mContext.getSystemService(Context.CONNECTIVITY_SERVICE)).thenReturn(mConnectivityMgr);
when(mConnectivityMgr.getAllNetworks()).thenReturn(mAllNetworks);
when(mConfig.shouldEnableWifiP2pDedicatedIp()).thenReturn(false);
+ when(mConfig.isSelectAllPrefixRangeEnabled()).thenReturn(true);
setUpIpServers();
- mPrivateAddressCoordinator = spy(new PrivateAddressCoordinator(mContext, mConfig,
- mTetheringPrefixes));
+ mPrivateAddressCoordinator = spy(new PrivateAddressCoordinator(mContext, mConfig));
}
private LinkAddress requestDownstreamAddress(final IpServer ipServer, boolean useLastAddress) {
diff --git a/packages/Tethering/tests/unit/src/com/android/networkstack/tethering/TetheringConfigurationTest.java b/packages/Tethering/tests/unit/src/com/android/networkstack/tethering/TetheringConfigurationTest.java
index dc0940cc0222..237e2c27bfa1 100644
--- a/packages/Tethering/tests/unit/src/com/android/networkstack/tethering/TetheringConfigurationTest.java
+++ b/packages/Tethering/tests/unit/src/com/android/networkstack/tethering/TetheringConfigurationTest.java
@@ -131,6 +131,7 @@ public class TetheringConfigurationTest {
when(mResources.getBoolean(R.bool.config_tether_enable_legacy_wifi_p2p_dedicated_ip))
.thenReturn(false);
initializeBpfOffloadConfiguration(true, null /* unset */);
+ initEnableSelectAllPrefixRangeFlag(null /* unset */);
mHasTelephonyManager = true;
mMockContext = new MockContext(mContext);
@@ -428,4 +429,30 @@ public class TetheringConfigurationTest {
mMockContext, mLog, INVALID_SUBSCRIPTION_ID);
assertTrue(testCfg.shouldEnableWifiP2pDedicatedIp());
}
+
+ private void initEnableSelectAllPrefixRangeFlag(final String value) {
+ doReturn(value).when(
+ () -> DeviceConfig.getProperty(eq(NAMESPACE_CONNECTIVITY),
+ eq(TetheringConfiguration.TETHER_ENABLE_SELECT_ALL_PREFIX_RANGES)));
+ }
+
+ @Test
+ public void testSelectAllPrefixRangeFlag() throws Exception {
+ // Test default value.
+ final TetheringConfiguration defaultCfg = new TetheringConfiguration(
+ mMockContext, mLog, INVALID_SUBSCRIPTION_ID);
+ assertTrue(defaultCfg.isSelectAllPrefixRangeEnabled());
+
+ // Test disable flag.
+ initEnableSelectAllPrefixRangeFlag("false");
+ final TetheringConfiguration testDisable = new TetheringConfiguration(
+ mMockContext, mLog, INVALID_SUBSCRIPTION_ID);
+ assertFalse(testDisable.isSelectAllPrefixRangeEnabled());
+
+ // Test enable flag.
+ initEnableSelectAllPrefixRangeFlag("true");
+ final TetheringConfiguration testEnable = new TetheringConfiguration(
+ mMockContext, mLog, INVALID_SUBSCRIPTION_ID);
+ assertTrue(testEnable.isSelectAllPrefixRangeEnabled());
+ }
}
diff --git a/packages/Tethering/tests/unit/src/com/android/networkstack/tethering/TetheringTest.java b/packages/Tethering/tests/unit/src/com/android/networkstack/tethering/TetheringTest.java
index 20e94b256ad1..114cb7ca6ec7 100644
--- a/packages/Tethering/tests/unit/src/com/android/networkstack/tethering/TetheringTest.java
+++ b/packages/Tethering/tests/unit/src/com/android/networkstack/tethering/TetheringTest.java
@@ -456,11 +456,7 @@ public class TetheringTest {
@Override
public PrivateAddressCoordinator getPrivateAddressCoordinator(Context ctx,
TetheringConfiguration cfg) {
- final ArrayList<IpPrefix> prefixPool = new ArrayList<>(Arrays.asList(
- new IpPrefix("192.168.0.0/16"),
- new IpPrefix("172.16.0.0/12"),
- new IpPrefix("10.0.0.0/8")));
- mPrivateAddressCoordinator = spy(new PrivateAddressCoordinator(ctx, cfg, prefixPool));
+ mPrivateAddressCoordinator = super.getPrivateAddressCoordinator(ctx, cfg);
return mPrivateAddressCoordinator;
}
}
diff --git a/services/accessibility/java/com/android/server/accessibility/AbstractAccessibilityServiceConnection.java b/services/accessibility/java/com/android/server/accessibility/AbstractAccessibilityServiceConnection.java
index a167ab16f944..d6d4e4f6c746 100644
--- a/services/accessibility/java/com/android/server/accessibility/AbstractAccessibilityServiceConnection.java
+++ b/services/accessibility/java/com/android/server/accessibility/AbstractAccessibilityServiceConnection.java
@@ -150,6 +150,8 @@ abstract class AbstractAccessibilityServiceConnection extends IAccessibilityServ
private boolean mRequestTwoFingerPassthrough;
+ private boolean mSendMotionEvents;
+
boolean mRequestFilterKeyEvents;
boolean mRetrieveInteractiveWindows;
@@ -329,6 +331,8 @@ abstract class AbstractAccessibilityServiceConnection extends IAccessibilityServ
& AccessibilityServiceInfo.FLAG_REQUEST_MULTI_FINGER_GESTURES) != 0;
mRequestTwoFingerPassthrough =
(info.flags & AccessibilityServiceInfo.FLAG_REQUEST_2_FINGER_PASSTHROUGH) != 0;
+ mSendMotionEvents =
+ (info.flags & AccessibilityServiceInfo.FLAG_SEND_MOTION_EVENTS) != 0;
mRequestFilterKeyEvents =
(info.flags & AccessibilityServiceInfo.FLAG_REQUEST_FILTER_KEY_EVENTS) != 0;
mRetrieveInteractiveWindows = (info.flags
@@ -1780,6 +1784,10 @@ abstract class AbstractAccessibilityServiceConnection extends IAccessibilityServ
return mRequestTwoFingerPassthrough;
}
+ public boolean isSendMotionEventsEnabled() {
+ return mSendMotionEvents;
+ }
+
@Override
public void setGestureDetectionPassthroughRegion(int displayId, Region region) {
mSystemSupport.setGestureDetectionPassthroughRegion(displayId, region);
diff --git a/services/accessibility/java/com/android/server/accessibility/AccessibilityInputFilter.java b/services/accessibility/java/com/android/server/accessibility/AccessibilityInputFilter.java
index cd9ab8db0854..857ac6ae62a9 100644
--- a/services/accessibility/java/com/android/server/accessibility/AccessibilityInputFilter.java
+++ b/services/accessibility/java/com/android/server/accessibility/AccessibilityInputFilter.java
@@ -119,12 +119,19 @@ class AccessibilityInputFilter extends InputFilter implements EventStreamTransfo
static final int FLAG_REQUEST_MULTI_FINGER_GESTURES = 0x00000100;
/**
- * Flag for enabling multi-finger gestures.
+ * Flag for enabling two-finger passthrough when multi-finger gestures are enabled.
*
* @see #setUserAndEnabledFeatures(int, int)
*/
static final int FLAG_REQUEST_2_FINGER_PASSTHROUGH = 0x00000200;
+ /**
+ * Flag for including motion events when dispatching a gesture.
+ *
+ * @see #setUserAndEnabledFeatures(int, int)
+ */
+ static final int FLAG_SEND_MOTION_EVENTS = 0x00000400;
+
static final int FEATURES_AFFECTING_MOTION_EVENTS =
FLAG_FEATURE_INJECT_MOTION_EVENTS
| FLAG_FEATURE_AUTOCLICK
@@ -432,6 +439,9 @@ class AccessibilityInputFilter extends InputFilter implements EventStreamTransfo
if ((mEnabledFeatures & FLAG_REQUEST_2_FINGER_PASSTHROUGH) != 0) {
explorer.setTwoFingerPassthroughEnabled(true);
}
+ if ((mEnabledFeatures & FLAG_SEND_MOTION_EVENTS) != 0) {
+ explorer.setSendMotionEventsEnabled(true);
+ }
addFirstEventHandler(displayId, explorer);
mTouchExplorer.put(displayId, explorer);
}
diff --git a/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java b/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java
index e1c499389ec5..35481a282701 100644
--- a/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java
+++ b/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java
@@ -1867,6 +1867,10 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub
if (userState.isFilterKeyEventsEnabledLocked()) {
flags |= AccessibilityInputFilter.FLAG_FEATURE_FILTER_KEY_EVENTS;
}
+ if (userState.isSendMotionEventsEnabled()) {
+ flags |= AccessibilityInputFilter.FLAG_SEND_MOTION_EVENTS;
+ }
+
if (userState.isAutoclickEnabledLocked()) {
flags |= AccessibilityInputFilter.FLAG_FEATURE_AUTOCLICK;
}
@@ -2147,6 +2151,7 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub
boolean serviceHandlesDoubleTapEnabled = false;
boolean requestMultiFingerGestures = false;
boolean requestTwoFingerPassthrough = false;
+ boolean sendMotionEvents = false;
final int serviceCount = userState.mBoundServices.size();
for (int i = 0; i < serviceCount; i++) {
AccessibilityServiceConnection service = userState.mBoundServices.get(i);
@@ -2155,6 +2160,7 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub
serviceHandlesDoubleTapEnabled = service.isServiceHandlesDoubleTapEnabled();
requestMultiFingerGestures = service.isMultiFingerGesturesEnabled();
requestTwoFingerPassthrough = service.isTwoFingerPassthroughEnabled();
+ sendMotionEvents = service.isSendMotionEventsEnabled();
break;
}
}
@@ -2172,6 +2178,7 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub
userState.setServiceHandlesDoubleTapLocked(serviceHandlesDoubleTapEnabled);
userState.setMultiFingerGesturesLocked(requestMultiFingerGestures);
userState.setTwoFingerPassthroughLocked(requestTwoFingerPassthrough);
+ userState.setSendMotionEventsEnabled(sendMotionEvents);
}
private boolean readAccessibilityShortcutKeySettingLocked(AccessibilityUserState userState) {
diff --git a/services/accessibility/java/com/android/server/accessibility/AccessibilityUserState.java b/services/accessibility/java/com/android/server/accessibility/AccessibilityUserState.java
index 4c9e44403026..240c7ff061c8 100644
--- a/services/accessibility/java/com/android/server/accessibility/AccessibilityUserState.java
+++ b/services/accessibility/java/com/android/server/accessibility/AccessibilityUserState.java
@@ -111,6 +111,7 @@ class AccessibilityUserState {
private boolean mServiceHandlesDoubleTap;
private boolean mRequestMultiFingerGestures;
private boolean mRequestTwoFingerPassthrough;
+ private boolean mSendMotionEventsEnabled;
private int mUserInteractiveUiTimeout;
private int mUserNonInteractiveUiTimeout;
private int mNonInteractiveUiTimeout = 0;
@@ -171,6 +172,7 @@ class AccessibilityUserState {
mServiceHandlesDoubleTap = false;
mRequestMultiFingerGestures = false;
mRequestTwoFingerPassthrough = false;
+ mSendMotionEventsEnabled = false;
mIsDisplayMagnificationEnabled = false;
mIsAutoclickEnabled = false;
mUserNonInteractiveUiTimeout = 0;
@@ -460,6 +462,7 @@ class AccessibilityUserState {
.append(String.valueOf(mRequestMultiFingerGestures));
pw.append(", requestTwoFingerPassthrough=")
.append(String.valueOf(mRequestTwoFingerPassthrough));
+ pw.append(", sendMotionEventsEnabled").append(String.valueOf(mSendMotionEventsEnabled));
pw.append(", displayMagnificationEnabled=").append(String.valueOf(
mIsDisplayMagnificationEnabled));
pw.append(", autoclickEnabled=").append(String.valueOf(mIsAutoclickEnabled));
@@ -802,6 +805,13 @@ class AccessibilityUserState {
mRequestTwoFingerPassthrough = enabled;
}
+ public boolean isSendMotionEventsEnabled() {
+ return mSendMotionEventsEnabled;
+ }
+
+ public void setSendMotionEventsEnabled(boolean mode) {
+ mSendMotionEventsEnabled = mode;
+ }
public int getUserInteractiveUiTimeoutLocked() {
return mUserInteractiveUiTimeout;
diff --git a/services/accessibility/java/com/android/server/accessibility/gestures/GestureManifold.java b/services/accessibility/java/com/android/server/accessibility/gestures/GestureManifold.java
index 14af8c63073e..2c38dc330a62 100644
--- a/services/accessibility/java/com/android/server/accessibility/gestures/GestureManifold.java
+++ b/services/accessibility/java/com/android/server/accessibility/gestures/GestureManifold.java
@@ -99,11 +99,15 @@ class GestureManifold implements GestureMatcher.StateChangeListener {
boolean mMultiFingerGesturesEnabled;
// Whether the two-finger passthrough is enabled when multi-finger gestures are enabled.
private boolean mTwoFingerPassthroughEnabled;
+ // Whether to send the motion events during gesture dispatch.
+ private boolean mSendMotionEventsEnabled = false;
// A list of all the multi-finger gestures, for easy adding and removal.
private final List<GestureMatcher> mMultiFingerGestures = new ArrayList<>();
// A list of two-finger swipes, for easy adding and removal when turning on or off two-finger
// passthrough.
private final List<GestureMatcher> mTwoFingerSwipes = new ArrayList<>();
+ // The list of motion events for the current gesture.
+ private List<MotionEvent> mEvents = new ArrayList<>();
// Shared state information.
private TouchState mState;
@@ -230,6 +234,9 @@ class GestureManifold implements GestureMatcher.StateChangeListener {
return false;
}
}
+ if (mSendMotionEventsEnabled) {
+ mEvents.add(MotionEvent.obtainNoHistory(rawEvent));
+ }
for (GestureMatcher matcher : mGestures) {
if (matcher.getState() != GestureMatcher.STATE_GESTURE_CANCELED) {
if (DEBUG) {
@@ -240,9 +247,8 @@ class GestureManifold implements GestureMatcher.StateChangeListener {
Slog.d(LOG_TAG, matcher.toString());
}
if (matcher.getState() == GestureMatcher.STATE_GESTURE_COMPLETED) {
- // Here we just clear and return. The actual gesture dispatch is done in
+ // Here we just return. The actual gesture dispatch is done in
// onStateChanged().
- clear();
// No need to process this event any further.
return true;
}
@@ -255,6 +261,11 @@ class GestureManifold implements GestureMatcher.StateChangeListener {
for (GestureMatcher matcher : mGestures) {
matcher.clear();
}
+ if (mEvents != null) {
+ while (mEvents.size() > 0) {
+ mEvents.remove(0).recycle();
+ }
+ }
}
/**
@@ -340,29 +351,28 @@ class GestureManifold implements GestureMatcher.StateChangeListener {
case GESTURE_DOUBLE_TAP:
if (mServiceHandlesDoubleTap) {
AccessibilityGestureEvent gestureEvent =
- new AccessibilityGestureEvent(gestureId, event.getDisplayId());
+ new AccessibilityGestureEvent(gestureId, event.getDisplayId(), mEvents);
mListener.onGestureCompleted(gestureEvent);
} else {
mListener.onDoubleTap(event, rawEvent, policyFlags);
}
- clear();
break;
case GESTURE_DOUBLE_TAP_AND_HOLD:
if (mServiceHandlesDoubleTap) {
AccessibilityGestureEvent gestureEvent =
- new AccessibilityGestureEvent(gestureId, event.getDisplayId());
+ new AccessibilityGestureEvent(gestureId, event.getDisplayId(), mEvents);
mListener.onGestureCompleted(gestureEvent);
} else {
mListener.onDoubleTapAndHold(event, rawEvent, policyFlags);
}
- clear();
break;
default:
AccessibilityGestureEvent gestureEvent =
- new AccessibilityGestureEvent(gestureId, event.getDisplayId());
+ new AccessibilityGestureEvent(gestureId, event.getDisplayId(), mEvents);
mListener.onGestureCompleted(gestureEvent);
break;
}
+ clear();
}
public boolean isMultiFingerGesturesEnabled() {
@@ -406,4 +416,25 @@ class GestureManifold implements GestureMatcher.StateChangeListener {
public boolean isServiceHandlesDoubleTapEnabled() {
return mServiceHandlesDoubleTap;
}
+
+ public void setSendMotionEventsEnabled(boolean mode) {
+ mSendMotionEventsEnabled = mode;
+ if (!mode) {
+ while (mEvents.size() > 0) {
+ mEvents.remove(0).recycle();
+ }
+ }
+ }
+
+ public boolean isSendMotionEventsEnabled() {
+ return mSendMotionEventsEnabled;
+ }
+
+ /**
+ * Returns the current list of motion events. It is the caller's responsibility to copy the list
+ * if they want it to persist after a call to clear().
+ */
+ public List<MotionEvent> getMotionEvents() {
+ return mEvents;
+ }
}
diff --git a/services/accessibility/java/com/android/server/accessibility/gestures/TouchExplorer.java b/services/accessibility/java/com/android/server/accessibility/gestures/TouchExplorer.java
index d8c692b88a0f..5460e80a2802 100644
--- a/services/accessibility/java/com/android/server/accessibility/gestures/TouchExplorer.java
+++ b/services/accessibility/java/com/android/server/accessibility/gestures/TouchExplorer.java
@@ -37,6 +37,7 @@ import static android.view.accessibility.AccessibilityEvent.TYPE_VIEW_HOVER_EXIT
import static com.android.server.accessibility.gestures.TouchState.ALL_POINTER_ID_BITS;
import android.accessibilityservice.AccessibilityGestureEvent;
+import android.accessibilityservice.AccessibilityService;
import android.annotation.NonNull;
import android.content.Context;
import android.graphics.Region;
@@ -340,6 +341,14 @@ public class TouchExplorer extends BaseEventStreamTransformation
public void onDoubleTapAndHold(MotionEvent event, MotionEvent rawEvent, int policyFlags) {
if (mDispatcher.longPressWithTouchEvents(event, policyFlags)) {
sendHoverExitAndTouchExplorationGestureEndIfNeeded(policyFlags);
+ if (isSendMotionEventsEnabled()) {
+ AccessibilityGestureEvent gestureEvent =
+ new AccessibilityGestureEvent(
+ AccessibilityService.GESTURE_DOUBLE_TAP_AND_HOLD,
+ event.getDisplayId(),
+ mGestureDetector.getMotionEvents());
+ mAms.onGesture(gestureEvent);
+ }
mState.startDelegating();
}
}
@@ -350,7 +359,14 @@ public class TouchExplorer extends BaseEventStreamTransformation
// Remove pending event deliveries.
mSendHoverEnterAndMoveDelayed.cancel();
mSendHoverExitDelayed.cancel();
-
+ if (isSendMotionEventsEnabled()) {
+ AccessibilityGestureEvent gestureEvent =
+ new AccessibilityGestureEvent(
+ AccessibilityService.GESTURE_DOUBLE_TAP,
+ event.getDisplayId(),
+ mGestureDetector.getMotionEvents());
+ mAms.onGesture(gestureEvent);
+ }
if (mSendTouchExplorationEndDelayed.isPending()) {
mSendTouchExplorationEndDelayed.forceSendAndRemove();
}
@@ -385,6 +401,9 @@ public class TouchExplorer extends BaseEventStreamTransformation
@Override
public boolean onGestureCompleted(AccessibilityGestureEvent gestureEvent) {
+ if (DEBUG) {
+ Slog.d(LOG_TAG, "Dispatching gesture event:" + gestureEvent.toString());
+ }
endGestureDetection(true);
mSendTouchInteractionEndDelayed.cancel();
mAms.onGesture(gestureEvent);
@@ -411,12 +430,24 @@ public class TouchExplorer extends BaseEventStreamTransformation
mDispatcher.sendMotionEvent(
event,
ACTION_HOVER_MOVE,
- mState.getLastReceivedEvent(),
+ event,
pointerIdBits,
policyFlags);
return true;
}
}
+ if (isSendMotionEventsEnabled()) {
+ // Send a gesture with motion events to represent the cancelled gesture.
+ AccessibilityGestureEvent gestureEvent =
+ new AccessibilityGestureEvent(
+ AccessibilityService.GESTURE_UNKNOWN,
+ event.getDisplayId(),
+ mGestureDetector.getMotionEvents());
+ if (DEBUG) {
+ Slog.d(LOG_TAG, "Dispatching gesture event:" + gestureEvent.toString());
+ }
+ mAms.onGesture(gestureEvent);
+ }
return false;
}
@@ -620,6 +651,14 @@ public class TouchExplorer extends BaseEventStreamTransformation
if (isDraggingGesture(event)) {
// Two pointers moving in the same direction within
// a given distance perform a drag.
+ if (isSendMotionEventsEnabled()) {
+ AccessibilityGestureEvent gestureEvent =
+ new AccessibilityGestureEvent(
+ AccessibilityService.GESTURE_PASSTHROUGH,
+ event.getDisplayId(),
+ mGestureDetector.getMotionEvents());
+ mAms.onGesture(gestureEvent);
+ }
computeDraggingPointerIdIfNeeded(event);
pointerIdBits = 1 << mDraggingPointerId;
event.setEdgeFlags(mReceivedPointerTracker.getLastReceivedDownEdgeFlags());
@@ -636,6 +675,14 @@ public class TouchExplorer extends BaseEventStreamTransformation
mState.startDragging();
} else {
// Two pointers moving arbitrary are delegated to the view hierarchy.
+ if (isSendMotionEventsEnabled()) {
+ AccessibilityGestureEvent gestureEvent =
+ new AccessibilityGestureEvent(
+ AccessibilityService.GESTURE_PASSTHROUGH,
+ event.getDisplayId(),
+ mGestureDetector.getMotionEvents());
+ mAms.onGesture(gestureEvent);
+ }
mState.startDelegating();
mDispatcher.sendDownForAllNotInjectedPointers(event, policyFlags);
}
@@ -650,6 +697,14 @@ public class TouchExplorer extends BaseEventStreamTransformation
if (DEBUG) {
Slog.d(LOG_TAG, "Three-finger edge swipe detected.");
}
+ if (isSendMotionEventsEnabled()) {
+ AccessibilityGestureEvent gestureEvent =
+ new AccessibilityGestureEvent(
+ AccessibilityService.GESTURE_PASSTHROUGH,
+ event.getDisplayId(),
+ mGestureDetector.getMotionEvents());
+ mAms.onGesture(gestureEvent);
+ }
mState.startDelegating();
if (mState.isTouchExploring()) {
mDispatcher.sendDownForAllNotInjectedPointers(event,
@@ -663,6 +718,14 @@ public class TouchExplorer extends BaseEventStreamTransformation
}
} else {
// More than two pointers are delegated to the view hierarchy.
+ if (isSendMotionEventsEnabled()) {
+ AccessibilityGestureEvent gestureEvent =
+ new AccessibilityGestureEvent(
+ AccessibilityService.GESTURE_PASSTHROUGH,
+ event.getDisplayId(),
+ mGestureDetector.getMotionEvents());
+ mAms.onGesture(gestureEvent);
+ }
mState.startDelegating();
event = MotionEvent.obtainNoHistory(event);
mDispatcher.sendDownForAllNotInjectedPointers(event, policyFlags);
@@ -1109,6 +1172,7 @@ public class TouchExplorer extends BaseEventStreamTransformation
public void setTwoFingerPassthroughEnabled(boolean enabled) {
mGestureDetector.setTwoFingerPassthroughEnabled(enabled);
}
+
public void setGestureDetectionPassthroughRegion(Region region) {
mGestureDetectionPassthroughRegion = region;
}
@@ -1117,6 +1181,17 @@ public class TouchExplorer extends BaseEventStreamTransformation
mTouchExplorationPassthroughRegion = region;
}
+ /**
+ * Whether to send the motion events that make up each gesture to the accessibility service.
+ */
+ public void setSendMotionEventsEnabled(boolean mode) {
+ mGestureDetector.setSendMotionEventsEnabled(mode);
+ }
+
+ public boolean isSendMotionEventsEnabled() {
+ return mGestureDetector.isSendMotionEventsEnabled();
+ }
+
private boolean shouldPerformGestureDetection(MotionEvent event) {
if (mState.isDelegating()) {
return false;
@@ -1213,7 +1288,14 @@ public class TouchExplorer extends BaseEventStreamTransformation
public void run() {
// Send an accessibility event to announce the touch exploration start.
mDispatcher.sendAccessibilityEvent(TYPE_TOUCH_EXPLORATION_GESTURE_START);
-
+ if (isSendMotionEventsEnabled()) {
+ AccessibilityGestureEvent gestureEvent =
+ new AccessibilityGestureEvent(
+ AccessibilityService.GESTURE_TOUCH_EXPLORATION,
+ mState.getLastReceivedEvent().getDisplayId(),
+ mGestureDetector.getMotionEvents());
+ mAms.onGesture(gestureEvent);
+ }
if (!mEvents.isEmpty() && !mRawEvents.isEmpty()) {
// Deliver a down event.
mDispatcher.sendMotionEvent(mEvents.get(0), ACTION_HOVER_ENTER,
diff --git a/services/appwidget/java/com/android/server/appwidget/AppWidgetServiceImpl.java b/services/appwidget/java/com/android/server/appwidget/AppWidgetServiceImpl.java
index 35312a3a2fac..1c4d752c9775 100644
--- a/services/appwidget/java/com/android/server/appwidget/AppWidgetServiceImpl.java
+++ b/services/appwidget/java/com/android/server/appwidget/AppWidgetServiceImpl.java
@@ -664,8 +664,12 @@ class AppWidgetServiceImpl extends IAppWidgetService.Stub implements WidgetBacku
if (targetWidget != null && targetWidget != widget) continue;
PendingIntent intent = null;
if (onClickIntent != null) {
+ // Rare informational activity click is okay being
+ // immutable; the tradeoff is more security in exchange for
+ // losing bounds-based window animations
intent = PendingIntent.getActivity(mContext, widget.appWidgetId,
- onClickIntent, PendingIntent.FLAG_UPDATE_CURRENT);
+ onClickIntent,
+ PendingIntent.FLAG_UPDATE_CURRENT | PendingIntent.FLAG_IMMUTABLE);
}
RemoteViews views = createMaskedWidgetRemoteViews(iconBitmap, showBadge, intent);
if (widget.replaceWithMaskedViewsLocked(views)) {
@@ -2409,8 +2413,10 @@ class AppWidgetServiceImpl extends IAppWidgetService.Stub implements WidgetBacku
intent.setComponent(provider.info.provider);
final long token = Binder.clearCallingIdentity();
try {
+ // Broadcast alarms sent by system are immutable
provider.broadcast = PendingIntent.getBroadcastAsUser(mContext, 1, intent,
- PendingIntent.FLAG_UPDATE_CURRENT, provider.info.getProfile());
+ PendingIntent.FLAG_UPDATE_CURRENT | PendingIntent.FLAG_IMMUTABLE,
+ provider.info.getProfile());
} finally {
Binder.restoreCallingIdentity(token);
}
diff --git a/services/autofill/java/com/android/server/autofill/AutofillInlineSessionController.java b/services/autofill/java/com/android/server/autofill/AutofillInlineSessionController.java
index c25dd37bc7d9..dd5e58a94d15 100644
--- a/services/autofill/java/com/android/server/autofill/AutofillInlineSessionController.java
+++ b/services/autofill/java/com/android/server/autofill/AutofillInlineSessionController.java
@@ -35,8 +35,8 @@ import java.util.function.Consumer;
* Controls the interaction with the IME for the {@link AutofillInlineSuggestionsRequestSession}s.
*
* <p>The class maintains the inline suggestion session with the autofill service. There is at most
- * one active inline suggestion session at any given corresponding to one focused view.
- * New sessions are created only when {@link #onCreateInlineSuggestionsRequestLocked} is called.</p>
+ * one active inline suggestion session at any given corresponding to one focused view. New
+ * sessions are created only when {@link #onCreateInlineSuggestionsRequestLocked} is called.</p>
*
* <p>The class manages the interaction between the {@link com.android.server.autofill.Session} and
* the inline suggestion session whenever inline suggestions can be provided. All calls to the
@@ -83,7 +83,6 @@ final class AutofillInlineSessionController {
@GuardedBy("mLock")
void onCreateInlineSuggestionsRequestLocked(@NonNull AutofillId autofillId,
@NonNull Consumer<InlineSuggestionsRequest> requestConsumer, @NonNull Bundle uiExtras) {
- // TODO(b/151123764): rename the method to better reflect what it does.
if (mSession != null) {
// Destroy the existing session.
mSession.destroySessionLocked();
diff --git a/services/autofill/java/com/android/server/autofill/AutofillManagerServiceImpl.java b/services/autofill/java/com/android/server/autofill/AutofillManagerServiceImpl.java
index c563b6c11d86..864ead1485b5 100644
--- a/services/autofill/java/com/android/server/autofill/AutofillManagerServiceImpl.java
+++ b/services/autofill/java/com/android/server/autofill/AutofillManagerServiceImpl.java
@@ -1055,7 +1055,7 @@ final class AutofillManagerServiceImpl
pw.println(compatPkgs);
}
pw.print(prefix); pw.print("Inline Suggestions Enabled: ");
- pw.println(isInlineSuggestionsEnabled());
+ pw.println(isInlineSuggestionsEnabledLocked());
pw.print(prefix); pw.print("Last prune: "); pw.println(mLastPrune);
mDisabledInfoCache.dump(mUserId, prefix, pw);
@@ -1168,7 +1168,7 @@ final class AutofillManagerServiceImpl
}
@GuardedBy("mLock")
- boolean isInlineSuggestionsEnabled() {
+ boolean isInlineSuggestionsEnabledLocked() {
if (mInfo != null) {
return mInfo.isInlineSuggestionsEnabled();
}
diff --git a/services/autofill/java/com/android/server/autofill/Helper.java b/services/autofill/java/com/android/server/autofill/Helper.java
index 80b0375a229d..e35c0ee4e59b 100644
--- a/services/autofill/java/com/android/server/autofill/Helper.java
+++ b/services/autofill/java/com/android/server/autofill/Helper.java
@@ -24,6 +24,9 @@ import android.app.assist.AssistStructure.WindowNode;
import android.content.ComponentName;
import android.metrics.LogMaker;
import android.service.autofill.Dataset;
+import android.service.autofill.InternalSanitizer;
+import android.service.autofill.SaveInfo;
+import android.text.TextUtils;
import android.util.ArrayMap;
import android.util.ArraySet;
import android.util.Slog;
@@ -38,6 +41,7 @@ import com.android.internal.util.ArrayUtils;
import java.io.PrintWriter;
import java.util.ArrayDeque;
import java.util.ArrayList;
+import java.util.Arrays;
public final class Helper {
@@ -234,6 +238,46 @@ public final class Helper {
}
}
+ @Nullable
+ static ArrayMap<AutofillId, InternalSanitizer> createSanitizers(@Nullable SaveInfo saveInfo) {
+ if (saveInfo == null) return null;
+
+ final InternalSanitizer[] sanitizerKeys = saveInfo.getSanitizerKeys();
+ if (sanitizerKeys == null) return null;
+
+ final int size = sanitizerKeys.length;
+ final ArrayMap<AutofillId, InternalSanitizer> sanitizers = new ArrayMap<>(size);
+ if (sDebug) Slog.d(TAG, "Service provided " + size + " sanitizers");
+ final AutofillId[][] sanitizerValues = saveInfo.getSanitizerValues();
+ for (int i = 0; i < size; i++) {
+ final InternalSanitizer sanitizer = sanitizerKeys[i];
+ final AutofillId[] ids = sanitizerValues[i];
+ if (sDebug) {
+ Slog.d(TAG, "sanitizer #" + i + " (" + sanitizer + ") for ids "
+ + Arrays.toString(ids));
+ }
+ for (AutofillId id : ids) {
+ sanitizers.put(id, sanitizer);
+ }
+ }
+ return sanitizers;
+ }
+
+ /**
+ * Returns true if {@code s1} contains all characters of {@code s2}, in order.
+ */
+ static boolean containsCharsInOrder(String s1, String s2) {
+ int prevIndex = -1;
+ for (char ch : s2.toCharArray()) {
+ int index = TextUtils.indexOf(s1, ch, prevIndex + 1);
+ if (index == -1) {
+ return false;
+ }
+ prevIndex = index;
+ }
+ return true;
+ }
+
private interface ViewNodeFilter {
boolean matches(ViewNode node);
}
diff --git a/services/autofill/java/com/android/server/autofill/Session.java b/services/autofill/java/com/android/server/autofill/Session.java
index 6c9d35cb2fef..f596b072d713 100644
--- a/services/autofill/java/com/android/server/autofill/Session.java
+++ b/services/autofill/java/com/android/server/autofill/Session.java
@@ -30,6 +30,8 @@ import static android.view.autofill.AutofillManager.FLAG_SMART_SUGGESTION_SYSTEM
import static android.view.autofill.AutofillManager.getSmartSuggestionModeToString;
import static com.android.internal.util.function.pooled.PooledLambda.obtainMessage;
+import static com.android.server.autofill.Helper.containsCharsInOrder;
+import static com.android.server.autofill.Helper.createSanitizers;
import static com.android.server.autofill.Helper.getNumericValue;
import static com.android.server.autofill.Helper.sDebug;
import static com.android.server.autofill.Helper.sVerbose;
@@ -117,7 +119,6 @@ import java.util.Collections;
import java.util.List;
import java.util.Objects;
import java.util.Optional;
-import java.util.concurrent.CountDownLatch;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.function.Consumer;
import java.util.function.Function;
@@ -372,26 +373,24 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState
* CountDownLatch.
*/
private final class AssistDataReceiverImpl extends IAssistDataReceiver.Stub {
-
+ @GuardedBy("mLock")
+ private boolean mWaitForInlineRequest;
@GuardedBy("mLock")
private InlineSuggestionsRequest mPendingInlineSuggestionsRequest;
@GuardedBy("mLock")
private FillRequest mPendingFillRequest;
- @GuardedBy("mLock")
- private CountDownLatch mCountDownLatch = new CountDownLatch(0);
@Nullable Consumer<InlineSuggestionsRequest> newAutofillRequestLocked(ViewState viewState,
boolean isInlineRequest) {
- mCountDownLatch = new CountDownLatch(isInlineRequest ? 2 : 1);
mPendingFillRequest = null;
+ mWaitForInlineRequest = isInlineRequest;
mPendingInlineSuggestionsRequest = null;
return isInlineRequest ? (inlineSuggestionsRequest) -> {
synchronized (mLock) {
- if (mCountDownLatch.getCount() == 0) {
+ if (!mWaitForInlineRequest || mPendingInlineSuggestionsRequest != null) {
return;
}
mPendingInlineSuggestionsRequest = inlineSuggestionsRequest;
- mCountDownLatch.countDown();
maybeRequestFillLocked();
viewState.resetState(ViewState.STATE_PENDING_CREATE_INLINE_REQUEST);
}
@@ -399,16 +398,23 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState
}
void maybeRequestFillLocked() {
- if (mCountDownLatch.getCount() > 0 || mPendingFillRequest == null) {
+ if (mPendingFillRequest == null) {
return;
}
- if (mPendingInlineSuggestionsRequest != null) {
+
+ if (mWaitForInlineRequest) {
+ if (mPendingInlineSuggestionsRequest == null) {
+ return;
+ }
+
mPendingFillRequest = new FillRequest(mPendingFillRequest.getId(),
mPendingFillRequest.getFillContexts(), mPendingFillRequest.getClientState(),
mPendingFillRequest.getFlags(), mPendingInlineSuggestionsRequest);
}
+
mRemoteFillService.onFillRequest(mPendingFillRequest);
mPendingInlineSuggestionsRequest = null;
+ mWaitForInlineRequest = false;
mPendingFillRequest = null;
}
@@ -509,15 +515,8 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState
request = new FillRequest(requestId, contexts, mClientState, flags,
/*inlineSuggestionsRequest=*/null);
- if (mCountDownLatch.getCount() > 0) {
- mPendingFillRequest = request;
- mCountDownLatch.countDown();
- maybeRequestFillLocked();
- } else {
- // TODO(b/151867668): ideally this case should not happen, but it was
- // observed, we should figure out why and fix.
- mRemoteFillService.onFillRequest(request);
- }
+ mPendingFillRequest = request;
+ maybeRequestFillLocked();
}
if (mActivityToken != null) {
@@ -545,6 +544,10 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState
return ids;
}
+ /**
+ * Returns the String value of an {@link AutofillValue} by {@link AutofillId id} if it is of
+ * type {@code AUTOFILL_TYPE_TEXT} or {@code AUTOFILL_TYPE_LIST}.
+ */
@Override
@Nullable
public String findByAutofillId(@NonNull AutofillId id) {
@@ -706,7 +709,7 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState
* Autofill provider).
*/
private boolean isInlineSuggestionsEnabledByAutofillProviderLocked() {
- return mService.isInlineSuggestionsEnabled();
+ return mService.isInlineSuggestionsEnabledLocked();
}
private boolean isViewFocusedLocked(int flags) {
@@ -767,7 +770,7 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState
// triggers a new partition and we end up with many duplicate partitions. This is
// enhanced as the focus change can be much faster than the taking of the assist structure.
// Hence remove the currently queued request and replace it with the one queued after the
- // structure is taken. This causes only one fill request per bust of focus changes.
+ // structure is taken. This causes only one fill request per burst of focus changes.
cancelCurrentRequestLocked();
// Only ask IME to create inline suggestions request if Autofill provider supports it and
@@ -780,7 +783,7 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState
&& isViewFocusedLocked(flags)) {
Consumer<InlineSuggestionsRequest> inlineSuggestionsRequestConsumer =
mAssistReceiver.newAutofillRequestLocked(viewState,
- /*isInlineRequest=*/ true);
+ /* isInlineRequest= */ true);
if (inlineSuggestionsRequestConsumer != null) {
final AutofillId focusedId = mCurrentViewId;
remoteRenderService.getInlineSuggestionsRendererInfo(
@@ -794,8 +797,7 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState
viewState.setState(ViewState.STATE_PENDING_CREATE_INLINE_REQUEST);
}
} else {
- mAssistReceiver.newAutofillRequestLocked(viewState,
- /*isInlineRequest=*/ false);
+ mAssistReceiver.newAutofillRequestLocked(viewState, /* isInlineRequest= */ false);
}
// Now request the assist structure data.
@@ -1172,7 +1174,14 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState
return null;
}
- // FillServiceCallbacks
+ // VultureCallback
+ @Override
+ public void onServiceDied(@NonNull RemoteFillService service) {
+ Slog.w(TAG, "removing session because service died");
+ forceRemoveSelfLocked();
+ }
+
+ // AutoFillUiCallback
@Override
public void authenticate(int requestId, int datasetIndex, IntentSender intent, Bundle extras,
boolean authenticateInline) {
@@ -1202,13 +1211,6 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState
this, authenticationId, intent, fillInIntent, authenticateInline));
}
- // VultureCallback
- @Override
- public void onServiceDied(@NonNull RemoteFillService service) {
- Slog.w(TAG, "removing session because service died");
- forceRemoveSelfLocked();
- }
-
// AutoFillUiCallback
@Override
public void fill(int requestId, int datasetIndex, Dataset dataset) {
@@ -1282,6 +1284,7 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState
}
}
+ // AutoFillUiCallback
@Override
public void dispatchUnhandledKey(AutofillId id, KeyEvent keyEvent) {
synchronized (mLock) {
@@ -2281,31 +2284,6 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState
}
@Nullable
- private ArrayMap<AutofillId, InternalSanitizer> createSanitizers(@Nullable SaveInfo saveInfo) {
- if (saveInfo == null) return null;
-
- final InternalSanitizer[] sanitizerKeys = saveInfo.getSanitizerKeys();
- if (sanitizerKeys == null) return null;
-
- final int size = sanitizerKeys.length ;
- final ArrayMap<AutofillId, InternalSanitizer> sanitizers = new ArrayMap<>(size);
- if (sDebug) Slog.d(TAG, "Service provided " + size + " sanitizers");
- final AutofillId[][] sanitizerValues = saveInfo.getSanitizerValues();
- for (int i = 0; i < size; i++) {
- final InternalSanitizer sanitizer = sanitizerKeys[i];
- final AutofillId[] ids = sanitizerValues[i];
- if (sDebug) {
- Slog.d(TAG, "sanitizer #" + i + " (" + sanitizer + ") for ids "
- + Arrays.toString(ids));
- }
- for (AutofillId id : ids) {
- sanitizers.put(id, sanitizer);
- }
- }
- return sanitizers;
- }
-
- @Nullable
private AutofillValue getSanitizedValue(
@Nullable ArrayMap<AutofillId, InternalSanitizer> sanitizers,
@NonNull AutofillId id,
@@ -2369,12 +2347,12 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState
*/
@GuardedBy("mLock")
@Nullable
- private CharSequence[] getAutofillOptionsFromContextsLocked(AutofillId id) {
+ private CharSequence[] getAutofillOptionsFromContextsLocked(@NonNull AutofillId autofillId) {
final int numContexts = mContexts.size();
-
for (int i = numContexts - 1; i >= 0; i--) {
final FillContext context = mContexts.get(i);
- final ViewNode node = Helper.findViewNodeByAutofillId(context.getStructure(), id);
+ final ViewNode node = Helper.findViewNodeByAutofillId(context.getStructure(),
+ autofillId);
if (node != null && node.getAutofillOptions() != null) {
return node.getAutofillOptions();
}
@@ -2480,7 +2458,7 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState
// TODO(b/113281366): rather than merge it here, it might be better to simply reuse the old
// session instead of creating a new one. But we need to consider what would happen on corner
// cases such as "Main Activity M -> activity A with username -> activity B with password"
- // If user follows the normal workflow, than session A would be merged with session B as
+ // If user follows the normal workflow, then session A would be merged with session B as
// expected. But if when on Activity A the user taps back or somehow launches another activity,
// session A could be merged with the wrong session.
/**
@@ -2573,11 +2551,11 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState
}
requestNewFillResponseLocked(viewState, ViewState.STATE_STARTED_PARTITION, flags);
return true;
- } else {
- if (sVerbose) {
- Slog.v(TAG, "Not starting new partition for view " + id + ": "
- + viewState.getStateAsString());
- }
+ }
+
+ if (sVerbose) {
+ Slog.v(TAG, "Not starting new partition for view " + id + ": "
+ + viewState.getStateAsString());
}
return false;
}
@@ -2938,21 +2916,6 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState
}
}
- /**
- * Returns true if {@code s1} contains all characters of {@code s2}, in order.
- */
- private static boolean containsCharsInOrder(String s1, String s2) {
- int prevIndex = -1;
- for (char ch : s2.toCharArray()) {
- int index = TextUtils.indexOf(s1, ch, prevIndex + 1);
- if (index == -1) {
- return false;
- }
- prevIndex = index;
- }
- return true;
- }
-
@Override
public void onFillReady(@NonNull FillResponse response, @NonNull AutofillId filledId,
@Nullable AutofillValue value) {
@@ -3421,7 +3384,7 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState
mInlineSessionController.getInlineSuggestionsRequestLocked().orElse(null));
}
if (mAugmentedAutofillDestroyer == null) {
- mAugmentedAutofillDestroyer = () -> remoteService.onDestroyAutofillWindowsRequest();
+ mAugmentedAutofillDestroyer = remoteService::onDestroyAutofillWindowsRequest;
}
return mAugmentedAutofillDestroyer;
}
diff --git a/services/backup/java/com/android/server/backup/UserBackupManagerService.java b/services/backup/java/com/android/server/backup/UserBackupManagerService.java
index aa8532b67c43..2ff66b564ec9 100644
--- a/services/backup/java/com/android/server/backup/UserBackupManagerService.java
+++ b/services/backup/java/com/android/server/backup/UserBackupManagerService.java
@@ -650,7 +650,7 @@ public class UserBackupManagerService {
context,
/* requestCode */ 0,
initIntent,
- /* flags */ 0,
+ /* flags */ PendingIntent.FLAG_IMMUTABLE,
UserHandle.of(userId));
// Set up the backup-request journaling
diff --git a/services/core/java/android/content/pm/PackageManagerInternal.java b/services/core/java/android/content/pm/PackageManagerInternal.java
index 43c54b4a97b3..031ad4286225 100644
--- a/services/core/java/android/content/pm/PackageManagerInternal.java
+++ b/services/core/java/android/content/pm/PackageManagerInternal.java
@@ -60,6 +60,27 @@ import java.util.function.Consumer;
* @hide Only for use within the system server.
*/
public abstract class PackageManagerInternal {
+ @IntDef(prefix = "PACKAGE_", value = {
+ PACKAGE_SYSTEM,
+ PACKAGE_SETUP_WIZARD,
+ PACKAGE_INSTALLER,
+ PACKAGE_VERIFIER,
+ PACKAGE_BROWSER,
+ PACKAGE_SYSTEM_TEXT_CLASSIFIER,
+ PACKAGE_PERMISSION_CONTROLLER,
+ PACKAGE_WELLBEING,
+ PACKAGE_DOCUMENTER,
+ PACKAGE_CONFIGURATOR,
+ PACKAGE_INCIDENT_REPORT_APPROVER,
+ PACKAGE_APP_PREDICTOR,
+ PACKAGE_OVERLAY_CONFIG_SIGNATURE,
+ PACKAGE_WIFI,
+ PACKAGE_COMPANION,
+ PACKAGE_RETAIL_DEMO,
+ })
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface KnownPackage {}
+
public static final int PACKAGE_SYSTEM = 0;
public static final int PACKAGE_SETUP_WIZARD = 1;
public static final int PACKAGE_INSTALLER = 2;
@@ -72,11 +93,13 @@ public abstract class PackageManagerInternal {
public static final int PACKAGE_CONFIGURATOR = 9;
public static final int PACKAGE_INCIDENT_REPORT_APPROVER = 10;
public static final int PACKAGE_APP_PREDICTOR = 11;
+ public static final int PACKAGE_OVERLAY_CONFIG_SIGNATURE = 12;
public static final int PACKAGE_WIFI = 13;
public static final int PACKAGE_COMPANION = 14;
public static final int PACKAGE_RETAIL_DEMO = 15;
- public static final int PACKAGE_OVERLAY_CONFIG_SIGNATURE = 16;
- public static final int LAST_KNOWN_PACKAGE = PACKAGE_OVERLAY_CONFIG_SIGNATURE;
+ // Integer value of the last known package ID. Increases as new ID is added to KnownPackage.
+ // Please note the numbers should be continuous.
+ public static final int LAST_KNOWN_PACKAGE = PACKAGE_RETAIL_DEMO;
@IntDef(flag = true, prefix = "RESOLVE_", value = {
RESOLVE_NON_BROWSER_ONLY,
@@ -118,26 +141,6 @@ public abstract class PackageManagerInternal {
*/
public static final int INTEGRITY_VERIFICATION_REJECT = 0;
- @IntDef(value = {
- PACKAGE_SYSTEM,
- PACKAGE_SETUP_WIZARD,
- PACKAGE_INSTALLER,
- PACKAGE_VERIFIER,
- PACKAGE_BROWSER,
- PACKAGE_SYSTEM_TEXT_CLASSIFIER,
- PACKAGE_PERMISSION_CONTROLLER,
- PACKAGE_WELLBEING,
- PACKAGE_DOCUMENTER,
- PACKAGE_CONFIGURATOR,
- PACKAGE_INCIDENT_REPORT_APPROVER,
- PACKAGE_APP_PREDICTOR,
- PACKAGE_WIFI,
- PACKAGE_COMPANION,
- PACKAGE_RETAIL_DEMO,
- })
- @Retention(RetentionPolicy.SOURCE)
- public @interface KnownPackage {}
-
/** Observer called whenever the list of packages changes */
public interface PackageListObserver {
/** A package was added to the system. */
diff --git a/services/core/java/com/android/server/ConnectivityService.java b/services/core/java/com/android/server/ConnectivityService.java
index 35f119428dc7..0cd6e08101da 100644
--- a/services/core/java/com/android/server/ConnectivityService.java
+++ b/services/core/java/com/android/server/ConnectivityService.java
@@ -1169,7 +1169,7 @@ public class ConnectivityService extends IConnectivityManager.Stub
mMultipathPolicyTracker = new MultipathPolicyTracker(mContext, mHandler);
- mDnsManager = new DnsManager(mContext, mDnsResolver, mSystemProperties);
+ mDnsManager = new DnsManager(mContext, mDnsResolver);
registerPrivateDnsSettingsCallbacks();
}
@@ -2471,12 +2471,11 @@ public class ConnectivityService extends IConnectivityManager.Stub
loge("Can't set TCP buffer sizes:" + e);
}
- Integer rwndValue = Settings.Global.getInt(mContext.getContentResolver(),
- Settings.Global.TCP_DEFAULT_INIT_RWND,
+ final Integer rwndValue = Settings.Global.getInt(mContext.getContentResolver(),
+ Settings.Global.TCP_DEFAULT_INIT_RWND,
mSystemProperties.getInt("net.tcp.default_init_rwnd", 0));
- final String sysctlKey = "sys.sysctl.tcp_def_init_rwnd";
if (rwndValue != 0) {
- mSystemProperties.set(sysctlKey, rwndValue.toString());
+ mSystemProperties.setTcpInitRwnd(rwndValue);
}
}
diff --git a/services/core/java/com/android/server/NetworkTimeUpdateService.java b/services/core/java/com/android/server/NetworkTimeUpdateService.java
index c34dd984f865..ff2308c35b9f 100644
--- a/services/core/java/com/android/server/NetworkTimeUpdateService.java
+++ b/services/core/java/com/android/server/NetworkTimeUpdateService.java
@@ -103,7 +103,9 @@ public class NetworkTimeUpdateService extends Binder {
mCM = mContext.getSystemService(ConnectivityManager.class);
Intent pollIntent = new Intent(ACTION_POLL, null);
- mPendingPollIntent = PendingIntent.getBroadcast(mContext, POLL_REQUEST, pollIntent, 0);
+ // Broadcast alarms sent by system are immutable
+ mPendingPollIntent = PendingIntent.getBroadcast(mContext, POLL_REQUEST, pollIntent,
+ PendingIntent.FLAG_IMMUTABLE);
mPollingIntervalMs = mContext.getResources().getInteger(
com.android.internal.R.integer.config_ntpPollingInterval);
diff --git a/services/core/java/com/android/server/NsdService.java b/services/core/java/com/android/server/NsdService.java
index 4a1820a8e538..78bd4cdd4eab 100644
--- a/services/core/java/com/android/server/NsdService.java
+++ b/services/core/java/com/android/server/NsdService.java
@@ -824,7 +824,7 @@ public class NsdService extends INsdManager.Stub {
@Override
public String toString() {
- StringBuffer sb = new StringBuffer();
+ StringBuilder sb = new StringBuilder();
sb.append("mChannel ").append(mChannel).append("\n");
sb.append("mMessenger ").append(mMessenger).append("\n");
sb.append("mResolvedService ").append(mResolvedService).append("\n");
diff --git a/services/core/java/com/android/server/SystemServiceManager.java b/services/core/java/com/android/server/SystemServiceManager.java
index b87468419430..ff2661b19b48 100644
--- a/services/core/java/com/android/server/SystemServiceManager.java
+++ b/services/core/java/com/android/server/SystemServiceManager.java
@@ -26,12 +26,14 @@ import android.os.SystemClock;
import android.os.Trace;
import android.os.UserManagerInternal;
import android.util.ArrayMap;
+import android.util.EventLog;
import android.util.Slog;
import android.util.SparseArray;
import com.android.internal.annotations.GuardedBy;
import com.android.internal.util.Preconditions;
import com.android.server.SystemService.TargetUser;
+import com.android.server.am.EventLogTags;
import com.android.server.utils.TimingsTraceAndSlog;
import dalvik.system.PathClassLoader;
@@ -53,12 +55,14 @@ public final class SystemServiceManager {
private static final int SERVICE_CALL_WARN_TIME_MS = 50;
// Constants used on onUser(...)
- private static final String START = "Start";
- private static final String UNLOCKING = "Unlocking";
- private static final String UNLOCKED = "Unlocked";
- private static final String SWITCH = "Switch";
- private static final String STOP = "Stop";
- private static final String CLEANUP = "Cleanup";
+ // NOTE: do not change their values, as they're used on Trace calls and changes might break
+ // performance tests that rely on them.
+ private static final String USER_STARTING = "Start";
+ private static final String USER_UNLOCKING = "Unlocking";
+ private static final String USER_UNLOCKED = "Unlocked";
+ private static final String USER_SWITCHING = "Switch";
+ private static final String USER_STOPPING = "Stop";
+ private static final String USER_STOPPED = "Cleanup";
private static File sSystemDir;
private final Context mContext;
@@ -86,7 +90,7 @@ public final class SystemServiceManager {
/**
* Reference to the current user, it's used to set the {@link TargetUser} on
- * {@link #switchUser(int, int)} as the previous user might have been removed already.
+ * {@link #onUserSwitching(int, int)} as the previous user might have been removed already.
*/
@GuardedBy("mTargetUsers")
private @Nullable TargetUser mCurrentUser;
@@ -275,33 +279,38 @@ public final class SystemServiceManager {
/**
* Starts the given user.
*/
- public void startUser(@NonNull TimingsTraceAndSlog t, @UserIdInt int userId) {
+ public void onUserStarting(@NonNull TimingsTraceAndSlog t, @UserIdInt int userId) {
+ EventLog.writeEvent(EventLogTags.SSM_USER_STARTING, userId);
+
final TargetUser targetUser = newTargetUser(userId);
synchronized (mTargetUsers) {
mTargetUsers.put(userId, targetUser);
}
- onUser(t, START, /* prevUser= */ null, targetUser);
+ onUser(t, USER_STARTING, /* prevUser= */ null, targetUser);
}
/**
* Unlocks the given user.
*/
- public void unlockUser(@UserIdInt int userId) {
- onUser(UNLOCKING, userId);
+ public void onUserUnlocking(@UserIdInt int userId) {
+ EventLog.writeEvent(EventLogTags.SSM_USER_UNLOCKING, userId);
+ onUser(USER_UNLOCKING, userId);
}
/**
* Called after the user was unlocked.
*/
public void onUserUnlocked(@UserIdInt int userId) {
- onUser(UNLOCKED, userId);
+ EventLog.writeEvent(EventLogTags.SSM_USER_UNLOCKED, userId);
+ onUser(USER_UNLOCKED, userId);
}
/**
* Switches to the given user.
*/
- public void switchUser(@UserIdInt int from, @UserIdInt int to) {
+ public void onUserSwitching(@UserIdInt int from, @UserIdInt int to) {
+ EventLog.writeEvent(EventLogTags.SSM_USER_SWITCHING, from, to);
final TargetUser curUser, prevUser;
synchronized (mTargetUsers) {
if (mCurrentUser == null) {
@@ -321,21 +330,23 @@ public final class SystemServiceManager {
Slog.d(TAG, "Set mCurrentUser to " + mCurrentUser);
}
}
- onUser(TimingsTraceAndSlog.newAsyncLog(), SWITCH, prevUser, curUser);
+ onUser(TimingsTraceAndSlog.newAsyncLog(), USER_SWITCHING, prevUser, curUser);
}
/**
* Stops the given user.
*/
- public void stopUser(@UserIdInt int userId) {
- onUser(STOP, userId);
+ public void onUserStopping(@UserIdInt int userId) {
+ EventLog.writeEvent(EventLogTags.SSM_USER_STOPPING, userId);
+ onUser(USER_STOPPING, userId);
}
/**
* Cleans up the given user.
*/
- public void cleanupUser(@UserIdInt int userId) {
- onUser(CLEANUP, userId);
+ public void onUserStopped(@UserIdInt int userId) {
+ EventLog.writeEvent(EventLogTags.SSM_USER_STOPPED, userId);
+ onUser(USER_STOPPED, userId);
// Remove cached TargetUser
synchronized (mTargetUsers) {
@@ -351,6 +362,7 @@ public final class SystemServiceManager {
private void onUser(@NonNull TimingsTraceAndSlog t, @NonNull String onWhat,
@Nullable TargetUser prevUser, @NonNull TargetUser curUser) {
final int curUserId = curUser.getUserIdentifier();
+ // NOTE: do not change label below, or it might break performance tests that rely on it.
t.traceBegin("ssm." + onWhat + "User-" + curUserId);
Slog.i(TAG, "Calling on" + onWhat + "User " + curUserId
+ (prevUser != null ? " (from " + prevUser + ")" : ""));
@@ -381,22 +393,22 @@ public final class SystemServiceManager {
long time = SystemClock.elapsedRealtime();
try {
switch (onWhat) {
- case SWITCH:
+ case USER_SWITCHING:
service.onUserSwitching(prevUser, curUser);
break;
- case START:
+ case USER_STARTING:
service.onUserStarting(curUser);
break;
- case UNLOCKING:
+ case USER_UNLOCKING:
service.onUserUnlocking(curUser);
break;
- case UNLOCKED:
+ case USER_UNLOCKED:
service.onUserUnlocked(curUser);
break;
- case STOP:
+ case USER_STOPPING:
service.onUserStopping(curUser);
break;
- case CLEANUP:
+ case USER_STOPPED:
service.onUserStopped(curUser);
break;
default:
diff --git a/services/core/java/com/android/server/WiredAccessoryManager.java b/services/core/java/com/android/server/WiredAccessoryManager.java
index 8e5c73bfc022..7fa93c045ce0 100644
--- a/services/core/java/com/android/server/WiredAccessoryManager.java
+++ b/services/core/java/com/android/server/WiredAccessoryManager.java
@@ -319,7 +319,7 @@ final class WiredAccessoryManager implements WiredAccessoryCallbacks {
}
private String switchCodeToString(int switchValues, int switchMask) {
- StringBuffer sb = new StringBuffer();
+ StringBuilder sb = new StringBuilder();
if ((switchMask & SW_HEADPHONE_INSERT_BIT) != 0 &&
(switchValues & SW_HEADPHONE_INSERT_BIT) != 0) {
sb.append("SW_HEADPHONE_INSERT ");
diff --git a/services/core/java/com/android/server/am/ActiveServices.java b/services/core/java/com/android/server/am/ActiveServices.java
index 31712becec05..6e5c0412985c 100644
--- a/services/core/java/com/android/server/am/ActiveServices.java
+++ b/services/core/java/com/android/server/am/ActiveServices.java
@@ -1940,7 +1940,9 @@ public final class ActiveServices {
ActivityServiceConnectionsHolder<ConnectionRecord> activity = null;
if (token != null) {
activity = mAm.mAtmInternal.getServiceConnectionsHolder(token);
- if (activity == null) {
+ // TODO(b/171280916): Remove the check after we have another API get window context
+ // token than getActivityToken.
+ if (activity == null && !mAm.mWindowManager.isWindowToken(token)) {
Slog.w(TAG, "Binding with unknown activity: " + token);
return 0;
}
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index 79a660a48540..63f7d44da1de 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -7361,7 +7361,7 @@ public class ActivityManagerService extends IActivityManager.Stub
final boolean bootingSystemUser = currentUserId == UserHandle.USER_SYSTEM;
if (bootingSystemUser) {
- mSystemServiceManager.startUser(t, currentUserId);
+ mSystemServiceManager.onUserStarting(t, currentUserId);
}
synchronized (this) {
diff --git a/services/core/java/com/android/server/am/BatteryStatsService.java b/services/core/java/com/android/server/am/BatteryStatsService.java
index 3eb4ddebaf06..6f706acf1706 100644
--- a/services/core/java/com/android/server/am/BatteryStatsService.java
+++ b/services/core/java/com/android/server/am/BatteryStatsService.java
@@ -651,12 +651,13 @@ public final class BatteryStatsService extends IBatteryStats.Stub
public void noteWakupAlarm(final String name, final int uid, final WorkSource workSource,
final String tag) {
enforceCallingPermission();
+ final WorkSource localWs = workSource != null ? new WorkSource(workSource) : null;
synchronized (mLock) {
final long elapsedRealtime = SystemClock.elapsedRealtime();
final long uptime = SystemClock.uptimeMillis();
mHandler.post(() -> {
synchronized (mStats) {
- mStats.noteWakupAlarmLocked(name, uid, workSource, tag,
+ mStats.noteWakupAlarmLocked(name, uid, localWs, tag,
elapsedRealtime, uptime);
}
});
@@ -665,12 +666,13 @@ public final class BatteryStatsService extends IBatteryStats.Stub
public void noteAlarmStart(final String name, final WorkSource workSource, final int uid) {
enforceCallingPermission();
+ final WorkSource localWs = workSource != null ? new WorkSource(workSource) : null;
synchronized (mLock) {
final long elapsedRealtime = SystemClock.elapsedRealtime();
final long uptime = SystemClock.uptimeMillis();
mHandler.post(() -> {
synchronized (mStats) {
- mStats.noteAlarmStartLocked(name, workSource, uid, elapsedRealtime, uptime);
+ mStats.noteAlarmStartLocked(name, localWs, uid, elapsedRealtime, uptime);
}
});
}
@@ -678,12 +680,13 @@ public final class BatteryStatsService extends IBatteryStats.Stub
public void noteAlarmFinish(final String name, final WorkSource workSource, final int uid) {
enforceCallingPermission();
+ final WorkSource localWs = workSource != null ? new WorkSource(workSource) : null;
synchronized (mLock) {
final long elapsedRealtime = SystemClock.elapsedRealtime();
final long uptime = SystemClock.uptimeMillis();
mHandler.post(() -> {
synchronized (mStats) {
- mStats.noteAlarmFinishLocked(name, workSource, uid, elapsedRealtime, uptime);
+ mStats.noteAlarmFinishLocked(name, localWs, uid, elapsedRealtime, uptime);
}
});
}
@@ -722,12 +725,13 @@ public final class BatteryStatsService extends IBatteryStats.Stub
public void noteStartWakelockFromSource(final WorkSource ws, final int pid, final String name,
final String historyName, final int type, final boolean unimportantForLogging) {
enforceCallingPermission();
+ final WorkSource localWs = ws != null ? new WorkSource(ws) : null;
synchronized (mLock) {
final long elapsedRealtime = SystemClock.elapsedRealtime();
final long uptime = SystemClock.uptimeMillis();
mHandler.post(() -> {
synchronized (mStats) {
- mStats.noteStartWakeFromSourceLocked(ws, pid, name, historyName,
+ mStats.noteStartWakeFromSourceLocked(localWs, pid, name, historyName,
type, unimportantForLogging, elapsedRealtime, uptime);
}
});
@@ -739,13 +743,15 @@ public final class BatteryStatsService extends IBatteryStats.Stub
final String newName, final String newHistoryName, final int newType,
final boolean newUnimportantForLogging) {
enforceCallingPermission();
+ final WorkSource localWs = ws != null ? new WorkSource(ws) : null;
+ final WorkSource localNewWs = newWs != null ? new WorkSource(newWs) : null;
synchronized (mLock) {
final long elapsedRealtime = SystemClock.elapsedRealtime();
final long uptime = SystemClock.uptimeMillis();
mHandler.post(() -> {
synchronized (mStats) {
- mStats.noteChangeWakelockFromSourceLocked(ws, pid, name, historyName, type,
- newWs, newPid, newName, newHistoryName, newType,
+ mStats.noteChangeWakelockFromSourceLocked(localWs, pid, name, historyName, type,
+ localNewWs, newPid, newName, newHistoryName, newType,
newUnimportantForLogging, elapsedRealtime, uptime);
}
});
@@ -755,12 +761,13 @@ public final class BatteryStatsService extends IBatteryStats.Stub
public void noteStopWakelockFromSource(final WorkSource ws, final int pid, final String name,
final String historyName, final int type) {
enforceCallingPermission();
+ final WorkSource localWs = ws != null ? new WorkSource(ws) : null;
synchronized (mLock) {
final long elapsedRealtime = SystemClock.elapsedRealtime();
final long uptime = SystemClock.uptimeMillis();
mHandler.post(() -> {
synchronized (mStats) {
- mStats.noteStopWakeFromSourceLocked(ws, pid, name, historyName, type,
+ mStats.noteStopWakeFromSourceLocked(localWs, pid, name, historyName, type,
elapsedRealtime, uptime);
}
});
@@ -787,12 +794,13 @@ public final class BatteryStatsService extends IBatteryStats.Stub
public void noteLongPartialWakelockStartFromSource(final String name, final String historyName,
final WorkSource workSource) {
enforceCallingPermission();
+ final WorkSource localWs = workSource != null ? new WorkSource(workSource) : null;
synchronized (mLock) {
final long elapsedRealtime = SystemClock.elapsedRealtime();
final long uptime = SystemClock.uptimeMillis();
mHandler.post(() -> {
synchronized (mStats) {
- mStats.noteLongPartialWakelockStartFromSource(name, historyName, workSource,
+ mStats.noteLongPartialWakelockStartFromSource(name, historyName, localWs,
elapsedRealtime, uptime);
}
});
@@ -819,12 +827,13 @@ public final class BatteryStatsService extends IBatteryStats.Stub
public void noteLongPartialWakelockFinishFromSource(final String name, final String historyName,
final WorkSource workSource) {
enforceCallingPermission();
+ final WorkSource localWs = workSource != null ? new WorkSource(workSource) : null;
synchronized (mLock) {
final long elapsedRealtime = SystemClock.elapsedRealtime();
final long uptime = SystemClock.uptimeMillis();
mHandler.post(() -> {
synchronized (mStats) {
- mStats.noteLongPartialWakelockFinishFromSource(name, historyName, workSource,
+ mStats.noteLongPartialWakelockFinishFromSource(name, historyName, localWs,
elapsedRealtime, uptime);
}
});
@@ -890,12 +899,14 @@ public final class BatteryStatsService extends IBatteryStats.Stub
@Override
public void noteGpsChanged(final WorkSource oldWs, final WorkSource newWs) {
enforceCallingPermission();
+ final WorkSource localOldWs = oldWs != null ? new WorkSource(oldWs) : null;
+ final WorkSource localNewWs = newWs != null ? new WorkSource(newWs) : null;
synchronized (mLock) {
final long elapsedRealtime = SystemClock.elapsedRealtime();
final long uptime = SystemClock.uptimeMillis();
mHandler.post(() -> {
synchronized (mStats) {
- mStats.noteGpsChangedLocked(oldWs, newWs, elapsedRealtime, uptime);
+ mStats.noteGpsChangedLocked(localOldWs, localNewWs, elapsedRealtime, uptime);
}
});
}
@@ -1322,12 +1333,13 @@ public final class BatteryStatsService extends IBatteryStats.Stub
public void noteWifiRunning(final WorkSource ws) {
enforceCallingPermission();
+ final WorkSource localWs = ws != null ? new WorkSource(ws) : null;
synchronized (mLock) {
final long elapsedRealtime = SystemClock.elapsedRealtime();
final long uptime = SystemClock.uptimeMillis();
mHandler.post(() -> {
synchronized (mStats) {
- mStats.noteWifiRunningLocked(ws, elapsedRealtime, uptime);
+ mStats.noteWifiRunningLocked(localWs, elapsedRealtime, uptime);
}
// TODO: Log WIFI_RUNNING_STATE_CHANGED in a better spot to include Hotspot too.
FrameworkStatsLog.write(FrameworkStatsLog.WIFI_RUNNING_STATE_CHANGED,
@@ -1338,12 +1350,15 @@ public final class BatteryStatsService extends IBatteryStats.Stub
public void noteWifiRunningChanged(final WorkSource oldWs, final WorkSource newWs) {
enforceCallingPermission();
+ final WorkSource localOldWs = oldWs != null ? new WorkSource(oldWs) : null;
+ final WorkSource localNewWs = newWs != null ? new WorkSource(newWs) : null;
synchronized (mLock) {
final long elapsedRealtime = SystemClock.elapsedRealtime();
final long uptime = SystemClock.uptimeMillis();
mHandler.post(() -> {
synchronized (mStats) {
- mStats.noteWifiRunningChangedLocked(oldWs, newWs, elapsedRealtime, uptime);
+ mStats.noteWifiRunningChangedLocked(
+ localOldWs, localNewWs, elapsedRealtime, uptime);
}
FrameworkStatsLog.write(FrameworkStatsLog.WIFI_RUNNING_STATE_CHANGED,
newWs, FrameworkStatsLog.WIFI_RUNNING_STATE_CHANGED__STATE__ON);
@@ -1355,12 +1370,13 @@ public final class BatteryStatsService extends IBatteryStats.Stub
public void noteWifiStopped(final WorkSource ws) {
enforceCallingPermission();
+ final WorkSource localWs = ws != null ? new WorkSource(ws) : ws;
synchronized (mLock) {
final long elapsedRealtime = SystemClock.elapsedRealtime();
final long uptime = SystemClock.uptimeMillis();
mHandler.post(() -> {
synchronized (mStats) {
- mStats.noteWifiStoppedLocked(ws, elapsedRealtime, uptime);
+ mStats.noteWifiStoppedLocked(localWs, elapsedRealtime, uptime);
}
FrameworkStatsLog.write(FrameworkStatsLog.WIFI_RUNNING_STATE_CHANGED,
ws, FrameworkStatsLog.WIFI_RUNNING_STATE_CHANGED__STATE__OFF);
@@ -1487,12 +1503,14 @@ public final class BatteryStatsService extends IBatteryStats.Stub
public void noteFullWifiLockAcquiredFromSource(final WorkSource ws) {
enforceCallingPermission();
+ final WorkSource localWs = ws != null ? new WorkSource(ws) : null;
synchronized (mLock) {
final long elapsedRealtime = SystemClock.elapsedRealtime();
final long uptime = SystemClock.uptimeMillis();
mHandler.post(() -> {
synchronized (mStats) {
- mStats.noteFullWifiLockAcquiredFromSourceLocked(ws, elapsedRealtime, uptime);
+ mStats.noteFullWifiLockAcquiredFromSourceLocked(
+ localWs, elapsedRealtime, uptime);
}
});
}
@@ -1500,12 +1518,14 @@ public final class BatteryStatsService extends IBatteryStats.Stub
public void noteFullWifiLockReleasedFromSource(final WorkSource ws) {
enforceCallingPermission();
+ final WorkSource localWs = ws != null ? new WorkSource(ws) : null;
synchronized (mLock) {
final long elapsedRealtime = SystemClock.elapsedRealtime();
final long uptime = SystemClock.uptimeMillis();
mHandler.post(() -> {
synchronized (mStats) {
- mStats.noteFullWifiLockReleasedFromSourceLocked(ws, elapsedRealtime, uptime);
+ mStats.noteFullWifiLockReleasedFromSourceLocked(
+ localWs, elapsedRealtime, uptime);
}
});
}
@@ -1513,12 +1533,13 @@ public final class BatteryStatsService extends IBatteryStats.Stub
public void noteWifiScanStartedFromSource(final WorkSource ws) {
enforceCallingPermission();
+ final WorkSource localWs = ws != null ? new WorkSource(ws) : null;
synchronized (mLock) {
final long elapsedRealtime = SystemClock.elapsedRealtime();
final long uptime = SystemClock.uptimeMillis();
mHandler.post(() -> {
synchronized (mStats) {
- mStats.noteWifiScanStartedFromSourceLocked(ws, elapsedRealtime, uptime);
+ mStats.noteWifiScanStartedFromSourceLocked(localWs, elapsedRealtime, uptime);
}
});
}
@@ -1526,12 +1547,13 @@ public final class BatteryStatsService extends IBatteryStats.Stub
public void noteWifiScanStoppedFromSource(final WorkSource ws) {
enforceCallingPermission();
+ final WorkSource localWs = ws != null ? new WorkSource(ws) : null;
synchronized (mLock) {
final long elapsedRealtime = SystemClock.elapsedRealtime();
final long uptime = SystemClock.uptimeMillis();
mHandler.post(() -> {
synchronized (mStats) {
- mStats.noteWifiScanStoppedFromSourceLocked(ws, elapsedRealtime, uptime);
+ mStats.noteWifiScanStoppedFromSourceLocked(localWs, elapsedRealtime, uptime);
}
});
}
@@ -1539,12 +1561,13 @@ public final class BatteryStatsService extends IBatteryStats.Stub
public void noteWifiBatchedScanStartedFromSource(final WorkSource ws, final int csph) {
enforceCallingPermission();
+ final WorkSource localWs = ws != null ? new WorkSource(ws) : null;
synchronized (mLock) {
final long elapsedRealtime = SystemClock.elapsedRealtime();
final long uptime = SystemClock.uptimeMillis();
mHandler.post(() -> {
synchronized (mStats) {
- mStats.noteWifiBatchedScanStartedFromSourceLocked(ws, csph,
+ mStats.noteWifiBatchedScanStartedFromSourceLocked(localWs, csph,
elapsedRealtime, uptime);
}
});
@@ -1553,12 +1576,14 @@ public final class BatteryStatsService extends IBatteryStats.Stub
public void noteWifiBatchedScanStoppedFromSource(final WorkSource ws) {
enforceCallingPermission();
+ final WorkSource localWs = ws != null ? new WorkSource(ws) : null;
synchronized (mLock) {
final long elapsedRealtime = SystemClock.elapsedRealtime();
final long uptime = SystemClock.uptimeMillis();
mHandler.post(() -> {
synchronized (mStats) {
- mStats.noteWifiBatchedScanStoppedFromSourceLocked(ws, elapsedRealtime, uptime);
+ mStats.noteWifiBatchedScanStoppedFromSourceLocked(
+ localWs, elapsedRealtime, uptime);
}
});
}
@@ -1635,12 +1660,13 @@ public final class BatteryStatsService extends IBatteryStats.Stub
@Override
public void noteBleScanStarted(final WorkSource ws, final boolean isUnoptimized) {
enforceCallingPermission();
+ final WorkSource localWs = ws != null ? new WorkSource(ws) : null;
synchronized (mLock) {
final long elapsedRealtime = SystemClock.elapsedRealtime();
final long uptime = SystemClock.uptimeMillis();
mHandler.post(() -> {
synchronized (mStats) {
- mStats.noteBluetoothScanStartedFromSourceLocked(ws, isUnoptimized,
+ mStats.noteBluetoothScanStartedFromSourceLocked(localWs, isUnoptimized,
elapsedRealtime, uptime);
}
});
@@ -1650,12 +1676,13 @@ public final class BatteryStatsService extends IBatteryStats.Stub
@Override
public void noteBleScanStopped(final WorkSource ws, final boolean isUnoptimized) {
enforceCallingPermission();
+ final WorkSource localWs = ws != null ? new WorkSource(ws) : null;
synchronized (mLock) {
final long elapsedRealtime = SystemClock.elapsedRealtime();
final long uptime = SystemClock.uptimeMillis();
mHandler.post(() -> {
synchronized (mStats) {
- mStats.noteBluetoothScanStoppedFromSourceLocked(ws, isUnoptimized,
+ mStats.noteBluetoothScanStoppedFromSourceLocked(localWs, isUnoptimized,
uptime, elapsedRealtime);
}
});
@@ -1679,12 +1706,13 @@ public final class BatteryStatsService extends IBatteryStats.Stub
@Override
public void noteBleScanResults(final WorkSource ws, final int numNewResults) {
enforceCallingPermission();
+ final WorkSource localWs = ws != null ? new WorkSource(ws) : null;
synchronized (mLock) {
final long elapsedRealtime = SystemClock.elapsedRealtime();
final long uptime = SystemClock.uptimeMillis();
mHandler.post(() -> {
synchronized (mStats) {
- mStats.noteBluetoothScanResultsFromSourceLocked(ws, numNewResults,
+ mStats.noteBluetoothScanResultsFromSourceLocked(localWs, numNewResults,
elapsedRealtime, uptime);
}
});
diff --git a/services/core/java/com/android/server/am/CachedAppOptimizer.java b/services/core/java/com/android/server/am/CachedAppOptimizer.java
index 8112bb854b71..cd0d5b47c238 100644
--- a/services/core/java/com/android/server/am/CachedAppOptimizer.java
+++ b/services/core/java/com/android/server/am/CachedAppOptimizer.java
@@ -777,27 +777,27 @@ public final class CachedAppOptimizer {
long freezeTime = app.freezeUnfreezeTime;
try {
+ freezeBinder(app.pid, false);
+ } catch (RuntimeException e) {
+ Slog.e(TAG_AM, "Unable to unfreeze binder for " + app.pid + " " + app.processName
+ + ". Killing it");
+ app.kill("Unable to unfreeze",
+ ApplicationExitInfo.REASON_OTHER,
+ ApplicationExitInfo.SUBREASON_INVALID_STATE, true);
+ return;
+ }
+
+ try {
Process.setProcessFrozen(app.pid, app.uid, false);
app.freezeUnfreezeTime = SystemClock.uptimeMillis();
app.frozen = false;
} catch (Exception e) {
Slog.e(TAG_AM, "Unable to unfreeze " + app.pid + " " + app.processName
- + ". Any related user experience might be hanged.");
+ + ". This might cause inconsistency or UI hangs.");
}
if (!app.frozen) {
- try {
- freezeBinder(app.pid, false);
- } catch (RuntimeException e) {
- Slog.e(TAG_AM, "Unable to unfreeze binder for " + app.pid + " " + app.processName
- + ". Killing it");
- app.kill("Unable to unfreeze",
- ApplicationExitInfo.REASON_OTHER,
- ApplicationExitInfo.SUBREASON_INVALID_STATE, true);
- return;
- }
-
if (DEBUG_FREEZER) {
Slog.d(TAG_AM, "sync unfroze " + app.pid + " " + app.processName);
}
@@ -1110,14 +1110,6 @@ public final class CachedAppOptimizer {
return;
}
- try {
- freezeBinder(pid, true);
- } catch (RuntimeException e) {
- // TODO: it might be preferable to kill the target pid in this case
- Slog.e(TAG_AM, "Unable to freeze binder for " + pid + " " + name);
- return;
- }
-
if (pid == 0 || proc.frozen) {
// Already frozen or not a real process, either one being
// launched or one being killed
@@ -1146,6 +1138,15 @@ public final class CachedAppOptimizer {
EventLog.writeEvent(EventLogTags.AM_FREEZE, pid, name);
+ try {
+ freezeBinder(pid, true);
+ } catch (RuntimeException e) {
+ Slog.e(TAG_AM, "Unable to freeze binder for " + pid + " " + name);
+ proc.kill("Unable to freeze binder interface",
+ ApplicationExitInfo.REASON_OTHER,
+ ApplicationExitInfo.SUBREASON_INVALID_STATE, true);
+ }
+
// See above for why we're not taking mPhenotypeFlagLock here
if (mRandom.nextFloat() < mFreezerStatsdSampleRate) {
FrameworkStatsLog.write(FrameworkStatsLog.APP_FREEZE_CHANGED,
diff --git a/services/core/java/com/android/server/am/CoreSettingsObserver.java b/services/core/java/com/android/server/am/CoreSettingsObserver.java
index 529c6516398e..f32423f75324 100644
--- a/services/core/java/com/android/server/am/CoreSettingsObserver.java
+++ b/services/core/java/com/android/server/am/CoreSettingsObserver.java
@@ -85,19 +85,19 @@ final class CoreSettingsObserver extends ContentObserver {
sGlobalSettingToTypeMap.put(
Settings.Global.DEBUG_VIEW_ATTRIBUTES_APPLICATION_PACKAGE, String.class);
sGlobalSettingToTypeMap.put(
- Settings.Global.GLOBAL_SETTINGS_ANGLE_DEBUG_PACKAGE, String.class);
+ Settings.Global.ANGLE_DEBUG_PACKAGE, String.class);
sGlobalSettingToTypeMap.put(
- Settings.Global.GLOBAL_SETTINGS_ANGLE_GL_DRIVER_ALL_ANGLE, int.class);
+ Settings.Global.ANGLE_GL_DRIVER_ALL_ANGLE, int.class);
sGlobalSettingToTypeMap.put(
- Settings.Global.GLOBAL_SETTINGS_ANGLE_GL_DRIVER_SELECTION_PKGS, String.class);
+ Settings.Global.ANGLE_GL_DRIVER_SELECTION_PKGS, String.class);
sGlobalSettingToTypeMap.put(
- Settings.Global.GLOBAL_SETTINGS_ANGLE_GL_DRIVER_SELECTION_VALUES, String.class);
+ Settings.Global.ANGLE_GL_DRIVER_SELECTION_VALUES, String.class);
sGlobalSettingToTypeMap.put(
- Settings.Global.GLOBAL_SETTINGS_ANGLE_ALLOWLIST, String.class);
+ Settings.Global.ANGLE_ALLOWLIST, String.class);
sGlobalSettingToTypeMap.put(
Settings.Global.ANGLE_EGL_FEATURES, String.class);
sGlobalSettingToTypeMap.put(
- Settings.Global.GLOBAL_SETTINGS_SHOW_ANGLE_IN_USE_DIALOG_BOX, String.class);
+ Settings.Global.SHOW_ANGLE_IN_USE_DIALOG_BOX, String.class);
sGlobalSettingToTypeMap.put(Settings.Global.ENABLE_GPU_DEBUG_LAYERS, int.class);
sGlobalSettingToTypeMap.put(Settings.Global.GPU_DEBUG_APP, String.class);
sGlobalSettingToTypeMap.put(Settings.Global.GPU_DEBUG_LAYERS, String.class);
diff --git a/services/core/java/com/android/server/am/EventLogTags.logtags b/services/core/java/com/android/server/am/EventLogTags.logtags
index b818ccf275c4..68f2e35094fc 100644
--- a/services/core/java/com/android/server/am/EventLogTags.logtags
+++ b/services/core/java/com/android/server/am/EventLogTags.logtags
@@ -104,6 +104,14 @@ option java_package com.android.server.am
30076 uc_start_user_internal (userId|1|5)
30077 uc_unlock_user (userId|1|5)
30078 uc_finish_user_boot (userId|1|5)
-30079 uc_dispatch_user_switch (oldUserId|1|5) (newUserId|1|5)
-30080 uc_continue_user_switch (oldUserId|1|5) (newUserId|1|5)
-30081 uc_send_user_broadcast (userId|1|5),(IntentAction|3) \ No newline at end of file
+30079 uc_dispatch_user_switch (oldUserId|1|5),(newUserId|1|5)
+30080 uc_continue_user_switch (oldUserId|1|5),(newUserId|1|5)
+30081 uc_send_user_broadcast (userId|1|5),(IntentAction|3)
+# Tags below are used by SystemServiceManager - although it's technically part of am, these are
+# also user switch events and useful to be analyzed together with events above.
+30082 ssm_user_starting (userId|1|5)
+30083 ssm_user_switching (oldUserId|1|5),(newUserId|1|5)
+30084 ssm_user_unlocking (userId|1|5)
+30085 ssm_user_unlocked (userId|1|5)
+30086 ssm_user_stopping (userId|1|5)
+30087 ssm_user_stopped (userId|1|5)
diff --git a/services/core/java/com/android/server/am/PreBootBroadcaster.java b/services/core/java/com/android/server/am/PreBootBroadcaster.java
index 747e8a89f8e7..be63dd41735b 100644
--- a/services/core/java/com/android/server/am/PreBootBroadcaster.java
+++ b/services/core/java/com/android/server/am/PreBootBroadcaster.java
@@ -144,7 +144,8 @@ public abstract class PreBootBroadcaster extends IIntentReceiver.Stub {
final PendingIntent contentIntent;
if (context.getPackageManager().resolveActivity(intent, 0) != null) {
- contentIntent = PendingIntent.getActivity(context, 0, intent, 0);
+ contentIntent = PendingIntent.getActivity(context, 0, intent,
+ PendingIntent.FLAG_IMMUTABLE);
} else {
contentIntent = null;
}
diff --git a/services/core/java/com/android/server/am/UserController.java b/services/core/java/com/android/server/am/UserController.java
index f1bad9819394..c29df6c44d5c 100644
--- a/services/core/java/com/android/server/am/UserController.java
+++ b/services/core/java/com/android/server/am/UserController.java
@@ -952,7 +952,7 @@ class UserController implements Handler.Callback {
mInjector.batteryStatsServiceNoteEvent(
BatteryStats.HistoryItem.EVENT_USER_RUNNING_FINISH,
Integer.toString(userId), userId);
- mInjector.getSystemServiceManager().stopUser(userId);
+ mInjector.getSystemServiceManager().onUserStopping(userId);
Runnable finishUserStoppedAsync = () ->
mHandler.post(() -> finishUserStopped(uss, allowDelayedLocking));
@@ -1028,7 +1028,7 @@ class UserController implements Handler.Callback {
}
if (stopped) {
- mInjector.systemServiceManagerCleanupUser(userId);
+ mInjector.systemServiceManagerOnUserStopped(userId);
mInjector.stackSupervisorRemoveUser(userId);
// Remove the user if it is ephemeral.
@@ -1307,7 +1307,7 @@ class UserController implements Handler.Callback {
Slog.w(TAG, "No user info for user #" + userId);
return false;
}
- if (foreground && userInfo.isManagedProfile()) {
+ if (foreground && userInfo.isProfile()) {
Slog.w(TAG, "Cannot switch to User #" + userId + ": not a full user");
return false;
}
@@ -1612,7 +1612,7 @@ class UserController implements Handler.Callback {
Slog.w(TAG, "Cannot switch to User #" + targetUserId + ": not supported");
return false;
}
- if (targetUserInfo.isManagedProfile()) {
+ if (targetUserInfo.isProfile()) {
Slog.w(TAG, "Cannot switch to User #" + targetUserId + ": not a full user");
return false;
}
@@ -2494,8 +2494,8 @@ class UserController implements Handler.Callback {
logUserLifecycleEvent(msg.arg1, USER_LIFECYCLE_EVENT_START_USER,
USER_LIFECYCLE_EVENT_STATE_BEGIN);
- mInjector.getSystemServiceManager().startUser(TimingsTraceAndSlog.newAsyncLog(),
- msg.arg1);
+ mInjector.getSystemServiceManager().onUserStarting(
+ TimingsTraceAndSlog.newAsyncLog(), msg.arg1);
logUserLifecycleEvent(msg.arg1, USER_LIFECYCLE_EVENT_START_USER,
USER_LIFECYCLE_EVENT_STATE_FINISH);
@@ -2503,7 +2503,7 @@ class UserController implements Handler.Callback {
break;
case USER_UNLOCK_MSG:
final int userId = msg.arg1;
- mInjector.getSystemServiceManager().unlockUser(userId);
+ mInjector.getSystemServiceManager().onUserUnlocking(userId);
// Loads recents on a worker thread that allows disk I/O
FgThread.getHandler().post(() -> {
mInjector.loadUserRecents(userId);
@@ -2528,7 +2528,7 @@ class UserController implements Handler.Callback {
BatteryStats.HistoryItem.EVENT_USER_FOREGROUND_START,
Integer.toString(msg.arg1), msg.arg1);
- mInjector.getSystemServiceManager().switchUser(msg.arg2, msg.arg1);
+ mInjector.getSystemServiceManager().onUserSwitching(msg.arg2, msg.arg1);
break;
case FOREGROUND_PROFILE_CHANGED_MSG:
dispatchForegroundProfileChanged(msg.arg1);
@@ -2781,8 +2781,8 @@ class UserController implements Handler.Callback {
LocalServices.getService(ActivityTaskManagerInternal.class).onUserStopped(userId);
}
- void systemServiceManagerCleanupUser(@UserIdInt int userId) {
- mService.mSystemServiceManager.cleanupUser(userId);
+ void systemServiceManagerOnUserStopped(@UserIdInt int userId) {
+ mService.mSystemServiceManager.onUserStopped(userId);
}
protected UserManagerService getUserManager() {
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 1f71d7809133..5dcadee20e13 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
@@ -127,12 +127,12 @@ public class FingerprintService extends SystemService {
}
@Override
- public void notifyAcquired(int userId) {
+ public void notifyAcquired(int userId, int acquireInfo) {
Utils.checkPermission(getContext(), TEST_BIOMETRIC);
}
@Override
- public void notifyError(int userId) {
+ public void notifyError(int userId, int errorCode) {
Utils.checkPermission(getContext(), TEST_BIOMETRIC);
}
diff --git a/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/LockoutFrameworkImpl.java b/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/LockoutFrameworkImpl.java
index 4fc1545c4334..dc5dace98825 100644
--- a/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/LockoutFrameworkImpl.java
+++ b/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/LockoutFrameworkImpl.java
@@ -135,6 +135,6 @@ public class LockoutFrameworkImpl implements LockoutTracker {
private PendingIntent getLockoutResetIntentForUser(int userId) {
return PendingIntent.getBroadcast(mContext, userId,
new Intent(ACTION_LOCKOUT_RESET).putExtra(KEY_LOCKOUT_RESET_USER, userId),
- PendingIntent.FLAG_UPDATE_CURRENT);
+ PendingIntent.FLAG_UPDATE_CURRENT | PendingIntent.FLAG_IMMUTABLE);
}
}
diff --git a/services/core/java/com/android/server/compat/CompatChange.java b/services/core/java/com/android/server/compat/CompatChange.java
index 2e9818d15963..bc3bff1b966f 100644
--- a/services/core/java/com/android/server/compat/CompatChange.java
+++ b/services/core/java/com/android/server/compat/CompatChange.java
@@ -63,7 +63,7 @@ public final class CompatChange extends CompatibilityChangeInfo {
private Map<String, Boolean> mPackageOverrides;
public CompatChange(long changeId) {
- this(changeId, null, -1, false, false, null);
+ this(changeId, null, -1, -1, false, false, null);
}
/**
@@ -71,11 +71,14 @@ public final class CompatChange extends CompatibilityChangeInfo {
* @param name Short descriptive name.
* @param enableAfterTargetSdk {@code targetSdkVersion} restriction. See {@link EnabledAfter};
* -1 if the change is always enabled.
+ * @param enableSinceTargetSdk {@code targetSdkVersion} restriction. See {@link EnabledSince};
+ * -1 if the change is always enabled.
* @param disabled If {@code true}, overrides any {@code enableAfterTargetSdk} set.
*/
public CompatChange(long changeId, @Nullable String name, int enableAfterTargetSdk,
- boolean disabled, boolean loggingOnly, String description) {
- super(changeId, name, enableAfterTargetSdk, disabled, loggingOnly, description);
+ int enableSinceTargetSdk, boolean disabled, boolean loggingOnly, String description) {
+ super(changeId, name, enableAfterTargetSdk, enableSinceTargetSdk, disabled, loggingOnly,
+ description);
}
/**
@@ -83,7 +86,8 @@ public final class CompatChange extends CompatibilityChangeInfo {
*/
public CompatChange(Change change) {
super(change.getId(), change.getName(), change.getEnableAfterTargetSdk(),
- change.getDisabled(), change.getLoggingOnly(), change.getDescription());
+ change.getEnableSinceTargetSdk(), change.getDisabled(), change.getLoggingOnly(),
+ change.getDescription());
}
void registerListener(ChangeListener listener) {
@@ -145,8 +149,8 @@ public final class CompatChange extends CompatibilityChangeInfo {
if (getDisabled()) {
return false;
}
- if (getEnableAfterTargetSdk() != -1) {
- return app.targetSdkVersion > getEnableAfterTargetSdk();
+ if (getEnableSinceTargetSdk() != -1) {
+ return app.targetSdkVersion >= getEnableSinceTargetSdk();
}
return true;
}
@@ -167,8 +171,8 @@ public final class CompatChange extends CompatibilityChangeInfo {
if (getName() != null) {
sb.append("; name=").append(getName());
}
- if (getEnableAfterTargetSdk() != -1) {
- sb.append("; enableAfterTargetSdk=").append(getEnableAfterTargetSdk());
+ if (getEnableSinceTargetSdk() != -1) {
+ sb.append("; enableSinceTargetSdk=").append(getEnableSinceTargetSdk());
}
if (getDisabled()) {
sb.append("; disabled");
diff --git a/services/core/java/com/android/server/compat/CompatConfig.java b/services/core/java/com/android/server/compat/CompatConfig.java
index aeaa1fedf9e3..d80c58b39768 100644
--- a/services/core/java/com/android/server/compat/CompatConfig.java
+++ b/services/core/java/com/android/server/compat/CompatConfig.java
@@ -192,16 +192,19 @@ final class CompatConfig {
}
/**
- * Returns the minimum sdk version for which this change should be enabled (or 0 if it is not
+ * Returns the maximum sdk version for which this change can be opted in (or -1 if it is not
* target sdk gated).
*/
- int minTargetSdkForChangeId(long changeId) {
+ int maxTargetSdkForChangeIdOptIn(long changeId) {
synchronized (mChanges) {
CompatChange c = mChanges.get(changeId);
if (c == null) {
- return 0;
+ return -1;
}
- return c.getEnableAfterTargetSdk();
+ if (c.getEnableSinceTargetSdk() != -1) {
+ return c.getEnableSinceTargetSdk() - 1;
+ }
+ return -1;
}
}
@@ -318,7 +321,7 @@ final class CompatConfig {
}
}
- private long[] getAllowedChangesAfterTargetSdkForPackage(String packageName,
+ private long[] getAllowedChangesSinceTargetSdkForPackage(String packageName,
int targetSdkVersion)
throws RemoteException {
LongArray allowed = new LongArray();
@@ -326,7 +329,7 @@ final class CompatConfig {
for (int i = 0; i < mChanges.size(); ++i) {
try {
CompatChange change = mChanges.valueAt(i);
- if (change.getEnableAfterTargetSdk() != targetSdkVersion) {
+ if (change.getEnableSinceTargetSdk() != targetSdkVersion) {
continue;
}
OverrideAllowedState allowedState =
@@ -345,14 +348,14 @@ final class CompatConfig {
}
/**
- * Enables all changes with enabledAfterTargetSdk == {@param targetSdkVersion} for
+ * Enables all changes with enabledSinceTargetSdk == {@param targetSdkVersion} for
* {@param packageName}.
*
* @return The number of changes that were toggled.
*/
int enableTargetSdkChangesForPackage(String packageName, int targetSdkVersion)
throws RemoteException {
- long[] changes = getAllowedChangesAfterTargetSdkForPackage(packageName, targetSdkVersion);
+ long[] changes = getAllowedChangesSinceTargetSdkForPackage(packageName, targetSdkVersion);
for (long changeId : changes) {
addOverride(changeId, packageName, true);
}
@@ -361,14 +364,14 @@ final class CompatConfig {
/**
- * Disables all changes with enabledAfterTargetSdk == {@param targetSdkVersion} for
+ * Disables all changes with enabledSinceTargetSdk == {@param targetSdkVersion} for
* {@param packageName}.
*
* @return The number of changes that were toggled.
*/
int disableTargetSdkChangesForPackage(String packageName, int targetSdkVersion)
throws RemoteException {
- long[] changes = getAllowedChangesAfterTargetSdkForPackage(packageName, targetSdkVersion);
+ long[] changes = getAllowedChangesSinceTargetSdkForPackage(packageName, targetSdkVersion);
for (long changeId : changes) {
addOverride(changeId, packageName, false);
}
@@ -448,12 +451,7 @@ final class CompatConfig {
CompatibilityChangeInfo[] changeInfos = new CompatibilityChangeInfo[mChanges.size()];
for (int i = 0; i < mChanges.size(); ++i) {
CompatChange change = mChanges.valueAt(i);
- changeInfos[i] = new CompatibilityChangeInfo(change.getId(),
- change.getName(),
- change.getEnableAfterTargetSdk(),
- change.getDisabled(),
- change.getLoggingOnly(),
- change.getDescription());
+ changeInfos[i] = new CompatibilityChangeInfo(change);
}
return changeInfos;
}
diff --git a/services/core/java/com/android/server/compat/OverrideValidatorImpl.java b/services/core/java/com/android/server/compat/OverrideValidatorImpl.java
index 08d266478f4b..79a13ca242c1 100644
--- a/services/core/java/com/android/server/compat/OverrideValidatorImpl.java
+++ b/services/core/java/com/android/server/compat/OverrideValidatorImpl.java
@@ -58,7 +58,7 @@ public class OverrideValidatorImpl extends IOverrideValidator.Stub {
boolean debuggableBuild = mAndroidBuildClassifier.isDebuggableBuild();
boolean finalBuild = mAndroidBuildClassifier.isFinalBuild();
- int minTargetSdk = mCompatConfig.minTargetSdkForChangeId(changeId);
+ int maxTargetSdk = mCompatConfig.maxTargetSdkForChangeIdOptIn(changeId);
boolean disabled = mCompatConfig.isDisabled(changeId);
// Allow any override for userdebug or eng builds.
@@ -82,16 +82,16 @@ public class OverrideValidatorImpl extends IOverrideValidator.Stub {
}
// Allow overriding any change for debuggable apps on non-final builds.
if (!finalBuild) {
- return new OverrideAllowedState(ALLOWED, appTargetSdk, minTargetSdk);
+ return new OverrideAllowedState(ALLOWED, appTargetSdk, maxTargetSdk);
}
// Do not allow overriding default enabled changes on user builds
- if (minTargetSdk == -1 && !disabled) {
- return new OverrideAllowedState(DISABLED_NON_TARGET_SDK, appTargetSdk, minTargetSdk);
+ if (maxTargetSdk == -1 && !disabled) {
+ return new OverrideAllowedState(DISABLED_NON_TARGET_SDK, appTargetSdk, maxTargetSdk);
}
// Only allow to opt-in for a targetSdk gated change.
- if (disabled || appTargetSdk <= minTargetSdk) {
- return new OverrideAllowedState(ALLOWED, appTargetSdk, minTargetSdk);
+ if (disabled || appTargetSdk <= maxTargetSdk) {
+ return new OverrideAllowedState(ALLOWED, appTargetSdk, maxTargetSdk);
}
- return new OverrideAllowedState(DISABLED_TARGET_SDK_TOO_HIGH, appTargetSdk, minTargetSdk);
+ return new OverrideAllowedState(DISABLED_TARGET_SDK_TOO_HIGH, appTargetSdk, maxTargetSdk);
}
}
diff --git a/services/core/java/com/android/server/compat/PlatformCompat.java b/services/core/java/com/android/server/compat/PlatformCompat.java
index c7de8d3d585f..e4f52f1fc927 100644
--- a/services/core/java/com/android/server/compat/PlatformCompat.java
+++ b/services/core/java/com/android/server/compat/PlatformCompat.java
@@ -59,8 +59,8 @@ public class PlatformCompat extends IPlatformCompat.Stub {
private final ChangeReporter mChangeReporter;
private final CompatConfig mCompatConfig;
- private static int sMinTargetSdk = Build.VERSION_CODES.P;
- private static int sMaxTargetSdk = Build.VERSION_CODES.Q;
+ private static int sMinTargetSdk = Build.VERSION_CODES.Q;
+ private static int sMaxTargetSdk = Build.VERSION_CODES.R;
public PlatformCompat(Context context) {
mContext = context;
@@ -381,9 +381,9 @@ public class PlatformCompat extends IPlatformCompat.Stub {
if (change.getLoggingOnly()) {
return false;
}
- if (change.getEnableAfterTargetSdk() > 0) {
- if (change.getEnableAfterTargetSdk() < sMinTargetSdk
- || change.getEnableAfterTargetSdk() > sMaxTargetSdk) {
+ if (change.getEnableSinceTargetSdk() > 0) {
+ if (change.getEnableSinceTargetSdk() < sMinTargetSdk
+ || change.getEnableSinceTargetSdk() > sMaxTargetSdk) {
return false;
}
}
diff --git a/services/core/java/com/android/server/connectivity/DataConnectionStats.java b/services/core/java/com/android/server/connectivity/DataConnectionStats.java
index 0304cdc47515..15f43a0481bd 100644
--- a/services/core/java/com/android/server/connectivity/DataConnectionStats.java
+++ b/services/core/java/com/android/server/connectivity/DataConnectionStats.java
@@ -19,12 +19,12 @@ package com.android.server.connectivity;
import static android.telephony.AccessNetworkConstants.TRANSPORT_TYPE_WWAN;
import static android.telephony.NetworkRegistrationInfo.DOMAIN_PS;
+import android.annotation.NonNull;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.os.Handler;
-import android.os.Looper;
import android.os.RemoteException;
import android.telephony.NetworkRegistrationInfo;
import android.telephony.PhoneStateListener;
@@ -36,6 +36,9 @@ import android.util.Log;
import com.android.internal.app.IBatteryStats;
import com.android.server.am.BatteryStatsService;
+import java.util.concurrent.Executor;
+import java.util.concurrent.RejectedExecutionException;
+
public class DataConnectionStats extends BroadcastReceiver {
private static final String TAG = "DataConnectionStats";
private static final boolean DEBUG = false;
@@ -55,7 +58,8 @@ public class DataConnectionStats extends BroadcastReceiver {
mContext = context;
mBatteryStats = BatteryStatsService.getService();
mListenerHandler = listenerHandler;
- mPhoneStateListener = new PhoneStateListenerImpl(listenerHandler.getLooper());
+ mPhoneStateListener =
+ new PhoneStateListenerImpl(new PhoneStateListenerExecutor(listenerHandler));
}
public void startMonitoring() {
@@ -140,9 +144,24 @@ public class DataConnectionStats extends BroadcastReceiver {
&& mServiceState.getState() != ServiceState.STATE_POWER_OFF;
}
+ private static class PhoneStateListenerExecutor implements Executor {
+ @NonNull
+ private final Handler mHandler;
+
+ PhoneStateListenerExecutor(@NonNull Handler handler) {
+ mHandler = handler;
+ }
+ @Override
+ public void execute(Runnable command) {
+ if (!mHandler.post(command)) {
+ throw new RejectedExecutionException(mHandler + " is shutting down");
+ }
+ }
+ }
+
private class PhoneStateListenerImpl extends PhoneStateListener {
- PhoneStateListenerImpl(Looper looper) {
- super(looper);
+ PhoneStateListenerImpl(Executor executor) {
+ super(executor);
}
@Override
diff --git a/services/core/java/com/android/server/connectivity/DnsManager.java b/services/core/java/com/android/server/connectivity/DnsManager.java
index 271ec4eac9e8..c7891865644a 100644
--- a/services/core/java/com/android/server/connectivity/DnsManager.java
+++ b/services/core/java/com/android/server/connectivity/DnsManager.java
@@ -237,7 +237,6 @@ public class DnsManager {
private final Context mContext;
private final ContentResolver mContentResolver;
private final IDnsResolver mDnsResolver;
- private final MockableSystemProperties mSystemProperties;
private final ConcurrentHashMap<Integer, PrivateDnsConfig> mPrivateDnsMap;
// TODO: Replace the Map with SparseArrays.
private final Map<Integer, PrivateDnsValidationStatuses> mPrivateDnsValidationMap;
@@ -249,11 +248,10 @@ public class DnsManager {
private int mMinSamples;
private int mMaxSamples;
- public DnsManager(Context ctx, IDnsResolver dnsResolver, MockableSystemProperties sp) {
+ public DnsManager(Context ctx, IDnsResolver dnsResolver) {
mContext = ctx;
mContentResolver = mContext.getContentResolver();
mDnsResolver = dnsResolver;
- mSystemProperties = sp;
mPrivateDnsMap = new ConcurrentHashMap<>();
mPrivateDnsValidationMap = new HashMap<>();
mLinkPropertiesMap = new HashMap<>();
diff --git a/services/core/java/com/android/server/connectivity/MockableSystemProperties.java b/services/core/java/com/android/server/connectivity/MockableSystemProperties.java
index 77b86d8e4355..ef767341d609 100644
--- a/services/core/java/com/android/server/connectivity/MockableSystemProperties.java
+++ b/services/core/java/com/android/server/connectivity/MockableSystemProperties.java
@@ -17,6 +17,7 @@
package com.android.server.connectivity;
import android.os.SystemProperties;
+import android.sysprop.NetworkProperties;
public class MockableSystemProperties {
@@ -31,8 +32,10 @@ public class MockableSystemProperties {
public boolean getBoolean(String key, boolean def) {
return SystemProperties.getBoolean(key, def);
}
-
- public void set(String key, String value) {
- SystemProperties.set(key, value);
+ /**
+ * Set net.tcp_def_init_rwnd to the tcp initial receive window size.
+ */
+ public void setTcpInitRwnd(int value) {
+ NetworkProperties.tcp_init_rwnd(value);
}
}
diff --git a/services/core/java/com/android/server/connectivity/Vpn.java b/services/core/java/com/android/server/connectivity/Vpn.java
index 1ed6b35341b8..e2187932b3e6 100644
--- a/services/core/java/com/android/server/connectivity/Vpn.java
+++ b/services/core/java/com/android/server/connectivity/Vpn.java
@@ -38,6 +38,7 @@ import android.app.NotificationManager;
import android.app.PendingIntent;
import android.content.BroadcastReceiver;
import android.content.ComponentName;
+import android.content.ContentResolver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
@@ -1976,28 +1977,33 @@ public class Vpn {
* @see Settings.Secure#putStringForUser
*/
public void settingsSecurePutStringForUser(String key, String value, int userId) {
- Settings.Secure.putStringForUser(mContext.getContentResolver(), key, value, userId);
+ Settings.Secure.putString(getContentResolverAsUser(userId), key, value);
}
/**
* @see Settings.Secure#putIntForUser
*/
public void settingsSecurePutIntForUser(String key, int value, int userId) {
- Settings.Secure.putIntForUser(mContext.getContentResolver(), key, value, userId);
+ Settings.Secure.putInt(getContentResolverAsUser(userId), key, value);
}
/**
* @see Settings.Secure#getStringForUser
*/
public String settingsSecureGetStringForUser(String key, int userId) {
- return Settings.Secure.getStringForUser(mContext.getContentResolver(), key, userId);
+ return Settings.Secure.getString(getContentResolverAsUser(userId), key);
}
/**
* @see Settings.Secure#getIntForUser
*/
public int settingsSecureGetIntForUser(String key, int def, int userId) {
- return Settings.Secure.getIntForUser(mContext.getContentResolver(), key, def, userId);
+ return Settings.Secure.getInt(getContentResolverAsUser(userId), key, def);
+ }
+
+ private ContentResolver getContentResolverAsUser(int userId) {
+ return mContext.createContextAsUser(
+ UserHandle.of(userId), 0 /* flags */).getContentResolver();
}
public boolean isCallerSystem() {
diff --git a/services/core/java/com/android/server/display/AutomaticBrightnessController.java b/services/core/java/com/android/server/display/AutomaticBrightnessController.java
index 93cada7adca3..eb61a1c2ad40 100644
--- a/services/core/java/com/android/server/display/AutomaticBrightnessController.java
+++ b/services/core/java/com/android/server/display/AutomaticBrightnessController.java
@@ -1051,7 +1051,7 @@ class AutomaticBrightnessController {
@Override
public String toString() {
- StringBuffer buf = new StringBuffer();
+ StringBuilder buf = new StringBuilder();
buf.append('[');
for (int i = 0; i < mCount; i++) {
final long next = i + 1 < mCount ? getTime(i + 1) : SystemClock.uptimeMillis();
diff --git a/services/core/java/com/android/server/display/DisplayManagerService.java b/services/core/java/com/android/server/display/DisplayManagerService.java
index a600292eca31..60c83905ed9c 100644
--- a/services/core/java/com/android/server/display/DisplayManagerService.java
+++ b/services/core/java/com/android/server/display/DisplayManagerService.java
@@ -91,6 +91,7 @@ import android.util.SparseArray;
import android.util.Spline;
import android.view.Display;
import android.view.DisplayInfo;
+import android.view.IDisplayFoldListener;
import android.view.Surface;
import android.view.SurfaceControl;
@@ -103,6 +104,7 @@ import com.android.server.DisplayThread;
import com.android.server.LocalServices;
import com.android.server.SystemService;
import com.android.server.UiThread;
+import com.android.server.policy.WindowManagerPolicy;
import com.android.server.wm.SurfaceAnimationThread;
import com.android.server.wm.WindowManagerInternal;
@@ -312,6 +314,9 @@ public final class DisplayManagerService extends SystemService {
// Receives notifications about changes to Settings.
private SettingsObserver mSettingsObserver;
+ // Received notifications of the display-fold action
+ private DisplayFoldListener mDisplayFoldListener;
+
public DisplayManagerService(Context context) {
this(context, new Injector());
}
@@ -429,6 +434,11 @@ public final class DisplayManagerService extends SystemService {
synchronized (mSyncRoot) {
mWindowManagerInternal = LocalServices.getService(WindowManagerInternal.class);
mInputManagerInternal = LocalServices.getService(InputManagerInternal.class);
+ WindowManagerPolicy policy = LocalServices.getService(WindowManagerPolicy.class);
+
+ mDisplayFoldListener = new DisplayFoldListener();
+ policy.registerDisplayFoldListener(mDisplayFoldListener);
+
scheduleTraversalLocked(false);
}
}
@@ -2563,13 +2573,6 @@ public final class DisplayManagerService extends SystemService {
public void ignoreProximitySensorUntilChanged() {
mDisplayPowerController.ignoreProximitySensorUntilChanged();
}
-
- @Override
- public void setDeviceFolded(boolean isFolded) {
- synchronized (mSyncRoot) {
- mLogicalDisplayMapper.setDeviceFoldedLocked(isFolded);
- }
- }
}
class DesiredDisplayModeSpecsObserver
@@ -2606,4 +2609,17 @@ public final class DisplayManagerService extends SystemService {
}
}
}
+
+ class DisplayFoldListener extends IDisplayFoldListener.Stub {
+ @Override
+ public void onDisplayFoldChanged(int displayId, boolean folded) {
+ // TODO: multi-display - IDisplayFoldListener callback only really works for the
+ // Display.DEFAULT_DISPLAY.
+ if (displayId == Display.DEFAULT_DISPLAY) {
+ synchronized (mSyncRoot) {
+ mLogicalDisplayMapper.setDeviceFoldedLocked(folded);
+ }
+ }
+ }
+ };
}
diff --git a/services/core/java/com/android/server/display/DisplayModeDirector.java b/services/core/java/com/android/server/display/DisplayModeDirector.java
index 4f5a0faee8dd..71b377cc2f11 100644
--- a/services/core/java/com/android/server/display/DisplayModeDirector.java
+++ b/services/core/java/com/android/server/display/DisplayModeDirector.java
@@ -123,7 +123,6 @@ public class DisplayModeDirector {
public void start(SensorManager sensorManager) {
mSettingsObserver.observe();
mDisplayObserver.observe();
- mSettingsObserver.observe();
mBrightnessObserver.observe(sensorManager);
synchronized (mLock) {
// We may have a listener already registered before the call to start, so go ahead and
diff --git a/services/core/java/com/android/server/display/LocalDisplayAdapter.java b/services/core/java/com/android/server/display/LocalDisplayAdapter.java
index 834046062191..6597aa54d66b 100644
--- a/services/core/java/com/android/server/display/LocalDisplayAdapter.java
+++ b/services/core/java/com/android/server/display/LocalDisplayAdapter.java
@@ -189,13 +189,11 @@ final class LocalDisplayAdapter extends DisplayAdapter {
private int mDefaultModeId;
private int mDefaultConfigGroup;
private int mActiveModeId;
- private boolean mActiveModeInvalid;
private DisplayModeDirector.DesiredDisplayModeSpecs mDisplayModeSpecs =
new DisplayModeDirector.DesiredDisplayModeSpecs();
private boolean mDisplayModeSpecsInvalid;
private int mActiveConfigId;
private int mActiveColorMode;
- private boolean mActiveColorModeInvalid;
private Display.HdrCapabilities mHdrCapabilities;
private boolean mAllmSupported;
private boolean mGameContentTypeSupported;
@@ -306,7 +304,6 @@ final class LocalDisplayAdapter extends DisplayAdapter {
// Schedule traversals to ensure that the correct state is reapplied if necessary.
if (mActiveModeId != NO_DISPLAY_MODE_ID
&& mActiveModeId != activeRecord.mMode.getModeId()) {
- mActiveModeInvalid = true;
sendTraversalRequestLocked();
}
@@ -379,7 +376,6 @@ final class LocalDisplayAdapter extends DisplayAdapter {
+ " mode.");
}
mActiveModeId = mDefaultModeId;
- mActiveModeInvalid = true;
}
// Schedule traversals so that we apply pending changes.
@@ -470,14 +466,12 @@ final class LocalDisplayAdapter extends DisplayAdapter {
Slog.w(TAG, "Active color mode no longer available, reverting"
+ " to default mode.");
mActiveColorMode = Display.COLOR_MODE_DEFAULT;
- mActiveColorModeInvalid = true;
} else {
if (!mSupportedColorModes.isEmpty()) {
// This should never happen.
Slog.e(TAG, "Default and active color mode is no longer available!"
+ " Reverting to first available mode.");
mActiveColorMode = mSupportedColorModes.get(0);
- mActiveColorModeInvalid = true;
} else {
// This should really never happen.
Slog.e(TAG, "No color modes available!");
@@ -854,8 +848,7 @@ final class LocalDisplayAdapter extends DisplayAdapter {
}
mActiveConfigId = activeConfigId;
mActiveModeId = findMatchingModeIdLocked(activeConfigId);
- mActiveModeInvalid = mActiveModeId == NO_DISPLAY_MODE_ID;
- if (mActiveModeInvalid) {
+ if (mActiveModeId == NO_DISPLAY_MODE_ID) {
Slog.w(TAG, "In unknown mode after setting allowed configs"
+ ", activeConfigId=" + mActiveConfigId);
}
@@ -873,7 +866,6 @@ final class LocalDisplayAdapter extends DisplayAdapter {
}
mActiveColorMode = colorMode;
- mActiveColorModeInvalid = false;
getHandler().sendMessage(PooledLambda.obtainMessage(
LocalDisplayDevice::requestColorModeAsync, this,
getDisplayTokenLocked(), colorMode));
diff --git a/services/core/java/com/android/server/display/LogicalDisplayMapper.java b/services/core/java/com/android/server/display/LogicalDisplayMapper.java
index 942a12ebf64e..fc3ba35c52ba 100644
--- a/services/core/java/com/android/server/display/LogicalDisplayMapper.java
+++ b/services/core/java/com/android/server/display/LogicalDisplayMapper.java
@@ -167,7 +167,31 @@ class LogicalDisplayMapper implements DisplayDeviceRepository.Listener {
}
}
- public void setDeviceFoldedLocked(boolean isFolded) {
+ public void dumpLocked(PrintWriter pw) {
+ pw.println("LogicalDisplayMapper:");
+ IndentingPrintWriter ipw = new IndentingPrintWriter(pw, " ");
+ ipw.increaseIndent();
+
+ ipw.println("mSingleDisplayDemoMode=" + mSingleDisplayDemoMode);
+ ipw.println("mNextNonDefaultDisplayId=" + mNextNonDefaultDisplayId);
+
+ final int logicalDisplayCount = mLogicalDisplays.size();
+ ipw.println();
+ ipw.println("Logical Displays: size=" + logicalDisplayCount);
+
+
+ for (int i = 0; i < logicalDisplayCount; i++) {
+ int displayId = mLogicalDisplays.keyAt(i);
+ LogicalDisplay display = mLogicalDisplays.valueAt(i);
+ ipw.println("Display " + displayId + ":");
+ ipw.increaseIndent();
+ display.dumpLocked(ipw);
+ ipw.decreaseIndent();
+ ipw.println();
+ }
+ }
+
+ void setDeviceFoldedLocked(boolean isFolded) {
mIsFolded = isFolded;
if (mIsFoldedOverride != null) {
isFolded = mIsFoldedOverride.booleanValue();
@@ -237,30 +261,6 @@ class LogicalDisplayMapper implements DisplayDeviceRepository.Listener {
}
}
- public void dumpLocked(PrintWriter pw) {
- pw.println("LogicalDisplayMapper:");
- IndentingPrintWriter ipw = new IndentingPrintWriter(pw, " ");
- ipw.increaseIndent();
-
- ipw.println("mSingleDisplayDemoMode=" + mSingleDisplayDemoMode);
- ipw.println("mNextNonDefaultDisplayId=" + mNextNonDefaultDisplayId);
-
- final int logicalDisplayCount = mLogicalDisplays.size();
- ipw.println();
- ipw.println("Logical Displays: size=" + logicalDisplayCount);
-
-
- for (int i = 0; i < logicalDisplayCount; i++) {
- int displayId = mLogicalDisplays.keyAt(i);
- LogicalDisplay display = mLogicalDisplays.valueAt(i);
- ipw.println("Display " + displayId + ":");
- ipw.increaseIndent();
- display.dumpLocked(ipw);
- ipw.decreaseIndent();
- ipw.println();
- }
- }
-
void setFoldOverrideLocked(Boolean isFolded) {
if (!Objects.equals(isFolded, mIsFoldedOverride)) {
mIsFoldedOverride = isFolded;
diff --git a/services/core/java/com/android/server/display/utils/History.java b/services/core/java/com/android/server/display/utils/History.java
index ed171b8f7408..988d573f276d 100644
--- a/services/core/java/com/android/server/display/utils/History.java
+++ b/services/core/java/com/android/server/display/utils/History.java
@@ -83,7 +83,7 @@ public class History {
* @return The buffer as string.
*/
public String toString() {
- StringBuffer sb = new StringBuffer();
+ StringBuilder sb = new StringBuilder();
sb.append("[");
for (int i = 0; i < mCount; i++) {
final int index = (mStart + i) % mSize;
diff --git a/services/core/java/com/android/server/display/utils/RollingBuffer.java b/services/core/java/com/android/server/display/utils/RollingBuffer.java
index dd5b7ab2403d..883f6eb4fb7d 100644
--- a/services/core/java/com/android/server/display/utils/RollingBuffer.java
+++ b/services/core/java/com/android/server/display/utils/RollingBuffer.java
@@ -136,7 +136,7 @@ public class RollingBuffer {
* @return The buffer as string.
*/
public String toString() {
- StringBuffer sb = new StringBuffer();
+ StringBuilder sb = new StringBuilder();
sb.append("[");
for (int i = 0; i < mCount; i++) {
final int index = offsetOf(i);
diff --git a/services/core/java/com/android/server/hdmi/HdmiCecLocalDevice.java b/services/core/java/com/android/server/hdmi/HdmiCecLocalDevice.java
index b88a37e7b8b4..946fb0d00d60 100755
--- a/services/core/java/com/android/server/hdmi/HdmiCecLocalDevice.java
+++ b/services/core/java/com/android/server/hdmi/HdmiCecLocalDevice.java
@@ -127,7 +127,7 @@ abstract class HdmiCecLocalDevice {
@Override
public String toString() {
- StringBuffer s = new StringBuffer();
+ StringBuilder s = new StringBuilder();
String logicalAddressString =
(logicalAddress == Constants.ADDR_INVALID)
? "invalid"
diff --git a/services/core/java/com/android/server/hdmi/HdmiCecMessage.java b/services/core/java/com/android/server/hdmi/HdmiCecMessage.java
index ff7da11340eb..7a6ce8de8c24 100644
--- a/services/core/java/com/android/server/hdmi/HdmiCecMessage.java
+++ b/services/core/java/com/android/server/hdmi/HdmiCecMessage.java
@@ -111,7 +111,7 @@ public final class HdmiCecMessage {
@Override
public String toString() {
- StringBuffer s = new StringBuffer();
+ StringBuilder s = new StringBuilder();
s.append(String.format("<%s> %X%X:%02X",
opcodeToString(mOpcode), mSource, mDestination, mOpcode));
if (mParams.length > 0) {
diff --git a/services/core/java/com/android/server/input/InputShellCommand.java b/services/core/java/com/android/server/input/InputShellCommand.java
index fd5f48c91867..51e6cf413074 100644
--- a/services/core/java/com/android/server/input/InputShellCommand.java
+++ b/services/core/java/com/android/server/input/InputShellCommand.java
@@ -215,7 +215,7 @@ public class InputShellCommand extends ShellCommand {
* @param text is a string of characters you want to input to the device.
*/
private void sendText(int source, final String text, int displayId) {
- final StringBuffer buff = new StringBuffer(text);
+ final StringBuilder buff = new StringBuilder(text);
boolean escapeFlag = false;
for (int i = 0; i < buff.length(); i++) {
if (escapeFlag) {
diff --git a/services/core/java/com/android/server/media/MediaSessionStack.java b/services/core/java/com/android/server/media/MediaSessionStack.java
index f15e22f92cad..f8ff5b5f8e66 100644
--- a/services/core/java/com/android/server/media/MediaSessionStack.java
+++ b/services/core/java/com/android/server/media/MediaSessionStack.java
@@ -416,7 +416,7 @@ class MediaSessionStack {
// Code copied from android.os.Debug#getCallers(int)
private static String getCallers(final int depth) {
final StackTraceElement[] callStack = Thread.currentThread().getStackTrace();
- StringBuffer sb = new StringBuffer();
+ StringBuilder sb = new StringBuilder();
for (int i = 0; i < depth; i++) {
sb.append(getCaller(callStack, i)).append(" ");
}
diff --git a/services/core/java/com/android/server/om/IdmapManager.java b/services/core/java/com/android/server/om/IdmapManager.java
index cb6e960b721d..eeb26552e63d 100644
--- a/services/core/java/com/android/server/om/IdmapManager.java
+++ b/services/core/java/com/android/server/om/IdmapManager.java
@@ -57,7 +57,7 @@ final class IdmapManager {
private final PackageManagerHelper mPackageManager;
/**
- * Package name of the reference package defined in 'config-signature' tag of
+ * Package name of the reference package defined in 'overlay-config-signature' tag of
* SystemConfig or empty String if tag not defined. This package is vetted on scan by
* PackageManagerService that it's a system package and is used to check if overlay matches
* its signature in order to fulfill the config_signature policy.
@@ -159,7 +159,7 @@ final class IdmapManager {
fulfilledPolicies |= OverlayablePolicy.ACTOR_SIGNATURE;
}
- // If SystemConfig defines 'config-signature' package, given that
+ // If SystemConfig defines 'overlay-config-signature' package, given that
// this package is vetted by OverlayManagerService that it's a
// preinstalled package, check if overlay matches its signature.
if (!TextUtils.isEmpty(mConfigSignaturePackage)
diff --git a/services/core/java/com/android/server/pm/IncrementalStates.java b/services/core/java/com/android/server/pm/IncrementalStates.java
index dda5fafb8cb1..43f4a3477a98 100644
--- a/services/core/java/com/android/server/pm/IncrementalStates.java
+++ b/services/core/java/com/android/server/pm/IncrementalStates.java
@@ -16,18 +16,21 @@
package com.android.server.pm;
-import android.content.pm.IDataLoaderStatusListener;
+import static android.os.incremental.IStorageHealthListener.HEALTH_STATUS_OK;
+import static android.os.incremental.IStorageHealthListener.HEALTH_STATUS_UNHEALTHY;
+import static android.os.incremental.IStorageHealthListener.HEALTH_STATUS_UNHEALTHY_STORAGE;
+import static android.os.incremental.IStorageHealthListener.HEALTH_STATUS_UNHEALTHY_TRANSPORT;
+
import android.content.pm.IncrementalStatesInfo;
import android.content.pm.PackageManager;
import android.os.Handler;
-import android.os.incremental.IStorageHealthListener;
import android.util.Slog;
import com.android.internal.annotations.GuardedBy;
import com.android.internal.os.BackgroundThread;
import com.android.internal.util.function.pooled.PooledLambda;
-import java.util.function.BiConsumer;
+import java.util.function.Consumer;
/**
* Manages state transitions of a package installed on Incremental File System. Currently manages:
@@ -36,8 +39,7 @@ import java.util.function.BiConsumer;
*
* The following events might change the states of a package:
* 1. Installation commit
- * 2. Incremental storage health
- * 3. Data loader stream health
+ * 2. Incremental storage health changes
* 4. Loading progress changes
*
* @hide
@@ -48,16 +50,14 @@ public final class IncrementalStates {
private final Handler mHandler = BackgroundThread.getHandler();
private final Object mLock = new Object();
@GuardedBy("mLock")
- private int mStreamStatus = IDataLoaderStatusListener.STREAM_HEALTHY;
- @GuardedBy("mLock")
- private int mStorageHealthStatus = IStorageHealthListener.HEALTH_STATUS_OK;
+ private int mStorageHealthStatus = HEALTH_STATUS_OK;
@GuardedBy("mLock")
private final LoadingState mLoadingState;
@GuardedBy("mLock")
private StartableState mStartableState;
@GuardedBy("mLock")
private Callback mCallback = null;
- private final BiConsumer<Integer, Integer> mStatusConsumer;
+ private final Consumer<Integer> mStatusConsumer;
public IncrementalStates() {
// By default the package is not startable and not fully loaded (i.e., is loading)
@@ -148,12 +148,9 @@ public final class IncrementalStates {
}
}
- private class StatusConsumer implements BiConsumer<Integer, Integer> {
+ private class StatusConsumer implements Consumer<Integer> {
@Override
- public void accept(Integer streamStatus, Integer storageStatus) {
- if (streamStatus == null && storageStatus == null) {
- return;
- }
+ public void accept(Integer storageStatus) {
final boolean oldState, newState;
synchronized (mLock) {
if (!mLoadingState.isLoading()) {
@@ -161,12 +158,7 @@ public final class IncrementalStates {
return;
}
oldState = mStartableState.isStartable();
- if (streamStatus != null) {
- mStreamStatus = (Integer) streamStatus;
- }
- if (storageStatus != null) {
- mStorageHealthStatus = (Integer) storageStatus;
- }
+ mStorageHealthStatus = storageStatus;
updateStartableStateLocked();
newState = mStartableState.isStartable();
}
@@ -188,21 +180,7 @@ public final class IncrementalStates {
Slog.i(TAG, "received storage health status changed event : storageHealthStatus="
+ storageHealthStatus);
}
- mStatusConsumer.accept(null, storageHealthStatus);
- }
-
- /**
- * By calling this method, the caller indicates that the stream status of the package has
- * been
- * changed. This could indicate a streaming error. The state will change according to the
- * status
- * code defined in {@code IDataLoaderStatusListener}.
- */
- public void onStreamStatusChanged(int streamState) {
- if (DEBUG) {
- Slog.i(TAG, "received stream status changed event : streamState=" + streamState);
- }
- mStatusConsumer.accept(streamState, null);
+ mStatusConsumer.accept(storageHealthStatus);
}
/**
@@ -284,35 +262,16 @@ public final class IncrementalStates {
final boolean currentState = mStartableState.isStartable();
boolean nextState = currentState;
if (!currentState) {
- if (mStorageHealthStatus == IStorageHealthListener.HEALTH_STATUS_OK
- && mStreamStatus == IDataLoaderStatusListener.STREAM_HEALTHY) {
- // change from unstartable -> startable when both stream and storage are healthy
+ if (mStorageHealthStatus == HEALTH_STATUS_OK) {
+ // change from unstartable -> startable
nextState = true;
}
} else {
- if (mStorageHealthStatus == IStorageHealthListener.HEALTH_STATUS_UNHEALTHY) {
- // unrecoverable if storage is unhealthy
+ if (mStorageHealthStatus == HEALTH_STATUS_UNHEALTHY
+ || mStorageHealthStatus == HEALTH_STATUS_UNHEALTHY_STORAGE
+ || mStorageHealthStatus == HEALTH_STATUS_UNHEALTHY_TRANSPORT) {
+ // change from startable -> unstartable
nextState = false;
- } else {
- switch (mStreamStatus) {
- case IDataLoaderStatusListener.STREAM_INTEGRITY_ERROR:
- // unrecoverable, fall through
- case IDataLoaderStatusListener.STREAM_SOURCE_ERROR: {
- // unrecoverable
- nextState = false;
- break;
- }
- case IDataLoaderStatusListener.STREAM_STORAGE_ERROR: {
- if (mStorageHealthStatus != IStorageHealthListener.HEALTH_STATUS_OK) {
- // unrecoverable if there is a pending read AND storage is limited
- nextState = false;
- }
- break;
- }
- default:
- // anything else, remain startable
- break;
- }
}
}
if (nextState == currentState) {
@@ -370,17 +329,11 @@ public final class IncrementalStates {
return PackageManager.UNSTARTABLE_REASON_UNKNOWN;
}
// Translate stream status to reason for unstartable state
- switch (mStreamStatus) {
- case IDataLoaderStatusListener.STREAM_TRANSPORT_ERROR:
- // fall through
- case IDataLoaderStatusListener.STREAM_INTEGRITY_ERROR:
- // fall through
- case IDataLoaderStatusListener.STREAM_SOURCE_ERROR: {
- return PackageManager.UNSTARTABLE_REASON_DATALOADER_TRANSPORT;
- }
- case IDataLoaderStatusListener.STREAM_STORAGE_ERROR: {
- return PackageManager.UNSTARTABLE_REASON_DATALOADER_STORAGE;
- }
+ switch (mStorageHealthStatus) {
+ case HEALTH_STATUS_UNHEALTHY_STORAGE:
+ return PackageManager.UNSTARTABLE_REASON_INSUFFICIENT_STORAGE;
+ case HEALTH_STATUS_UNHEALTHY_TRANSPORT:
+ return PackageManager.UNSTARTABLE_REASON_CONNECTION_ERROR;
default:
return PackageManager.UNSTARTABLE_REASON_UNKNOWN;
}
@@ -464,7 +417,6 @@ public final class IncrementalStates {
}
IncrementalStates l = (IncrementalStates) o;
return l.mStorageHealthStatus == mStorageHealthStatus
- && l.mStreamStatus == mStreamStatus
&& l.mStartableState.equals(mStartableState)
&& l.mLoadingState.equals(mLoadingState);
}
@@ -474,7 +426,6 @@ public final class IncrementalStates {
int hashCode = mStartableState.hashCode();
hashCode = 31 * hashCode + mLoadingState.hashCode();
hashCode = 31 * hashCode + mStorageHealthStatus;
- hashCode = 31 * hashCode + mStreamStatus;
return hashCode;
}
}
diff --git a/services/core/java/com/android/server/pm/PackageInstallerSession.java b/services/core/java/com/android/server/pm/PackageInstallerSession.java
index 649cafb1cb06..5d2928e1a854 100644
--- a/services/core/java/com/android/server/pm/PackageInstallerSession.java
+++ b/services/core/java/com/android/server/pm/PackageInstallerSession.java
@@ -143,7 +143,6 @@ import com.android.internal.util.ArrayUtils;
import com.android.internal.util.FrameworkStatsLog;
import com.android.internal.util.IndentingPrintWriter;
import com.android.internal.util.Preconditions;
-import com.android.internal.util.function.pooled.PooledLambda;
import com.android.server.LocalServices;
import com.android.server.pm.Installer.InstallerException;
import com.android.server.pm.dex.DexManager;
@@ -1702,28 +1701,6 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub {
dispatchSessionFinished(error, detailedMessage, null);
}
- private void onStorageHealthStatusChanged(int status) {
- final String packageName = getPackageName();
- if (TextUtils.isEmpty(packageName)) {
- // The package has not been installed.
- return;
- }
- mHandler.post(PooledLambda.obtainRunnable(
- PackageManagerService::onStorageHealthStatusChanged,
- mPm, packageName, status, userId).recycleOnUse());
- }
-
- private void onStreamHealthStatusChanged(int status) {
- final String packageName = getPackageName();
- if (TextUtils.isEmpty(packageName)) {
- // The package has not been installed.
- return;
- }
- mHandler.post(PooledLambda.obtainRunnable(
- PackageManagerService::onStreamStatusChanged,
- mPm, packageName, status, userId).recycleOnUse());
- }
-
/**
* If session should be sealed, then it's sealed to prevent further modification.
* If the session can't be sealed then it's destroyed.
@@ -3315,19 +3292,11 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub {
return;
}
- final boolean isDestroyedOrDataLoaderFinished;
synchronized (mLock) {
- isDestroyedOrDataLoaderFinished = mDestroyed || mDataLoaderFinished;
- }
- if (isDestroyedOrDataLoaderFinished) {
- switch (status) {
- case IDataLoaderStatusListener.DATA_LOADER_UNRECOVERABLE:
- // treat as unhealthy storage
- onStorageHealthStatusChanged(
- IStorageHealthListener.HEALTH_STATUS_UNHEALTHY);
- return;
+ if (mDestroyed || mDataLoaderFinished) {
+ // No need to worry about post installation
+ return;
}
- return;
}
try {
@@ -3423,13 +3392,10 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub {
}
@Override
public void reportStreamHealth(int dataLoaderId, int streamStatus) {
- synchronized (mLock) {
- if (!mDestroyed && !mDataLoaderFinished) {
- // ignore streaming status if package isn't installed
- return;
- }
- }
- onStreamHealthStatusChanged(streamStatus);
+ // Currently the stream status is not used during package installation. It is
+ // technically possible for the data loader to report stream status via this
+ // callback, but if something is wrong with the streaming, it is more likely that
+ // prepareDataLoaderLocked will return false and the installation will be aborted.
}
};
@@ -3438,20 +3404,16 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub {
healthCheckParams.blockedTimeoutMs = INCREMENTAL_STORAGE_BLOCKED_TIMEOUT_MS;
healthCheckParams.unhealthyTimeoutMs = INCREMENTAL_STORAGE_UNHEALTHY_TIMEOUT_MS;
healthCheckParams.unhealthyMonitoringMs = INCREMENTAL_STORAGE_UNHEALTHY_MONITORING_MS;
-
final boolean systemDataLoader =
params.getComponentName().getPackageName() == SYSTEM_DATA_LOADER_PACKAGE;
final IStorageHealthListener healthListener = new IStorageHealthListener.Stub() {
@Override
public void onHealthStatus(int storageId, int status) {
- final boolean isDestroyedOrDataLoaderFinished;
synchronized (mLock) {
- isDestroyedOrDataLoaderFinished = mDestroyed || mDataLoaderFinished;
- }
- if (isDestroyedOrDataLoaderFinished) {
- // App's installed.
- onStorageHealthStatusChanged(status);
- return;
+ if (mDestroyed || mDataLoaderFinished) {
+ // No need to worry about post installation
+ return;
+ }
}
switch (status) {
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index d529f0e604f9..c39152be518a 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -1,6 +1,5 @@
/*
* Copyright (C) 2006 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
@@ -47,8 +46,10 @@ import static android.content.pm.PackageManager.FLAG_PERMISSION_USER_FIXED;
import static android.content.pm.PackageManager.FLAG_PERMISSION_USER_SET;
import static android.content.pm.PackageManager.FLAG_PERMISSION_WHITELIST_INSTALLER;
import static android.content.pm.PackageManager.INSTALL_FAILED_ALREADY_EXISTS;
+import static android.content.pm.PackageManager.INSTALL_FAILED_BAD_PERMISSION_GROUP;
import static android.content.pm.PackageManager.INSTALL_FAILED_DUPLICATE_PACKAGE;
import static android.content.pm.PackageManager.INSTALL_FAILED_DUPLICATE_PERMISSION;
+import static android.content.pm.PackageManager.INSTALL_FAILED_DUPLICATE_PERMISSION_GROUP;
import static android.content.pm.PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
import static android.content.pm.PackageManager.INSTALL_FAILED_INTERNAL_ERROR;
import static android.content.pm.PackageManager.INSTALL_FAILED_INVALID_APK;
@@ -233,6 +234,7 @@ import android.content.pm.parsing.component.ParsedInstrumentation;
import android.content.pm.parsing.component.ParsedIntentInfo;
import android.content.pm.parsing.component.ParsedMainComponent;
import android.content.pm.parsing.component.ParsedPermission;
+import android.content.pm.parsing.component.ParsedPermissionGroup;
import android.content.pm.parsing.component.ParsedProcess;
import android.content.pm.parsing.component.ParsedProvider;
import android.content.pm.parsing.component.ParsedService;
@@ -271,8 +273,10 @@ import android.os.Trace;
import android.os.UserHandle;
import android.os.UserManager;
import android.os.UserManagerInternal;
+import android.os.incremental.IStorageHealthListener;
import android.os.incremental.IncrementalManager;
import android.os.incremental.IncrementalStorage;
+import android.os.incremental.StorageHealthCheckParams;
import android.os.storage.DiskInfo;
import android.os.storage.IStorageManager;
import android.os.storage.StorageEventListener;
@@ -506,9 +510,6 @@ public class PackageManagerService extends IPackageManager.Stub
private static final boolean HIDE_EPHEMERAL_APIS = false;
- private static final boolean ENABLE_FREE_CACHE_V2 =
- SystemProperties.getBoolean("fw.free_cache_v2", true);
-
private static final String PRECOMPILE_LAYOUTS = "pm.precompile_layouts";
private static final int RADIO_UID = Process.PHONE_UID;
@@ -732,14 +733,23 @@ public class PackageManagerService extends IPackageManager.Stub
private static final String RANDOM_DIR_PREFIX = "~~";
+ /**
+ * Timeout configurations for incremental storage health monitor.
+ * See {@link IStorageHealthListener}
+ */
+ private static final int INCREMENTAL_STORAGE_BLOCKED_TIMEOUT_MS = 2000;
+ private static final int INCREMENTAL_STORAGE_UNHEALTHY_TIMEOUT_MS = 7000;
+ private static final int INCREMENTAL_STORAGE_UNHEALTHY_MONITORING_MS = 60000;
+
final ServiceThread mHandlerThread;
final Handler mHandler;
private final ProcessLoggingHandler mProcessLoggingHandler;
- final int mSdkVersion = Build.VERSION.SDK_INT;
+ private final boolean mEnableFreeCacheV2;
+ final int mSdkVersion;
final Context mContext;
final boolean mFactoryTest;
final boolean mOnlyCore;
@@ -894,24 +904,8 @@ public class PackageManagerService extends IPackageManager.Stub
T produce(Injector injector, PackageManagerService packageManager);
}
- static class LocalServicesProducer<T> implements Producer<T> {
- private final Class<T> mProducingClass;
- LocalServicesProducer(Class<T> clazz) {
- this.mProducingClass = clazz;
- }
- public T produce(Injector injector, PackageManagerService packageManager) {
- return LocalServices.getService(mProducingClass);
- }
- }
-
- static class SystemServiceProducer<T> implements Producer<T> {
- private final Class<T> mProducingClass;
- SystemServiceProducer(Class<T> clazz) {
- this.mProducingClass = clazz;
- }
- public T produce(Injector injector, PackageManagerService packageManager) {
- return packageManager.mContext.getSystemService(mProducingClass);
- }
+ interface ServiceProducer {
+ <T> T produce(Class<T> c);
}
@VisibleForTesting(visibility = Visibility.PRIVATE)
@@ -941,41 +935,43 @@ public class PackageManagerService extends IPackageManager.Stub
// ----- producers -----
private final Singleton<ComponentResolver> mComponentResolverProducer;
- private final Singleton<PermissionManagerServiceInternal> mPermissionManagerProducer;
+ private final Singleton<PermissionManagerServiceInternal> mPermissionManagerServiceProducer;
private final Singleton<UserManagerService> mUserManagerProducer;
private final Singleton<Settings> mSettingsProducer;
- private final Singleton<ActivityTaskManagerInternal> mActivityTaskManagerProducer;
- private final Singleton<ActivityManagerInternal> mActivityManagerInternalProducer;
- private final Singleton<DeviceIdleInternal> mLocalDeviceIdleController;
- private final Singleton<StorageManagerInternal> mStorageManagerInternalProducer;
- private final Singleton<NetworkPolicyManagerInternal> mNetworkPolicyManagerProducer;
- private final Singleton<PermissionPolicyInternal> mPermissionPolicyProducer;
- private final Singleton<DeviceStorageMonitorInternal> mDeviceStorageMonitorProducer;
- private final Singleton<DisplayManager> mDisplayManagerProducer;
- private final Singleton<StorageManager> mStorageManagerProducer;
- private final Singleton<AppOpsManager> mAppOpsManagerProducer;
private final Singleton<AppsFilter> mAppsFilterProducer;
private final Singleton<PlatformCompat> mPlatformCompatProducer;
+ private final Singleton<SystemConfig> mSystemConfigProducer;
+ private final Singleton<PackageDexOptimizer> mPackageDexOptimizerProducer;
+ private final Singleton<DexManager> mDexManagerProducer;
+ private final Singleton<ArtManagerService> mArtManagerServiceProducer;
+ private final Singleton<ApexManager> mApexManagerProducer;
+ private final Singleton<ViewCompiler> mViewCompilerProducer;
+ private final Singleton<IPermissionManager> mPermissionManagerProducer;
+ private final Singleton<IncrementalManager> mIncrementalManagerProducer;
+ private final SystemWrapper mSystemWrapper;
+ private final ServiceProducer mGetLocalServiceProducer;
+ private final ServiceProducer mGetSystemServiceProducer;
Injector(Context context, Object lock, Installer installer,
Object installLock, PackageAbiHelper abiHelper,
Handler backgroundHandler,
Producer<ComponentResolver> componentResolverProducer,
- Producer<PermissionManagerServiceInternal> permissionManagerProducer,
+ Producer<PermissionManagerServiceInternal> permissionManagerServiceProducer,
Producer<UserManagerService> userManagerProducer,
Producer<Settings> settingsProducer,
- Producer<ActivityTaskManagerInternal> activityTaskManagerProducer,
- Producer<ActivityManagerInternal> activityManagerInternalProducer,
- Producer<DeviceIdleInternal> deviceIdleControllerProducer,
- Producer<StorageManagerInternal> storageManagerInternalProducer,
- Producer<NetworkPolicyManagerInternal> networkPolicyManagerProducer,
- Producer<PermissionPolicyInternal> permissionPolicyProvider,
- Producer<DeviceStorageMonitorInternal> deviceStorageMonitorProducer,
- Producer<DisplayManager> displayManagerProducer,
- Producer<StorageManager> storageManagerProducer,
- Producer<AppOpsManager> appOpsManagerProducer,
Producer<AppsFilter> appsFilterProducer,
- Producer<PlatformCompat> platformCompatProducer) {
+ Producer<PlatformCompat> platformCompatProducer,
+ Producer<SystemConfig> systemConfigProducer,
+ Producer<PackageDexOptimizer> packageDexOptimizerProducer,
+ Producer<DexManager> dexManagerProducer,
+ Producer<ArtManagerService> artManagerServiceProducer,
+ Producer<ApexManager> apexManagerProducer,
+ Producer<IPermissionManager> permissionManagerProducer,
+ Producer<ViewCompiler> viewCompilerProducer,
+ Producer<IncrementalManager> incrementalManagerProducer,
+ SystemWrapper systemWrapper,
+ ServiceProducer getLocalServiceProducer,
+ ServiceProducer getSystemServiceProducer) {
mContext = context;
mLock = lock;
mInstaller = installer;
@@ -984,21 +980,22 @@ public class PackageManagerService extends IPackageManager.Stub
mBackgroundHandler = backgroundHandler;
mBackgroundExecutor = new HandlerExecutor(backgroundHandler);
mComponentResolverProducer = new Singleton<>(componentResolverProducer);
- mPermissionManagerProducer = new Singleton<>(permissionManagerProducer);
+ mPermissionManagerServiceProducer = new Singleton<>(permissionManagerServiceProducer);
mUserManagerProducer = new Singleton<>(userManagerProducer);
mSettingsProducer = new Singleton<>(settingsProducer);
- mActivityTaskManagerProducer = new Singleton<>(activityTaskManagerProducer);
- mActivityManagerInternalProducer = new Singleton<>(activityManagerInternalProducer);
- mLocalDeviceIdleController = new Singleton<>(deviceIdleControllerProducer);
- mStorageManagerInternalProducer = new Singleton<>(storageManagerInternalProducer);
- mNetworkPolicyManagerProducer = new Singleton<>(networkPolicyManagerProducer);
- mPermissionPolicyProducer = new Singleton<>(permissionPolicyProvider);
- mDeviceStorageMonitorProducer = new Singleton<>(deviceStorageMonitorProducer);
- mDisplayManagerProducer = new Singleton<>(displayManagerProducer);
- mStorageManagerProducer = new Singleton<>(storageManagerProducer);
- mAppOpsManagerProducer = new Singleton<>(appOpsManagerProducer);
mAppsFilterProducer = new Singleton<>(appsFilterProducer);
mPlatformCompatProducer = new Singleton<>(platformCompatProducer);
+ mSystemConfigProducer = new Singleton<>(systemConfigProducer);
+ mPackageDexOptimizerProducer = new Singleton<>(packageDexOptimizerProducer);
+ mDexManagerProducer = new Singleton<>(dexManagerProducer);
+ mArtManagerServiceProducer = new Singleton<>(artManagerServiceProducer);
+ mApexManagerProducer = new Singleton<>(apexManagerProducer);
+ mPermissionManagerProducer = new Singleton<>(permissionManagerProducer);
+ mViewCompilerProducer = new Singleton<>(viewCompilerProducer);
+ mIncrementalManagerProducer = new Singleton<>(incrementalManagerProducer);
+ mSystemWrapper = systemWrapper;
+ mGetLocalServiceProducer = getLocalServiceProducer;
+ mGetSystemServiceProducer = getSystemServiceProducer;
}
/**
@@ -1038,7 +1035,7 @@ public class PackageManagerService extends IPackageManager.Stub
}
public PermissionManagerServiceInternal getPermissionManagerServiceInternal() {
- return mPermissionManagerProducer.get(this, mPackageManager);
+ return mPermissionManagerServiceProducer.get(this, mPackageManager);
}
public Context getContext() {
@@ -1049,60 +1046,112 @@ public class PackageManagerService extends IPackageManager.Stub
return mSettingsProducer.get(this, mPackageManager);
}
- public ActivityTaskManagerInternal getActivityTaskManagerInternal() {
- return mActivityTaskManagerProducer.get(this, mPackageManager);
+ public AppsFilter getAppsFilter() {
+ return mAppsFilterProducer.get(this, mPackageManager);
}
- public ActivityManagerInternal getActivityManagerInternal() {
- return mActivityManagerInternalProducer.get(this, mPackageManager);
+ public PlatformCompat getCompatibility() {
+ return mPlatformCompatProducer.get(this, mPackageManager);
}
- public DeviceIdleInternal getLocalDeviceIdleController() {
- return mLocalDeviceIdleController.get(this, mPackageManager);
+ public SystemConfig getSystemConfig() {
+ return mSystemConfigProducer.get(this, mPackageManager);
}
- public StorageManagerInternal getStorageManagerInternal() {
- return mStorageManagerInternalProducer.get(this, mPackageManager);
+ public PackageDexOptimizer getPackageDexOptimizer() {
+ return mPackageDexOptimizerProducer.get(this, mPackageManager);
}
- public NetworkPolicyManagerInternal getNetworkPolicyManagerInternal() {
- return mNetworkPolicyManagerProducer.get(this, mPackageManager);
+ public DexManager getDexManager() {
+ return mDexManagerProducer.get(this, mPackageManager);
}
- public PermissionPolicyInternal getPermissionPolicyInternal() {
- return mPermissionPolicyProducer.get(this, mPackageManager);
+ public ArtManagerService getArtManagerService() {
+ return mArtManagerServiceProducer.get(this, mPackageManager);
}
- public DeviceStorageMonitorInternal getDeviceStorageMonitorInternal() {
- return mDeviceStorageMonitorProducer.get(this, mPackageManager);
+ public ApexManager getApexManager() {
+ return mApexManagerProducer.get(this, mPackageManager);
}
- public DisplayManager getDisplayManager() {
- return mDisplayManagerProducer.get(this, mPackageManager);
+ public ViewCompiler getViewCompiler() {
+ return mViewCompilerProducer.get(this, mPackageManager);
}
- public StorageManager getStorageManager() {
- return mStorageManagerProducer.get(this, mPackageManager);
+ public IPermissionManager getPermissionManagerService() {
+ return mPermissionManagerProducer.get(this, mPackageManager);
}
- public AppOpsManager getAppOpsManager() {
- return mAppOpsManagerProducer.get(this, mPackageManager);
+ public Handler getBackgroundHandler() {
+ return mBackgroundHandler;
}
- public AppsFilter getAppsFilter() {
- return mAppsFilterProducer.get(this, mPackageManager);
+ public Executor getBackgroundExecutor() {
+ return mBackgroundExecutor;
}
- public PlatformCompat getCompatibility() {
- return mPlatformCompatProducer.get(this, mPackageManager);
+ public <T> T getLocalService(Class<T> c) {
+ return mGetLocalServiceProducer.produce(c);
}
- public Handler getBackgroundHandler() {
- return mBackgroundHandler;
+ public <T> T getSystemService(Class<T> c) {
+ return mGetSystemServiceProducer.produce(c);
}
- public Executor getBackgroundExecutor() {
- return mBackgroundExecutor;
+ public SystemWrapper getSystemWrapper() {
+ return mSystemWrapper;
+ }
+
+ public IncrementalManager getIncrementalManager() {
+ return mIncrementalManagerProducer.get(this, mPackageManager);
+ }
+ }
+
+ /** Provides an abstraction to static access to system state. */
+ public interface SystemWrapper {
+ /** @see SystemProperties#get(String) */
+ String getProperty(String key);
+ /** @see SystemProperties#getInt(String, int) */
+ int getPropertyInt(String key, int defValue);
+ /** @see SystemProperties#getBoolean(String, boolean) */
+ boolean getPropertyBoolean(String key, boolean defValue);
+ /** @see SystemProperties#digestOf(String...) */
+ String digestOfProperties(@NonNull String... keys);
+ /** @see SystemProperties#set(String, String) */
+ void setProperty(String key, String value);
+ /** @see Build.VERSION#SDK_INT */
+ int getSdkInt();
+ }
+
+ private static class DefaultSystemWrapper implements SystemWrapper {
+ @Override
+ public String getProperty(String key) {
+ return SystemProperties.get(key);
+ }
+
+ @Override
+ public int getPropertyInt(String key, int defValue) {
+ return SystemProperties.getInt(key, defValue);
+ }
+
+ @Override
+ public boolean getPropertyBoolean(String key, boolean defValue) {
+ return SystemProperties.getBoolean(key, defValue);
+ }
+
+ @Override
+ public String digestOfProperties(String... keys) {
+ return SystemProperties.digestOf(keys);
+ }
+
+ @Override
+ public void setProperty(String key, String value) {
+ SystemProperties.set(key, value);
+ }
+
+ @Override
+ public int getSdkInt() {
+ return Build.VERSION.SDK_INT;
}
}
@@ -1161,6 +1210,8 @@ public class PackageManagerService extends IPackageManager.Stub
public @Nullable String retailDemoPackage;
public ComponentName resolveComponentName;
public ArrayMap<String, AndroidPackage> packages;
+ public boolean enableFreeCacheV2;
+ public int sdkVersion;
}
private final AppsFilter mAppsFilter;
@@ -1354,7 +1405,7 @@ public class PackageManagerService extends IPackageManager.Stub
options.setTemporaryAppWhitelistDuration(whitelistTimeout);
DeviceIdleInternal idleController =
- mInjector.getLocalDeviceIdleController();
+ mInjector.getLocalService(DeviceIdleInternal.class);
idleController.addPowerSaveTempWhitelistApp(Process.myUid(),
mIntentFilterVerifierComponent.getPackageName(), whitelistTimeout,
UserHandle.USER_SYSTEM, true, "intent filter verifier");
@@ -1427,7 +1478,7 @@ public class PackageManagerService extends IPackageManager.Stub
case INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_ALWAYS:
if (!verified) {
// Don't demote if sysconfig says 'always'
- SystemConfig systemConfig = SystemConfig.getInstance();
+ SystemConfig systemConfig = mInjector.getSystemConfig();
ArraySet<String> packages = systemConfig.getLinkedApps();
if (!packages.contains(packageName)) {
// updatedStatus is already UNDEFINED
@@ -2324,7 +2375,8 @@ public class PackageManagerService extends IPackageManager.Stub
// Send broadcast package appeared if external for all users
if (res.pkg.isExternalStorage()) {
if (!update) {
- final StorageManager storage = mInjector.getStorageManager();
+ final StorageManager storage = mInjector.getSystemService(
+ StorageManager.class);
VolumeInfo volume =
storage.findVolumeByUuid(
res.pkg.getStorageUuid().toString());
@@ -2503,7 +2555,7 @@ public class PackageManagerService extends IPackageManager.Stub
ApkChecksums.Injector injector = new ApkChecksums.Injector(
() -> mContext,
() -> mInjector.getBackgroundHandler(),
- () -> mContext.getSystemService(IncrementalManager.class));
+ () -> mInjector.getIncrementalManager());
ApkChecksums.getChecksums(filesToChecksum, optional, required, trustedCerts,
statusReceiver, injector);
});
@@ -2679,31 +2731,32 @@ public class PackageManagerService extends IPackageManager.Stub
Injector injector = new Injector(
context, lock, installer, installLock, new PackageAbiHelperImpl(),
backgroundHandler,
- (i, pm) ->
- new ComponentResolver(i.getUserManagerService(), pm.mPmInternal, lock),
- (i, pm) ->
- PermissionManagerService.create(context, lock),
- (i, pm) ->
- new UserManagerService(context, pm,
+ (i, pm) -> new ComponentResolver(i.getUserManagerService(), pm.mPmInternal, lock),
+ (i, pm) -> PermissionManagerService.create(context, lock),
+ (i, pm) -> new UserManagerService(context, pm,
new UserDataPreparer(installer, installLock, context, onlyCore),
lock),
- (i, pm) ->
- new Settings(Environment.getDataDirectory(),
- i.getPermissionManagerServiceInternal().getPermissionSettings(),
- RuntimePermissionsPersistence.createInstance(),
- i.getPermissionManagerServiceInternal(), lock),
- new Injector.LocalServicesProducer<>(ActivityTaskManagerInternal.class),
- new Injector.LocalServicesProducer<>(ActivityManagerInternal.class),
- new Injector.LocalServicesProducer<>(DeviceIdleInternal.class),
- new Injector.LocalServicesProducer<>(StorageManagerInternal.class),
- new Injector.LocalServicesProducer<>(NetworkPolicyManagerInternal.class),
- new Injector.LocalServicesProducer<>(PermissionPolicyInternal.class),
- new Injector.LocalServicesProducer<>(DeviceStorageMonitorInternal.class),
- new Injector.SystemServiceProducer<>(DisplayManager.class),
- new Injector.SystemServiceProducer<>(StorageManager.class),
- new Injector.SystemServiceProducer<>(AppOpsManager.class),
+ (i, pm) -> new Settings(Environment.getDataDirectory(),
+ i.getPermissionManagerServiceInternal().getPermissionSettings(),
+ RuntimePermissionsPersistence.createInstance(),
+ i.getPermissionManagerServiceInternal(), lock),
(i, pm) -> AppsFilter.create(pm.mPmInternal, i),
- (i, pm) -> (PlatformCompat) ServiceManager.getService("platform_compat"));
+ (i, pm) -> (PlatformCompat) ServiceManager.getService("platform_compat"),
+ (i, pm) -> SystemConfig.getInstance(),
+ (i, pm) -> new PackageDexOptimizer(i.getInstaller(), i.getInstallLock(),
+ i.getContext(), "*dexopt*"),
+ (i, pm) -> new DexManager(i.getContext(), pm, i.getPackageDexOptimizer(),
+ i.getInstaller(), i.getInstallLock()),
+ (i, pm) -> new ArtManagerService(i.getContext(), pm, i.getInstaller(),
+ i.getInstallLock()),
+ (i, pm) -> ApexManager.getInstance(),
+ (i, pm) -> (IPermissionManager) ServiceManager.getService("permissionmgr"),
+ (i, pm) -> new ViewCompiler(i.getInstallLock(), i.getInstaller()),
+ (i, pm) -> (IncrementalManager)
+ pm.mContext.getSystemService(Context.INCREMENTAL_SERVICE),
+ new DefaultSystemWrapper(),
+ LocalServices::getService,
+ context::getSystemService);
PackageManagerService m = new PackageManagerService(injector, onlyCore, factoryTest);
t.traceEnd(); // "create package manager"
@@ -2776,16 +2829,17 @@ public class PackageManagerService extends IPackageManager.Stub
* reasons. This simply requests that the copy takes place and awaits confirmation of its
* completion. See platform/system/extras/cppreopt/ for the implementation of the actual copy.
*/
- private static void requestCopyPreoptedFiles() {
+ private static void requestCopyPreoptedFiles(Injector injector) {
final int WAIT_TIME_MS = 100;
final String CP_PREOPT_PROPERTY = "sys.cppreopt";
- if (SystemProperties.getInt("ro.cp_system_other_odex", 0) == 1) {
- SystemProperties.set(CP_PREOPT_PROPERTY, "requested");
+ if (injector.getSystemWrapper().getPropertyInt("ro.cp_system_other_odex", 0) == 1) {
+ injector.getSystemWrapper().setProperty(CP_PREOPT_PROPERTY, "requested");
// We will wait for up to 100 seconds.
final long timeStart = SystemClock.uptimeMillis();
final long timeEnd = timeStart + 100 * 1000;
long timeNow = timeStart;
- while (!SystemProperties.get(CP_PREOPT_PROPERTY).equals("finished")) {
+ while (!injector.getSystemWrapper()
+ .getProperty(CP_PREOPT_PROPERTY).equals("finished")) {
try {
Thread.sleep(WAIT_TIME_MS);
} catch (InterruptedException e) {
@@ -2793,7 +2847,7 @@ public class PackageManagerService extends IPackageManager.Stub
}
timeNow = SystemClock.uptimeMillis();
if (timeNow > timeEnd) {
- SystemProperties.set(CP_PREOPT_PROPERTY, "timed-out");
+ injector.getSystemWrapper().setProperty(CP_PREOPT_PROPERTY, "timed-out");
Slog.wtf(TAG, "cppreopt did not finish!");
break;
}
@@ -2925,6 +2979,8 @@ public class PackageManagerService extends IPackageManager.Stub
mResolveComponentName = testParams.resolveComponentName;
mPackages.putAll(testParams.packages);
+ mEnableFreeCacheV2 = testParams.enableFreeCacheV2;
+ mSdkVersion = testParams.sdkVersion;
}
public PackageManagerService(Injector injector, boolean onlyCore, boolean factoryTest) {
@@ -2950,6 +3006,7 @@ public class PackageManagerService extends IPackageManager.Stub
LockGuard.installLock(mLock, LockGuard.INDEX_PACKAGES);
EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_PMS_START,
SystemClock.uptimeMillis());
+ mSdkVersion = injector.getSystemWrapper().getSdkInt();
if (mSdkVersion <= 0) {
Slog.w(TAG, "**** ro.build.version.sdk not set!");
@@ -2960,6 +3017,8 @@ public class PackageManagerService extends IPackageManager.Stub
mOnlyCore = onlyCore;
mMetrics = new DisplayMetrics();
mInstaller = injector.getInstaller();
+ mEnableFreeCacheV2 =
+ injector.getSystemWrapper().getPropertyBoolean("fw.free_cache_v2", true);
// Create sub-components that provide services / data. Order here is important.
t.traceBegin("createSubComponents");
@@ -2971,9 +3030,8 @@ public class PackageManagerService extends IPackageManager.Stub
mComponentResolver = injector.getComponentResolver();
mPermissionManager = injector.getPermissionManagerServiceInternal();
mSettings = injector.getSettings();
- mPermissionManagerService = (IPermissionManager) ServiceManager.getService("permissionmgr");
- mIncrementalManager =
- (IncrementalManager) mContext.getSystemService(Context.INCREMENTAL_SERVICE);
+ mPermissionManagerService = injector.getPermissionManagerService();
+ mIncrementalManager = mInjector.getIncrementalManager();
PlatformCompat platformCompat = mInjector.getCompatibility();
mPackageParserCallback = new PackageParser2.Callback() {
@Override
@@ -3009,7 +3067,8 @@ public class PackageManagerService extends IPackageManager.Stub
ApplicationInfo.FLAG_SYSTEM, ApplicationInfo.PRIVATE_FLAG_PRIVILEGED);
t.traceEnd();
- String separateProcesses = SystemProperties.get("debug.separate_processes");
+ String separateProcesses =
+ injector.getSystemWrapper().getProperty("debug.separate_processes");
if (separateProcesses != null && separateProcesses.length() > 0) {
if ("*".equals(separateProcesses)) {
mDefParseFlags = PackageParser.PARSE_IGNORE_PROCESSES;
@@ -3026,25 +3085,22 @@ public class PackageManagerService extends IPackageManager.Stub
mSeparateProcesses = null;
}
- mPackageDexOptimizer = new PackageDexOptimizer(mInstaller, mInstallLock, mContext,
- "*dexopt*");
- mDexManager =
- new DexManager(mContext, this, mPackageDexOptimizer, mInstaller, mInstallLock);
- mArtManagerService = new ArtManagerService(mContext, this, mInstaller, mInstallLock);
+ mPackageDexOptimizer = injector.getPackageDexOptimizer();
+ mDexManager = injector.getDexManager();
+ mArtManagerService = injector.getArtManagerService();
mMoveCallbacks = new MoveCallbacks(FgThread.get().getLooper());
+ mViewCompiler = injector.getViewCompiler();
- mViewCompiler = new ViewCompiler(mInstallLock, mInstaller);
-
- getDefaultDisplayMetrics(mInjector.getDisplayManager(), mMetrics);
+ getDefaultDisplayMetrics(mInjector.getSystemService(DisplayManager.class), mMetrics);
t.traceBegin("get system config");
- SystemConfig systemConfig = SystemConfig.getInstance();
+ SystemConfig systemConfig = injector.getSystemConfig();
mAvailableFeatures = systemConfig.getAvailableFeatures();
t.traceEnd();
mProtectedPackages = new ProtectedPackages(mContext);
- mApexManager = ApexManager.getInstance();
+ mApexManager = injector.getApexManager();
mAppsFilter = mInjector.getAppsFilter();
final List<ScanPartition> scanPartitions = new ArrayList<>();
@@ -3122,7 +3178,7 @@ public class PackageManagerService extends IPackageManager.Stub
}
if (!mOnlyCore && mFirstBoot) {
- requestCopyPreoptedFiles();
+ requestCopyPreoptedFiles(mInjector);
}
String customResolverActivityName = Resources.getSystem().getString(
@@ -3177,7 +3233,7 @@ public class PackageManagerService extends IPackageManager.Stub
}
}
- mCacheDir = preparePackageParserCache();
+ mCacheDir = preparePackageParserCache(injector);
// Set flag to monitor and not change apk file paths when
// scanning install directories.
@@ -4000,7 +4056,7 @@ public class PackageManagerService extends IPackageManager.Stub
setUpInstantAppInstallerActivityLP(getInstantAppInstallerLPr());
}
- private static @Nullable File preparePackageParserCache() {
+ private static @Nullable File preparePackageParserCache(Injector injector) {
if (!FORCE_PACKAGE_PARSED_CACHE_ENABLED) {
if (!DEFAULT_PACKAGE_PARSER_CACHE_ENABLED) {
return null;
@@ -4011,7 +4067,8 @@ public class PackageManagerService extends IPackageManager.Stub
return null;
}
- if (SystemProperties.getBoolean("pm.boot.disable_package_cache", false)) {
+ if (injector.getSystemWrapper()
+ .getPropertyBoolean("pm.boot.disable_package_cache", false)) {
Slog.i(TAG, "Disabling package parser cache due to system property.");
return null;
}
@@ -4027,7 +4084,7 @@ public class PackageManagerService extends IPackageManager.Stub
// identify cached items. In particular, changing the value of certain
// feature flags should cause us to invalidate any caches.
final String cacheName = FORCE_PACKAGE_PARSED_CACHE_ENABLED ? "debug"
- : SystemProperties.digestOf(
+ : injector.getSystemWrapper().digestOfProperties(
"ro.build.fingerprint",
StorageManager.PROP_ISOLATED_STORAGE,
StorageManager.PROP_ISOLATED_STORAGE_SNAPSHOT
@@ -4093,7 +4150,7 @@ public class PackageManagerService extends IPackageManager.Stub
public boolean isDeviceUpgrading() {
// allow instant applications
// The system property allows testing ota flow when upgraded to the same image.
- return mIsUpgrade || SystemProperties.getBoolean(
+ return mIsUpgrade || mInjector.getSystemWrapper().getPropertyBoolean(
"persist.pm.mock-upgrade", false /* default */);
}
@@ -4360,7 +4417,7 @@ public class PackageManagerService extends IPackageManager.Stub
Slog.d(TAG, "Priming domain verifications in user " + userId);
}
- SystemConfig systemConfig = SystemConfig.getInstance();
+ SystemConfig systemConfig = mInjector.getSystemConfig();
ArraySet<String> packages = systemConfig.getLinkedApps();
for (String packageName : packages) {
@@ -5169,11 +5226,11 @@ public class PackageManagerService extends IPackageManager.Stub
* until the requested bytes are available.
*/
public void freeStorage(String volumeUuid, long bytes, int storageFlags) throws IOException {
- final StorageManager storage = mInjector.getStorageManager();
+ final StorageManager storage = mInjector.getSystemService(StorageManager.class);
final File file = storage.findPathForUuid(volumeUuid);
if (file.getUsableSpace() >= bytes) return;
- if (ENABLE_FREE_CACHE_V2) {
+ if (mEnableFreeCacheV2) {
final boolean internalVolume = Objects.equals(StorageManager.UUID_PRIVATE_INTERNAL,
volumeUuid);
final boolean aggressive = (storageFlags
@@ -5252,7 +5309,7 @@ public class PackageManagerService extends IPackageManager.Stub
private boolean pruneUnusedStaticSharedLibraries(long neededSpace, long maxCachePeriod)
throws IOException {
- final StorageManager storage = mInjector.getStorageManager();
+ final StorageManager storage = mInjector.getSystemService(StorageManager.class);
final File volume = storage.findPathForUuid(StorageManager.UUID_PRIVATE_INTERNAL);
List<VersionedPackage> packagesToDelete = null;
@@ -5500,7 +5557,8 @@ public class PackageManagerService extends IPackageManager.Stub
}
private boolean isRecentsAccessingChildProfiles(int callingUid, int targetUserId) {
- if (!mInjector.getActivityTaskManagerInternal().isCallerRecents(callingUid)) {
+ if (!mInjector.getLocalService(ActivityTaskManagerInternal.class)
+ .isCallerRecents(callingUid)) {
return false;
}
final long token = Binder.clearCallingIdentity();
@@ -5983,7 +6041,7 @@ public class PackageManagerService extends IPackageManager.Stub
res.addAll(mAvailableFeatures.values());
}
final FeatureInfo fi = new FeatureInfo();
- fi.reqGlEsVersion = SystemProperties.getInt("ro.opengles.version",
+ fi.reqGlEsVersion = mInjector.getSystemWrapper().getPropertyInt("ro.opengles.version",
FeatureInfo.GL_ES_VERSION_UNDEFINED);
res.add(fi);
@@ -9065,10 +9123,10 @@ public class PackageManagerService extends IPackageManager.Stub
if (providerInfo != null) {
// Looking for cross-user grants before enforcing the typical cross-users permissions
if (userId != UserHandle.getUserId(callingUid)) {
- final UriGrantsManagerInternal mUgmInternal =
- LocalServices.getService(UriGrantsManagerInternal.class);
+ final UriGrantsManagerInternal ugmInternal =
+ mInjector.getLocalService(UriGrantsManagerInternal.class);
checkedGrants =
- mUgmInternal.checkAuthorityGrants(callingUid, providerInfo, userId, true);
+ ugmInternal.checkAuthorityGrants(callingUid, providerInfo, userId, true);
}
}
if (!checkedGrants) {
@@ -9678,7 +9736,7 @@ public class PackageManagerService extends IPackageManager.Stub
pkgName, getSettingsVersionForPackage(parsedPackage)),
Collections.singletonMap(pkgName,
getSharedLibLatestVersionSetting(scanResult))),
- mSettings.mKeySetManagerService);
+ mSettings.mKeySetManagerService, mInjector);
appIdCreated = optimisticallyRegisterAppId(scanResult);
commitReconciledScanResultLocked(
reconcileResult.get(pkgName), mUserManager.getUserIds());
@@ -9696,6 +9754,18 @@ public class PackageManagerService extends IPackageManager.Stub
mSettings.disableSystemPackageLPw(parsedPackage.getPackageName(), true);
}
}
+ if (mIncrementalManager != null && isIncrementalPath(parsedPackage.getPath())) {
+ if (pkgSetting != null && pkgSetting.isPackageLoading()) {
+ final StorageHealthCheckParams healthCheckParams = new StorageHealthCheckParams();
+ healthCheckParams.blockedTimeoutMs = INCREMENTAL_STORAGE_BLOCKED_TIMEOUT_MS;
+ healthCheckParams.unhealthyTimeoutMs = INCREMENTAL_STORAGE_UNHEALTHY_TIMEOUT_MS;
+ healthCheckParams.unhealthyMonitoringMs =
+ INCREMENTAL_STORAGE_UNHEALTHY_MONITORING_MS;
+ mIncrementalManager.registerHealthListener(parsedPackage.getPath(),
+ healthCheckParams,
+ new IncrementalHealthListener(parsedPackage.getPackageName()));
+ }
+ }
return scanResult.pkgSetting.pkg;
}
@@ -9957,7 +10027,7 @@ public class PackageManagerService extends IPackageManager.Stub
pkgCompilationReason = PackageManagerService.REASON_BACKGROUND_DEXOPT;
}
- if (SystemProperties.getBoolean(PRECOMPILE_LAYOUTS, false)) {
+ if (mInjector.getSystemWrapper().getPropertyBoolean(PRECOMPILE_LAYOUTS, false)) {
mArtManagerService.compileLayouts(pkg);
}
@@ -10933,7 +11003,7 @@ public class PackageManagerService extends IPackageManager.Stub
}
private int getVendorPartitionVersion() {
- final String version = SystemProperties.get("ro.vndk.version");
+ final String version = mInjector.getSystemWrapper().getProperty("ro.vndk.version");
if (!version.isEmpty()) {
try {
return Integer.parseInt(version);
@@ -12349,9 +12419,10 @@ public class PackageManagerService extends IPackageManager.Stub
// A non-preloaded overlay package, without <overlay android:targetName>, will
// only be used if it is signed with the same certificate as its target OR if
// it is signed with the same certificate as a reference package declared
- // in 'config-signature' tag of SystemConfig.
- // If the target is already installed or 'config-signature' tag in SystemConfig
- // is set, check this here to augment the last line of defence which is OMS.
+ // in 'overlay-config-signature' tag of SystemConfig.
+ // If the target is already installed or 'overlay-config-signature' tag in
+ // SystemConfig is set, check this here to augment the last line of defense
+ // which is OMS.
if (pkg.getOverlayTargetName() == null) {
final PackageSetting targetPkgSetting =
mSettings.getPackageLPr(pkg.getOverlayTarget());
@@ -12957,7 +13028,7 @@ public class PackageManagerService extends IPackageManager.Stub
+ intent.toShortString(false, true, false, false)
+ " " + intent.getExtras(), here);
}
- mInjector.getActivityManagerInternal().broadcastIntent(
+ mInjector.getLocalService(ActivityManagerInternal.class).broadcastIntent(
intent, finishedReceiver, requiredPermissions,
finishedReceiver != null, id,
broadcastAllowList == null ? null : broadcastAllowList.get(id));
@@ -14262,7 +14333,7 @@ public class PackageManagerService extends IPackageManager.Stub
&& mInstantAppInstallerActivity.packageName.equals(
mRequiredVerifierPackage)) {
try {
- mInjector.getAppOpsManager()
+ mInjector.getSystemService(AppOpsManager.class)
.checkPackage(installerUid, mRequiredVerifierPackage);
if (DEBUG_VERIFY) {
Slog.i(TAG, "disable verification for instant app");
@@ -14512,7 +14583,7 @@ public class PackageManagerService extends IPackageManager.Stub
if (getInstantAppPackageName(Binder.getCallingUid()) != null) {
throw new SecurityException("Instant applications don't have access to this method");
}
- mInjector.getAppOpsManager().checkPackage(Binder.getCallingUid(),
+ mInjector.getSystemService(AppOpsManager.class).checkPackage(Binder.getCallingUid(),
callerPackageName);
synchronized (mLock) {
PackageSetting ps = mSettings.mPackages.get(packageName);
@@ -14672,7 +14743,7 @@ public class PackageManagerService extends IPackageManager.Stub
*/
private boolean performRollbackManagerRestore(int userId, int token, PackageInstalledInfo res,
PostInstallData data) {
- RollbackManagerInternal rm = LocalServices.getService(RollbackManagerInternal.class);
+ RollbackManagerInternal rm = mInjector.getLocalService(RollbackManagerInternal.class);
final String packageName = res.pkg.getPackageName();
final int[] allUsers = mUserManager.getUserIds();
@@ -15435,7 +15506,7 @@ public class PackageManagerService extends IPackageManager.Stub
integrityVerification.setPackage("android");
DeviceIdleInternal idleController =
- mInjector.getLocalDeviceIdleController();
+ mInjector.getLocalService(DeviceIdleInternal.class);
final long idleDuration = getVerificationTimeout();
idleController.addPowerSaveTempWhitelistAppDirect(Process.myUid(),
@@ -15545,7 +15616,7 @@ public class PackageManagerService extends IPackageManager.Stub
receivers, verificationState);
DeviceIdleInternal idleController =
- mInjector.getLocalDeviceIdleController();
+ mInjector.getLocalService(DeviceIdleInternal.class);
final long idleDuration = getVerificationTimeout();
final BroadcastOptions options = BroadcastOptions.makeBasic();
options.setTemporaryAppWhitelistDuration(idleDuration);
@@ -16355,12 +16426,25 @@ public class PackageManagerService extends IPackageManager.Stub
// TODO(b/169721400): generalize Incremental States and create a Callback object
// that can be used for all the packages.
- final IncrementalStatesCallback incrementalStatesCallback =
- new IncrementalStatesCallback(ps, userId);
final String codePath = ps.getPathString();
if (IncrementalManager.isIncrementalPath(codePath) && mIncrementalManager != null) {
- mIncrementalManager.registerCallback(codePath, incrementalStatesCallback);
+ final IncrementalStatesCallback incrementalStatesCallback =
+ new IncrementalStatesCallback(ps.name,
+ UserHandle.getUid(userId, ps.appId),
+ getInstalledUsers(ps, userId));
ps.setIncrementalStatesCallback(incrementalStatesCallback);
+ mIncrementalManager.registerLoadingProgressCallback(codePath,
+ new IncrementalProgressListener(ps.name));
+ final IncrementalHealthListener incrementalHealthListener =
+ new IncrementalHealthListener(ps.name);
+ final StorageHealthCheckParams healthCheckParams =
+ new StorageHealthCheckParams();
+ healthCheckParams.blockedTimeoutMs = INCREMENTAL_STORAGE_BLOCKED_TIMEOUT_MS;
+ healthCheckParams.unhealthyTimeoutMs = INCREMENTAL_STORAGE_UNHEALTHY_TIMEOUT_MS;
+ healthCheckParams.unhealthyMonitoringMs =
+ INCREMENTAL_STORAGE_UNHEALTHY_MONITORING_MS;
+ mIncrementalManager.registerHealthListener(codePath,
+ new StorageHealthCheckParams(), incrementalHealthListener);
}
// Ensure that the uninstall reason is UNKNOWN for users with the package installed.
@@ -16544,7 +16628,7 @@ public class PackageManagerService extends IPackageManager.Stub
@GuardedBy("mLock")
private static Map<String, ReconciledPackage> reconcilePackagesLocked(
- final ReconcileRequest request, KeySetManagerService ksms)
+ final ReconcileRequest request, KeySetManagerService ksms, Injector injector)
throws ReconcileFailure {
final Map<String, ScanResult> scannedPackages = request.scannedPackages;
@@ -16695,7 +16779,8 @@ public class PackageManagerService extends IPackageManager.Stub
&& compareSignatures(sharedUserSignatures,
parsedPackage.getSigningDetails().signatures)
!= PackageManager.SIGNATURE_MATCH) {
- if (SystemProperties.getInt("ro.product.first_api_level", 0) <= 29) {
+ if (injector.getSystemWrapper()
+ .getPropertyInt("ro.product.first_api_level", 0) <= 29) {
// Mismatched signatures is an error and silently skipping system
// packages will likely break the device in unforeseen ways.
// However, we allow the device to boot anyway because, prior to Q,
@@ -17069,7 +17154,7 @@ public class PackageManagerService extends IPackageManager.Stub
try {
Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "reconcilePackages");
reconciledPackages = reconcilePackagesLocked(
- reconcileRequest, mSettings.mKeySetManagerService);
+ reconcileRequest, mSettings.mKeySetManagerService, mInjector);
} catch (ReconcileFailure e) {
for (InstallRequest request : requests) {
request.installResult.setError("Reconciliation failed...", e);
@@ -17204,7 +17289,7 @@ public class PackageManagerService extends IPackageManager.Stub
if (performDexopt) {
// Compile the layout resources.
- if (SystemProperties.getBoolean(PRECOMPILE_LAYOUTS, false)) {
+ if (mInjector.getSystemWrapper().getPropertyBoolean(PRECOMPILE_LAYOUTS, false)) {
Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "compileLayouts");
mViewCompiler.compileLayouts(pkg);
Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
@@ -17263,45 +17348,39 @@ public class PackageManagerService extends IPackageManager.Stub
NativeLibraryHelper.waitForNativeBinariesExtraction(incrementalStorages);
}
- private class IncrementalStatesCallback extends IPackageLoadingProgressCallback.Stub
- implements IncrementalStates.Callback {
- @GuardedBy("mPackageSetting")
- private final PackageSetting mPackageSetting;
- private final String mPackageName;
- private final String mPathString;
- private final int mUid;
- private final int[] mInstalledUserIds;
-
- IncrementalStatesCallback(PackageSetting packageSetting, int userId) {
- mPackageSetting = packageSetting;
- mPackageName = packageSetting.name;
- mUid = UserHandle.getUid(userId, packageSetting.appId);
- mPathString = packageSetting.getPathString();
- final int[] allUserIds = resolveUserIds(userId);
- final ArrayList<Integer> installedUserIds = new ArrayList<>();
- for (int i = 0; i < allUserIds.length; i++) {
- if (packageSetting.getInstalled(allUserIds[i])) {
- installedUserIds.add(allUserIds[i]);
- }
- }
- final int numInstalledUserId = installedUserIds.size();
- mInstalledUserIds = new int[numInstalledUserId];
- for (int i = 0; i < numInstalledUserId; i++) {
- mInstalledUserIds[i] = installedUserIds.get(i);
+ private int[] getInstalledUsers(PackageSetting ps, int userId) {
+ final int[] allUserIds = resolveUserIds(userId);
+ final ArrayList<Integer> installedUserIdsList = new ArrayList<>();
+ for (int i = 0; i < allUserIds.length; i++) {
+ if (ps.getInstalled(allUserIds[i])) {
+ installedUserIdsList.add(allUserIds[i]);
}
}
+ final int numInstalledUserId = installedUserIdsList.size();
+ final int[] installedUserIds = new int[numInstalledUserId];
+ for (int i = 0; i < numInstalledUserId; i++) {
+ installedUserIds[i] = installedUserIdsList.get(i);
+ }
+ return installedUserIds;
+ }
- @Override
- public void onPackageLoadingProgressChanged(float progress) {
- synchronized (mPackageSetting) {
- mPackageSetting.setLoadingProgress(progress);
- }
+ /**
+ * Package states callback, used to listen for package state changes and send broadcasts
+ */
+ private final class IncrementalStatesCallback implements IncrementalStates.Callback {
+ private final String mPackageName;
+ private final int mUid;
+ private final int[] mInstalledUserIds;
+ IncrementalStatesCallback(String packageName, int uid, int[] installedUserIds) {
+ mPackageName = packageName;
+ mUid = uid;
+ mInstalledUserIds = installedUserIds;
}
@Override
public void onPackageFullyLoaded() {
- mIncrementalManager.unregisterCallback(mPathString, this);
final SparseArray<int[]> newBroadcastAllowList;
+ final String codePath;
synchronized (mLock) {
final PackageSetting ps = mSettings.mPackages.get(mPackageName);
if (ps == null) {
@@ -17309,6 +17388,7 @@ public class PackageManagerService extends IPackageManager.Stub
}
newBroadcastAllowList = mAppsFilter.getVisibilityAllowList(
ps, mInstalledUserIds, mSettings.mPackages);
+ codePath = ps.getPathString();
}
Bundle extras = new Bundle();
extras.putInt(Intent.EXTRA_UID, mUid);
@@ -17317,6 +17397,8 @@ public class PackageManagerService extends IPackageManager.Stub
extras, 0 /*flags*/,
null /*targetPackage*/, null /*finishedReceiver*/,
mInstalledUserIds, null /* instantUserIds */, newBroadcastAllowList);
+ // Unregister health listener as it will always be healthy from now
+ mIncrementalManager.unregisterHealthListener(codePath);
}
@Override
@@ -17333,7 +17415,7 @@ public class PackageManagerService extends IPackageManager.Stub
Bundle extras = new Bundle();
extras.putInt(Intent.EXTRA_UID, mUid);
extras.putString(Intent.EXTRA_PACKAGE_NAME, mPackageName);
- extras.putInt(Intent.EXTRA_REASON, reason);
+ extras.putInt(Intent.EXTRA_UNSTARTABLE_REASON, reason);
// send broadcast to users with this app installed
sendPackageBroadcast(Intent.ACTION_PACKAGE_UNSTARTABLE, mPackageName,
extras, 0 /*flags*/,
@@ -17364,37 +17446,48 @@ public class PackageManagerService extends IPackageManager.Stub
}
/**
- * This is an internal method that is used to indicate changes on the health status of the
- * Incremental Storage used by an installed package with an associated user id. This might
- * result in a change in the loading state of the package.
+ * Loading progress callback, used to listen for progress changes and update package setting
*/
- public void onStorageHealthStatusChanged(String packageName, int status, int userId) {
- final int callingUid = Binder.getCallingUid();
- mPermissionManager.enforceCrossUserPermission(
- callingUid, userId, true, false,
- "onStorageHealthStatusChanged");
- final PackageSetting ps = getPackageSettingForUser(packageName, callingUid, userId);
- if (ps == null) {
- return;
+ private class IncrementalProgressListener extends IPackageLoadingProgressCallback.Stub {
+ private final String mPackageName;
+ IncrementalProgressListener(String packageName) {
+ mPackageName = packageName;
+ }
+
+ @Override
+ public void onPackageLoadingProgressChanged(float progress) {
+ final PackageSetting ps;
+ synchronized (mLock) {
+ ps = mSettings.mPackages.get(mPackageName);
+ }
+ if (ps == null) {
+ return;
+ }
+ ps.setLoadingProgress(progress);
}
- ps.setStorageHealthStatus(status);
}
/**
- * This is an internal method that is used to indicate changes on the stream status of the
- * data loader used by an installed package with an associated user id. This might
- * result in a change in the loading state of the package.
+ * Incremental storage health status callback, used to listen for monitoring changes and update
+ * package setting.
*/
- public void onStreamStatusChanged(String packageName, int status, int userId) {
- final int callingUid = Binder.getCallingUid();
- mPermissionManager.enforceCrossUserPermission(
- callingUid, userId, true, false,
- "onStreamStatusChanged");
- final PackageSetting ps = getPackageSettingForUser(packageName, callingUid, userId);
- if (ps == null) {
- return;
+ private class IncrementalHealthListener extends IStorageHealthListener.Stub {
+ private final String mPackageName;
+ IncrementalHealthListener(String packageName) {
+ mPackageName = packageName;
+ }
+
+ @Override
+ public void onHealthStatus(int storageId, int status) throws RemoteException {
+ final PackageSetting ps;
+ synchronized (mLock) {
+ ps = mSettings.mPackages.get(mPackageName);
+ }
+ if (ps == null) {
+ return;
+ }
+ ps.setStorageHealthStatus(status);
}
- ps.setStreamStatus(status);
}
@Nullable PackageSetting getPackageSettingForUser(String packageName, int callingUid,
@@ -17526,6 +17619,49 @@ public class PackageManagerService extends IPackageManager.Stub
}
}
+ private boolean doesSignatureMatchForPermissions(@NonNull String sourcePackageName,
+ @NonNull ParsedPackage parsedPackage, int scanFlags) {
+ // If the defining package is signed with our cert, it's okay. This
+ // also includes the "updating the same package" case, of course.
+ // "updating same package" could also involve key-rotation.
+
+ final PackageSetting sourcePackageSetting;
+ synchronized (mLock) {
+ sourcePackageSetting = mSettings.getPackageLPr(sourcePackageName);
+ }
+
+ final SigningDetails sourceSigningDetails = (sourcePackageSetting == null
+ ? SigningDetails.UNKNOWN : sourcePackageSetting.getSigningDetails());
+ final KeySetManagerService ksms = mSettings.mKeySetManagerService;
+ if (sourcePackageName.equals(parsedPackage.getPackageName())
+ && (ksms.shouldCheckUpgradeKeySetLocked(
+ sourcePackageSetting, scanFlags))) {
+ return ksms.checkUpgradeKeySetLocked(sourcePackageSetting, parsedPackage);
+ } else {
+
+ // in the event of signing certificate rotation, we need to see if the
+ // package's certificate has rotated from the current one, or if it is an
+ // older certificate with which the current is ok with sharing permissions
+ if (sourceSigningDetails.checkCapability(
+ parsedPackage.getSigningDetails(),
+ PackageParser.SigningDetails.CertCapabilities.PERMISSION)) {
+ return true;
+ } else if (parsedPackage.getSigningDetails().checkCapability(
+ sourceSigningDetails,
+ PackageParser.SigningDetails.CertCapabilities.PERMISSION)) {
+ // the scanned package checks out, has signing certificate rotation
+ // history, and is newer; bring it over
+ synchronized (mLock) {
+ sourcePackageSetting.signatures.mSigningDetails =
+ parsedPackage.getSigningDetails();
+ }
+ return true;
+ } else {
+ return false;
+ }
+ }
+ }
+
@GuardedBy("mInstallLock")
private PrepareResult preparePackageLI(InstallArgs args, PackageInstalledInfo res)
throws PrepareFailure {
@@ -17684,6 +17820,15 @@ public class PackageManagerService extends IPackageManager.Stub
}
}
+ /*
+ * Cannot properly check CANNOT_INSTALL_WITH_BAD_PERMISSION_GROUPS using CompatChanges
+ * as this only works for packages that are installed
+ *
+ * TODO: Move logic for permission group compatibility into PermissionManagerService
+ */
+ boolean cannotInstallWithBadPermissionGroups =
+ parsedPackage.getTargetSdkVersion() >= Build.VERSION_CODES.S;
+
PackageSetting ps = mSettings.mPackages.get(pkgName);
if (ps != null) {
if (DEBUG_INSTALL) Slog.d(TAG, "Existing package: " + ps);
@@ -17735,8 +17880,33 @@ public class PackageManagerService extends IPackageManager.Stub
res.origUsers = ps.queryInstalledUsers(mUserManager.getUserIds(), true);
}
+ final int numGroups = ArrayUtils.size(parsedPackage.getPermissionGroups());
+ for (int groupNum = 0; groupNum < numGroups; groupNum++) {
+ final ParsedPermissionGroup group =
+ parsedPackage.getPermissionGroups().get(groupNum);
+ final PermissionGroupInfo sourceGroup = getPermissionGroupInfo(group.getName(), 0);
+
+ if (sourceGroup != null && cannotInstallWithBadPermissionGroups) {
+ final String sourcePackageName = sourceGroup.packageName;
+
+ if ((replace || !parsedPackage.getPackageName().equals(sourcePackageName))
+ && !doesSignatureMatchForPermissions(sourcePackageName, parsedPackage,
+ scanFlags)) {
+ EventLog.writeEvent(0x534e4554, "146211400", -1,
+ parsedPackage.getPackageName());
+
+ throw new PrepareFailure(INSTALL_FAILED_DUPLICATE_PERMISSION_GROUP,
+ "Package "
+ + parsedPackage.getPackageName()
+ + " attempting to redeclare permission group "
+ + group.getName() + " already owned by "
+ + sourcePackageName);
+ }
+ }
+ }
- int N = ArrayUtils.size(parsedPackage.getPermissions());
+ // TODO: Move logic for checking permission compatibility into PermissionManagerService
+ final int N = ArrayUtils.size(parsedPackage.getPermissions());
for (int i = N - 1; i >= 0; i--) {
final ParsedPermission perm = parsedPackage.getPermissions().get(i);
final BasePermission bp = mPermissionManager.getPermissionTEMP(perm.getName());
@@ -17752,46 +17922,10 @@ public class PackageManagerService extends IPackageManager.Stub
// Check whether the newly-scanned package wants to define an already-defined perm
if (bp != null) {
- // If the defining package is signed with our cert, it's okay. This
- // also includes the "updating the same package" case, of course.
- // "updating same package" could also involve key-rotation.
- final boolean sigsOk;
final String sourcePackageName = bp.getPackageName();
- final PackageSetting sourcePackageSetting;
- synchronized (mLock) {
- sourcePackageSetting = mSettings.getPackageLPr(sourcePackageName);
- }
- final SigningDetails sourceSigningDetails = (sourcePackageSetting == null
- ? SigningDetails.UNKNOWN : sourcePackageSetting.getSigningDetails());
- final KeySetManagerService ksms = mSettings.mKeySetManagerService;
- if (sourcePackageName.equals(parsedPackage.getPackageName())
- && (ksms.shouldCheckUpgradeKeySetLocked(
- sourcePackageSetting, scanFlags))) {
- sigsOk = ksms.checkUpgradeKeySetLocked(sourcePackageSetting, parsedPackage);
- } else {
- // in the event of signing certificate rotation, we need to see if the
- // package's certificate has rotated from the current one, or if it is an
- // older certificate with which the current is ok with sharing permissions
- if (sourceSigningDetails.checkCapability(
- parsedPackage.getSigningDetails(),
- PackageParser.SigningDetails.CertCapabilities.PERMISSION)) {
- sigsOk = true;
- } else if (parsedPackage.getSigningDetails().checkCapability(
- sourceSigningDetails,
- PackageParser.SigningDetails.CertCapabilities.PERMISSION)) {
- // the scanned package checks out, has signing certificate rotation
- // history, and is newer; bring it over
- synchronized (mLock) {
- sourcePackageSetting.signatures.mSigningDetails =
- parsedPackage.getSigningDetails();
- }
- sigsOk = true;
- } else {
- sigsOk = false;
- }
- }
- if (!sigsOk) {
+ if (!doesSignatureMatchForPermissions(sourcePackageName, parsedPackage,
+ scanFlags)) {
// If the owning package is the system itself, we log but allow
// install to proceed; we fail the install on all other permission
// redefinitions.
@@ -17826,6 +17960,52 @@ public class PackageManagerService extends IPackageManager.Stub
}
}
}
+
+ if (perm.getGroup() != null && cannotInstallWithBadPermissionGroups) {
+ boolean isPermGroupDefinedByPackage = false;
+ for (int groupNum = 0; groupNum < numGroups; groupNum++) {
+ if (parsedPackage.getPermissionGroups().get(groupNum).getName()
+ .equals(perm.getGroup())) {
+ isPermGroupDefinedByPackage = true;
+ break;
+ }
+ }
+
+ if (!isPermGroupDefinedByPackage) {
+ final PermissionGroupInfo sourceGroup =
+ getPermissionGroupInfo(perm.getGroup(), 0);
+
+ if (sourceGroup == null) {
+ EventLog.writeEvent(0x534e4554, "146211400", -1,
+ parsedPackage.getPackageName());
+
+ throw new PrepareFailure(INSTALL_FAILED_BAD_PERMISSION_GROUP,
+ "Package "
+ + parsedPackage.getPackageName()
+ + " attempting to declare permission "
+ + perm.getName() + " in non-existing group "
+ + perm.getGroup());
+ } else {
+ String groupSourcePackageName = sourceGroup.packageName;
+
+ if (!PLATFORM_PACKAGE_NAME.equals(groupSourcePackageName)
+ && !doesSignatureMatchForPermissions(groupSourcePackageName,
+ parsedPackage, scanFlags)) {
+ EventLog.writeEvent(0x534e4554, "146211400", -1,
+ parsedPackage.getPackageName());
+
+ throw new PrepareFailure(INSTALL_FAILED_BAD_PERMISSION_GROUP,
+ "Package "
+ + parsedPackage.getPackageName()
+ + " attempting to declare permission "
+ + perm.getName() + " in group "
+ + perm.getGroup() + " owned by package "
+ + groupSourcePackageName
+ + " with incompatible certificate");
+ }
+ }
+ }
+ }
}
}
@@ -19029,7 +19209,7 @@ public class PackageManagerService extends IPackageManager.Stub
extras.putInt(Intent.EXTRA_UID, removedUid);
extras.putBoolean(Intent.EXTRA_DATA_REMOVED, dataRemoved);
extras.putBoolean(Intent.EXTRA_DONT_KILL_APP, !killApp);
- extras.putBoolean(Intent.EXTRA_REMOVED_BY_SYSTEM, removedBySystem);
+ extras.putBoolean(Intent.EXTRA_USER_INITIATED, !removedBySystem);
if (isUpdate || isRemovedPackageSystemUpdate) {
extras.putBoolean(Intent.EXTRA_REPLACING, true);
}
@@ -19839,7 +20019,7 @@ public class PackageManagerService extends IPackageManager.Stub
}
private void resetNetworkPolicies(int userId) {
- mInjector.getNetworkPolicyManagerInternal().resetUserState(userId);
+ mInjector.getLocalService(NetworkPolicyManagerInternal.class).resetUserState(userId);
}
/**
@@ -21105,7 +21285,7 @@ public class PackageManagerService extends IPackageManager.Stub
}
public String getOverlayConfigSignaturePackageName() {
- return ensureSystemPackageName(SystemConfig.getInstance()
+ return ensureSystemPackageName(mInjector.getSystemConfig()
.getOverlayConfigSignaturePackage());
}
@@ -21875,7 +22055,7 @@ public class PackageManagerService extends IPackageManager.Stub
mPermissionManager.updateAllPermissions(StorageManager.UUID_PRIVATE_INTERNAL, false);
final PermissionPolicyInternal permissionPolicyInternal =
- mInjector.getPermissionPolicyInternal();
+ mInjector.getLocalService(PermissionPolicyInternal.class);
permissionPolicyInternal.setOnInitializedCallback(userId -> {
// The SDK updated case is already handled when we run during the ctor.
synchronized (mLock) {
@@ -21886,13 +22066,13 @@ public class PackageManagerService extends IPackageManager.Stub
}
// Watch for external volumes that come and go over time
- final StorageManager storage = mInjector.getStorageManager();
+ final StorageManager storage = mInjector.getSystemService(StorageManager.class);
storage.registerListener(mStorageListener);
mInstallerService.systemReady();
mPackageDexOptimizer.systemReady();
- mInjector.getStorageManagerInternal().addExternalStoragePolicy(
+ mInjector.getLocalService(StorageManagerInternal.class).addExternalStoragePolicy(
new StorageManagerInternal.ExternalStorageMountPolicy() {
@Override
public int getMountMode(int uid, String packageName) {
@@ -22237,11 +22417,8 @@ public class PackageManagerService extends IPackageManager.Stub
final IndentingPrintWriter ipw = new IndentingPrintWriter(pw, " ", 120);
ipw.println("Known Packages:");
ipw.increaseIndent();
- for (int i = 0; i < LAST_KNOWN_PACKAGE; i++) {
+ for (int i = 0; i <= LAST_KNOWN_PACKAGE; i++) {
final String knownPackage = mPmInternal.knownPackageToString(i);
- if ("Unknown".equals(knownPackage)) {
- continue;
- }
ipw.print(knownPackage);
ipw.println(":");
final String[] pkgNames = mPmInternal.getKnownPackageNames(i,
@@ -22625,7 +22802,7 @@ public class PackageManagerService extends IPackageManager.Stub
if (ArrayUtils.isEmpty(apkList)) {
return;
}
- String sku = SystemProperties.get("ro.boot.hardware.sku");
+ String sku = mInjector.getSystemWrapper().getProperty("ro.boot.hardware.sku");
if (!TextUtils.isEmpty(sku) && ArrayUtils.contains(skuArray, sku)) {
return;
}
@@ -22921,7 +23098,7 @@ public class PackageManagerService extends IPackageManager.Stub
}
// Reconcile app data for all started/unlocked users
- final StorageManager sm = mInjector.getStorageManager();
+ final StorageManager sm = mInjector.getSystemService(StorageManager.class);
UserManagerInternal umInternal = mInjector.getUserManagerInternal();
for (UserInfo user : mUserManager.getUsers(false /* includeDying */)) {
final int flags;
@@ -23122,7 +23299,7 @@ public class PackageManagerService extends IPackageManager.Stub
* correct for all installed apps on all mounted volumes.
*/
void reconcileAppsData(int userId, int flags, boolean migrateAppsData) {
- final StorageManager storage = mInjector.getStorageManager();
+ final StorageManager storage = mInjector.getSystemService(StorageManager.class);
for (VolumeInfo vol : storage.getWritablePrivateVolumes()) {
final String volumeUuid = vol.getFsUuid();
synchronized (mInstallLock) {
@@ -23257,7 +23434,7 @@ public class PackageManagerService extends IPackageManager.Stub
Installer.Batch batch = new Installer.Batch();
UserManagerInternal umInternal = mInjector.getUserManagerInternal();
- StorageManagerInternal smInternal = mInjector.getStorageManagerInternal();
+ StorageManagerInternal smInternal = mInjector.getLocalService(StorageManagerInternal.class);
for (UserInfo user : mUserManager.getUsers(false /*excludeDying*/)) {
final int flags;
if (umInternal.isUserUnlockingOrUnlocked(user.id)) {
@@ -23586,7 +23763,7 @@ public class PackageManagerService extends IPackageManager.Stub
private void movePackageInternal(final String packageName, final String volumeUuid,
final int moveId, final int callingUid, UserHandle user)
throws PackageManagerException {
- final StorageManager storage = mInjector.getStorageManager();
+ final StorageManager storage = mInjector.getSystemService(StorageManager.class);
final PackageManager pm = mContext.getPackageManager();
final String currentVolumeUuid;
@@ -23824,7 +24001,7 @@ public class PackageManagerService extends IPackageManager.Stub
return;
}
- final StorageManager storage = mInjector.getStorageManager();;
+ final StorageManager storage = mInjector.getSystemService(StorageManager.class);;
VolumeInfo volume = storage.findVolumeByUuid(pkg.getStorageUuid().toString());
int packageExternalStorageType = getPackageExternalStorageType(volume, pkg.isExternalStorage());
@@ -23864,7 +24041,7 @@ public class PackageManagerService extends IPackageManager.Stub
}
};
- final StorageManager storage = mInjector.getStorageManager();
+ final StorageManager storage = mInjector.getSystemService(StorageManager.class);
storage.setPrimaryStorageUuid(volumeUuid, callback);
return realMoveId;
}
@@ -24044,7 +24221,7 @@ public class PackageManagerService extends IPackageManager.Stub
final long token = Binder.clearCallingIdentity();
try {
final DeviceStorageMonitorInternal
- dsm = mInjector.getDeviceStorageMonitorInternal();
+ dsm = mInjector.getLocalService(DeviceStorageMonitorInternal.class);
if (dsm != null) {
return dsm.isMemoryLow();
} else {
@@ -25636,7 +25813,7 @@ public class PackageManagerService extends IPackageManager.Stub
"Failed registering loading progress callback. Incremental is not enabled");
return false;
}
- return mIncrementalManager.registerCallback(ps.getPathString(),
+ return mIncrementalManager.registerLoadingProgressCallback(ps.getPathString(),
(IPackageLoadingProgressCallback) callback.getBinder());
}
@@ -25655,7 +25832,7 @@ public class PackageManagerService extends IPackageManager.Stub
if (mIncrementalManager == null) {
return false;
}
- return mIncrementalManager.unregisterCallback(ps.getPathString(),
+ return mIncrementalManager.unregisterLoadingProgressCallback(ps.getPathString(),
(IPackageLoadingProgressCallback) callback.getBinder());
}
}
@@ -25828,7 +26005,7 @@ public class PackageManagerService extends IPackageManager.Stub
@Override
public boolean isAutoRevokeWhitelisted(String packageName) {
- int mode = mInjector.getAppOpsManager().checkOpNoThrow(
+ int mode = mInjector.getSystemService(AppOpsManager.class).checkOpNoThrow(
AppOpsManager.OP_AUTO_REVOKE_PERMISSIONS_IF_UNUSED,
Binder.getCallingUid(), packageName);
return mode == MODE_IGNORED;
diff --git a/services/core/java/com/android/server/pm/PackageManagerShellCommand.java b/services/core/java/com/android/server/pm/PackageManagerShellCommand.java
index c46a7efaa704..9aa1a621a760 100644
--- a/services/core/java/com/android/server/pm/PackageManagerShellCommand.java
+++ b/services/core/java/com/android/server/pm/PackageManagerShellCommand.java
@@ -2729,13 +2729,13 @@ class PackageManagerShellCommand extends ShellCommand {
Slog.i(TAG, "Removing " + userId + " or set as ephemeral if in use.");
int result = um.removeUserOrSetEphemeral(userId);
switch (result) {
- case UserManagerService.REMOVE_RESULT_REMOVED:
+ case UserManager.REMOVE_RESULT_REMOVED:
getOutPrintWriter().printf("Success: user %d removed\n", userId);
return 0;
- case UserManagerService.REMOVE_RESULT_SET_EPHEMERAL:
+ case UserManager.REMOVE_RESULT_SET_EPHEMERAL:
getOutPrintWriter().printf("Success: user %d set as ephemeral\n", userId);
return 0;
- case UserManagerService.REMOVE_RESULT_ALREADY_BEING_REMOVED:
+ case UserManager.REMOVE_RESULT_ALREADY_BEING_REMOVED:
getOutPrintWriter().printf("Success: user %d is already being removed\n", userId);
return 0;
default:
diff --git a/services/core/java/com/android/server/pm/PackageSetting.java b/services/core/java/com/android/server/pm/PackageSetting.java
index de9d3a09df35..83f6c5285874 100644
--- a/services/core/java/com/android/server/pm/PackageSetting.java
+++ b/services/core/java/com/android/server/pm/PackageSetting.java
@@ -28,11 +28,13 @@ import android.util.proto.ProtoOutputStream;
import com.android.internal.annotations.VisibleForTesting;
import com.android.server.pm.parsing.pkg.AndroidPackage;
+import com.android.server.pm.permission.LegacyPermissionDataProvider;
import com.android.server.pm.permission.LegacyPermissionState;
import com.android.server.pm.pkg.PackageStateUnserialized;
import java.io.File;
import java.util.ArrayList;
+import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.Map;
@@ -300,7 +302,8 @@ public class PackageSetting extends PackageSettingBase {
return mimeGroups != null ? mimeGroups.get(mimeGroup) : null;
}
- public void dumpDebug(ProtoOutputStream proto, long fieldId, List<UserInfo> users) {
+ public void dumpDebug(ProtoOutputStream proto, long fieldId, List<UserInfo> users,
+ LegacyPermissionDataProvider dataProvider) {
final long packageToken = proto.start(fieldId);
proto.write(PackageProto.NAME, (realName != null ? realName : name));
proto.write(PackageProto.UID, appId);
@@ -337,9 +340,33 @@ public class PackageSetting extends PackageSettingBase {
proto.write(PackageProto.StatesProto.IS_STARTABLE, incrementalStates.isStartable());
proto.write(PackageProto.StatesProto.IS_LOADING, incrementalStates.isLoading());
writeUsersInfoToProto(proto, PackageProto.USERS);
+ writePackageUserPermissionsProto(proto, PackageProto.USER_PERMISSIONS, users, dataProvider);
proto.end(packageToken);
}
+ /**
+ * TODO (b/170263003) refactor to dump to permissiongr proto
+ * Dumps the permissions that are granted to users for this package.
+ */
+ void writePackageUserPermissionsProto(ProtoOutputStream proto, long fieldId,
+ List<UserInfo> users, LegacyPermissionDataProvider dataProvider) {
+ Collection<LegacyPermissionState.PermissionState> runtimePermissionStates;
+ for (UserInfo user : users) {
+ final long permissionsToken = proto.start(PackageProto.USER_PERMISSIONS);
+ proto.write(PackageProto.UserPermissionsProto.ID, user.id);
+
+ runtimePermissionStates = dataProvider.getLegacyPermissionState(appId)
+ .getRuntimePermissionStates(user.id);
+ for (LegacyPermissionState.PermissionState permission : runtimePermissionStates) {
+ if (permission.isGranted()) {
+ proto.write(PackageProto.UserPermissionsProto.GRANTED_PERMISSIONS,
+ permission.getName());
+ }
+ }
+ proto.end(permissionsToken);
+ }
+ }
+
/** Updates all fields in the current setting from another. */
public void updateFrom(PackageSetting other) {
super.updateFrom(other);
diff --git a/services/core/java/com/android/server/pm/PackageSettingBase.java b/services/core/java/com/android/server/pm/PackageSettingBase.java
index d52ad46d4b7e..be7c7c6ff1d6 100644
--- a/services/core/java/com/android/server/pm/PackageSettingBase.java
+++ b/services/core/java/com/android/server/pm/PackageSettingBase.java
@@ -793,13 +793,6 @@ public abstract class PackageSettingBase extends SettingBase {
incrementalStates.onStorageHealthStatusChanged(status);
}
- /**
- * @see IncrementalStates#onStreamStatusChanged(int)
- */
- public void setStreamStatus(int status) {
- incrementalStates.onStreamStatusChanged(status);
- }
-
protected PackageSettingBase updateFrom(PackageSettingBase other) {
super.copyFrom(other);
setPath(other.getPath());
diff --git a/services/core/java/com/android/server/pm/PackageSignatures.java b/services/core/java/com/android/server/pm/PackageSignatures.java
index 6bce78862087..b7d1eec68c7a 100644
--- a/services/core/java/com/android/server/pm/PackageSignatures.java
+++ b/services/core/java/com/android/server/pm/PackageSignatures.java
@@ -309,7 +309,7 @@ class PackageSignatures {
@Override
public String toString() {
- StringBuffer buf = new StringBuffer(128);
+ StringBuilder buf = new StringBuilder(128);
buf.append("PackageSignatures{");
buf.append(Integer.toHexString(System.identityHashCode(this)));
buf.append(" version:");
diff --git a/services/core/java/com/android/server/pm/PackageUsage.java b/services/core/java/com/android/server/pm/PackageUsage.java
index ef37a20479d6..ec8977988e3f 100644
--- a/services/core/java/com/android/server/pm/PackageUsage.java
+++ b/services/core/java/com/android/server/pm/PackageUsage.java
@@ -97,7 +97,7 @@ class PackageUsage extends AbstractStatsBase<Map<String, PackageSetting>> {
BufferedInputStream in = null;
try {
in = new BufferedInputStream(file.openRead());
- StringBuffer sb = new StringBuffer();
+ StringBuilder sb = new StringBuilder();
String firstLine = readLine(in, sb);
if (firstLine == null) {
@@ -117,7 +117,7 @@ class PackageUsage extends AbstractStatsBase<Map<String, PackageSetting>> {
}
private void readVersion0LP(Map<String, PackageSetting> pkgSettings, InputStream in,
- StringBuffer sb, String firstLine)
+ StringBuilder sb, String firstLine)
throws IOException {
// Initial version of the file had no version number and stored one
// package-timestamp pair per line.
@@ -145,7 +145,7 @@ class PackageUsage extends AbstractStatsBase<Map<String, PackageSetting>> {
}
private void readVersion1LP(Map<String, PackageSetting> pkgSettings, InputStream in,
- StringBuffer sb) throws IOException {
+ StringBuilder sb) throws IOException {
// Version 1 of the file started with the corresponding version
// number and then stored a package name and eight timestamps per line.
String line;
@@ -178,11 +178,11 @@ class PackageUsage extends AbstractStatsBase<Map<String, PackageSetting>> {
}
}
- private String readLine(InputStream in, StringBuffer sb) throws IOException {
+ private String readLine(InputStream in, StringBuilder sb) throws IOException {
return readToken(in, sb, '\n');
}
- private String readToken(InputStream in, StringBuffer sb, char endOfToken)
+ private String readToken(InputStream in, StringBuilder sb, char endOfToken)
throws IOException {
sb.setLength(0);
while (true) {
diff --git a/services/core/java/com/android/server/pm/Settings.java b/services/core/java/com/android/server/pm/Settings.java
index 4c8d2b9b0a9e..c7304c2695c9 100644
--- a/services/core/java/com/android/server/pm/Settings.java
+++ b/services/core/java/com/android/server/pm/Settings.java
@@ -5018,7 +5018,7 @@ public final class Settings {
final int count = mPackages.size();
for (int i = 0; i < count; i++) {
final PackageSetting ps = mPackages.valueAt(i);
- ps.dumpDebug(proto, PackageServiceDumpProto.PACKAGES, users);
+ ps.dumpDebug(proto, PackageServiceDumpProto.PACKAGES, users, mPermissionDataProvider);
}
}
diff --git a/services/core/java/com/android/server/pm/UserManagerService.java b/services/core/java/com/android/server/pm/UserManagerService.java
index 66e84b180588..a0344e27f96c 100644
--- a/services/core/java/com/android/server/pm/UserManagerService.java
+++ b/services/core/java/com/android/server/pm/UserManagerService.java
@@ -22,7 +22,6 @@ import static android.content.Intent.FLAG_ACTIVITY_NEW_TASK;
import android.Manifest;
import android.annotation.ColorRes;
import android.annotation.DrawableRes;
-import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.StringRes;
@@ -132,8 +131,6 @@ import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.PrintWriter;
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.Arrays;
@@ -248,43 +245,6 @@ public class UserManagerService extends IUserManager.Stub {
static final int WRITE_USER_MSG = 1;
static final int WRITE_USER_DELAY = 2*1000; // 2 seconds
- /**
- * A response code from {@link #removeUserOrSetEphemeral(int)} indicating that the specified
- * user has been successfully removed.
- */
- 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.
- */
- public static final int REMOVE_RESULT_SET_EPHEMERAL = 1;
-
- /**
- * A response code from {@link #removeUserOrSetEphemeral(int)} indicating that the specified
- * user is already in the process of being removed.
- */
- 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.
- */
- public static final int REMOVE_RESULT_ERROR = 3;
-
- /**
- * Possible response codes from {@link #removeUserOrSetEphemeral(int)}.
- */
- @IntDef(prefix = { "REMOVE_RESULT_" }, value = {
- REMOVE_RESULT_REMOVED,
- REMOVE_RESULT_SET_EPHEMERAL,
- REMOVE_RESULT_ALREADY_BEING_REMOVED,
- REMOVE_RESULT_ERROR,
- })
- @Retention(RetentionPolicy.SOURCE)
- public @interface RemoveResult {}
-
// Tron counters
private static final String TRON_GUEST_CREATED = "users_guest_created";
private static final String TRON_USER_CREATED = "users_user_created";
@@ -4031,17 +3991,17 @@ public class UserManagerService extends IUserManager.Stub {
}
@Override
- public @RemoveResult int removeUserOrSetEphemeral(@UserIdInt int userId) {
+ public @UserManager.RemoveResult int removeUserOrSetEphemeral(@UserIdInt int userId) {
Slog.i(LOG_TAG, "removeUserOrSetEphemeral u" + userId);
checkManageUsersPermission("Only the system can remove users");
final String restriction = getUserRemovalRestriction(userId);
if (getUserRestrictions(UserHandle.getCallingUserId()).getBoolean(restriction, false)) {
Slog.w(LOG_TAG, "Cannot remove user. " + restriction + " is enabled.");
- return REMOVE_RESULT_ERROR;
+ return UserManager.REMOVE_RESULT_ERROR;
}
if (userId == UserHandle.USER_SYSTEM) {
Slog.e(LOG_TAG, "System user cannot be removed.");
- return REMOVE_RESULT_ERROR;
+ return UserManager.REMOVE_RESULT_ERROR;
}
final long ident = Binder.clearCallingIdentity();
@@ -4053,12 +4013,12 @@ public class UserManagerService extends IUserManager.Stub {
if (userData == null) {
Slog.e(LOG_TAG,
"Cannot remove user " + userId + ", invalid user id provided.");
- return REMOVE_RESULT_ERROR;
+ return UserManager.REMOVE_RESULT_ERROR;
}
if (mRemovingUserIds.get(userId)) {
Slog.e(LOG_TAG, "User " + userId + " is already scheduled for removal.");
- return REMOVE_RESULT_ALREADY_BEING_REMOVED;
+ return UserManager.REMOVE_RESULT_ALREADY_BEING_REMOVED;
}
}
@@ -4067,7 +4027,7 @@ public class UserManagerService extends IUserManager.Stub {
if (currentUser != userId) {
// Attempt to remove the user. This will fail if the user is the current user
if (removeUser(userId)) {
- return REMOVE_RESULT_REMOVED;
+ return UserManager.REMOVE_RESULT_REMOVED;
}
Slog.w(LOG_TAG, "Unable to immediately remove non-current user: " + userId
@@ -4081,7 +4041,7 @@ public class UserManagerService extends IUserManager.Stub {
userData.info.flags |= UserInfo.FLAG_EPHEMERAL;
writeUserLP(userData);
- return REMOVE_RESULT_SET_EPHEMERAL;
+ return UserManager.REMOVE_RESULT_SET_EPHEMERAL;
}
} finally {
Binder.restoreCallingIdentity(ident);
diff --git a/services/core/java/com/android/server/pm/permission/BasePermission.java b/services/core/java/com/android/server/pm/permission/BasePermission.java
index bebb67686696..667414e9cc72 100644
--- a/services/core/java/com/android/server/pm/permission/BasePermission.java
+++ b/services/core/java/com/android/server/pm/permission/BasePermission.java
@@ -198,6 +198,11 @@ public final class BasePermission {
== PermissionInfo.PROTECTION_DANGEROUS;
}
+ public boolean isInstalled() {
+ return mPermissionInfo != null
+ && (mPermissionInfo.flags & PermissionInfo.FLAG_INSTALLED) != 0;
+ }
+
public boolean isRemoved() {
return mPermissionInfo != null
&& (mPermissionInfo.flags & PermissionInfo.FLAG_REMOVED) != 0;
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 19a56505416d..d871325fe829 100644
--- a/services/core/java/com/android/server/pm/permission/PermissionManagerService.java
+++ b/services/core/java/com/android/server/pm/permission/PermissionManagerService.java
@@ -2352,19 +2352,23 @@ public class PermissionManagerService extends IPermissionManager.Stub {
final PermissionInfo permissionInfo = PackageInfoUtils.generatePermissionInfo(p,
PackageManager.GET_META_DATA);
+ final BasePermission bp;
if (p.isTree()) {
- final BasePermission bp = BasePermission.createOrUpdate(
+ bp = BasePermission.createOrUpdate(
mPackageManagerInt,
mSettings.getPermissionTreeLocked(p.getName()), permissionInfo, pkg,
mSettings.getAllPermissionTreesLocked(), chatty);
mSettings.putPermissionTreeLocked(p.getName(), bp);
} else {
- final BasePermission bp = BasePermission.createOrUpdate(
+ bp = BasePermission.createOrUpdate(
mPackageManagerInt,
mSettings.getPermissionLocked(p.getName()),
permissionInfo, pkg, mSettings.getAllPermissionTreesLocked(), chatty);
mSettings.putPermissionLocked(p.getName(), bp);
}
+ if (bp.isInstalled()) {
+ p.setFlags(p.getFlags() | PermissionInfo.FLAG_INSTALLED);
+ }
}
}
}
diff --git a/services/core/java/com/android/server/policy/DisplayFoldController.java b/services/core/java/com/android/server/policy/DisplayFoldController.java
index 0ca6e5923f1b..f8e26fc57b95 100644
--- a/services/core/java/com/android/server/policy/DisplayFoldController.java
+++ b/services/core/java/com/android/server/policy/DisplayFoldController.java
@@ -80,37 +80,42 @@ class DisplayFoldController {
}
void setDeviceFolded(boolean folded) {
- mDisplayManagerInternal.setDeviceFolded(folded);
-
if (mFolded != null && mFolded == folded) {
return;
}
- if (folded) {
- Rect foldedArea;
- if (!mOverrideFoldedArea.isEmpty()) {
- foldedArea = mOverrideFoldedArea;
- } else if (!mFoldedArea.isEmpty()) {
- foldedArea = mFoldedArea;
- } else {
- return;
- }
- mDisplayManagerInternal.getNonOverrideDisplayInfo(mDisplayId, mNonOverrideDisplayInfo);
- final int dx = (mNonOverrideDisplayInfo.logicalWidth - foldedArea.width()) / 2
- - foldedArea.left;
- final int dy = (mNonOverrideDisplayInfo.logicalHeight - foldedArea.height()) / 2
- - foldedArea.top;
-
- // Bypass scaling otherwise LogicalDisplay will scale contents by default.
- mDisplayManagerInternal.setDisplayScalingDisabled(mDisplayId, true);
- mWindowManagerInternal.setForcedDisplaySize(mDisplayId,
- foldedArea.width(), foldedArea.height());
- mDisplayManagerInternal.setDisplayOffsets(mDisplayId, -dx, -dy);
+ final Rect foldedArea;
+ if (!mOverrideFoldedArea.isEmpty()) {
+ foldedArea = mOverrideFoldedArea;
+ } else if (!mFoldedArea.isEmpty()) {
+ foldedArea = mFoldedArea;
} else {
- mDisplayManagerInternal.setDisplayScalingDisabled(mDisplayId, false);
- mWindowManagerInternal.clearForcedDisplaySize(mDisplayId);
- mDisplayManagerInternal.setDisplayOffsets(mDisplayId, 0, 0);
+ foldedArea = null;
}
+
+ // Only do display scaling/cropping if it has been configured to do so
+ if (foldedArea != null) {
+ if (folded) {
+
+ mDisplayManagerInternal.getNonOverrideDisplayInfo(
+ mDisplayId, mNonOverrideDisplayInfo);
+ final int dx = (mNonOverrideDisplayInfo.logicalWidth - foldedArea.width()) / 2
+ - foldedArea.left;
+ final int dy = (mNonOverrideDisplayInfo.logicalHeight - foldedArea.height()) / 2
+ - foldedArea.top;
+
+ // Bypass scaling otherwise LogicalDisplay will scale contents by default.
+ mDisplayManagerInternal.setDisplayScalingDisabled(mDisplayId, true);
+ mWindowManagerInternal.setForcedDisplaySize(mDisplayId,
+ foldedArea.width(), foldedArea.height());
+ mDisplayManagerInternal.setDisplayOffsets(mDisplayId, -dx, -dy);
+ } else {
+ mDisplayManagerInternal.setDisplayScalingDisabled(mDisplayId, false);
+ mWindowManagerInternal.clearForcedDisplaySize(mDisplayId);
+ mDisplayManagerInternal.setDisplayOffsets(mDisplayId, 0, 0);
+ }
+ }
+
mDurationLogger.setDeviceFolded(folded);
mDurationLogger.logFocusedAppWithFoldState(folded, mFocusedApp);
mFolded = folded;
diff --git a/services/core/java/com/android/server/policy/PhoneWindowManager.java b/services/core/java/com/android/server/policy/PhoneWindowManager.java
index b74de1347224..0983e10d2965 100644
--- a/services/core/java/com/android/server/policy/PhoneWindowManager.java
+++ b/services/core/java/com/android/server/policy/PhoneWindowManager.java
@@ -471,7 +471,6 @@ public class PhoneWindowManager implements WindowManagerPolicy {
int mLidKeyboardAccessibility;
int mLidNavigationAccessibility;
private boolean mLidControlsDisplayFold;
- private boolean mShouldSwapDisplaysOnLidSwitch;
int mShortPressOnPowerBehavior;
int mLongPressOnPowerBehavior;
int mVeryLongPressOnPowerBehavior;
@@ -1849,8 +1848,6 @@ public class PhoneWindowManager implements WindowManagerPolicy {
com.android.internal.R.integer.config_lidNavigationAccessibility);
mLidControlsDisplayFold = mContext.getResources().getBoolean(
com.android.internal.R.bool.config_lidControlsDisplayFold);
- mShouldSwapDisplaysOnLidSwitch = mContext.getResources().getStringArray(
- com.android.internal.R.array.config_internalFoldedPhysicalDisplayIds).length == 2;
mAllowTheaterModeWakeFromKey = mContext.getResources().getBoolean(
com.android.internal.R.bool.config_allowTheaterModeWakeFromKey);
@@ -5041,8 +5038,6 @@ public class PhoneWindowManager implements WindowManagerPolicy {
final int lidState = mDefaultDisplayPolicy.getLidState();
if (mLidControlsDisplayFold && mDisplayFoldController != null) {
mDisplayFoldController.requestDeviceFolded(lidState == LID_CLOSED);
- } else if (mShouldSwapDisplaysOnLidSwitch) {
- mDisplayManagerInternal.setDeviceFolded(lidState == LID_CLOSED);
} else if (lidState == LID_CLOSED) {
int lidBehavior = getLidBehavior();
switch (lidBehavior) {
diff --git a/services/core/java/com/android/server/rollback/RollbackManagerServiceImpl.java b/services/core/java/com/android/server/rollback/RollbackManagerServiceImpl.java
index 9350edf6d68a..1e89e06617d3 100644
--- a/services/core/java/com/android/server/rollback/RollbackManagerServiceImpl.java
+++ b/services/core/java/com/android/server/rollback/RollbackManagerServiceImpl.java
@@ -28,7 +28,6 @@ import android.content.Intent;
import android.content.IntentFilter;
import android.content.IntentSender;
import android.content.pm.ApplicationInfo;
-import android.content.pm.ModuleInfo;
import android.content.pm.PackageInfo;
import android.content.pm.PackageInstaller;
import android.content.pm.PackageManager;
@@ -1089,8 +1088,8 @@ class RollbackManagerServiceImpl extends IRollbackManager.Stub implements Rollba
Manifest.permission.TEST_MANAGE_ROLLBACKS,
installerPackageName) == PackageManager.PERMISSION_GRANTED;
- // For now only allow rollbacks for modules or for testing.
- return (isRollbackWhitelisted(packageName) && manageRollbacksGranted)
+ // For now only allow rollbacks for allowlisted packages or for testing.
+ return (isRollbackAllowlisted(packageName) && manageRollbacksGranted)
|| testManageRollbacksGranted;
}
@@ -1098,25 +1097,8 @@ class RollbackManagerServiceImpl extends IRollbackManager.Stub implements Rollba
* Returns true is this package is eligible for enabling rollback.
*/
@AnyThread
- private boolean isRollbackWhitelisted(String packageName) {
- // TODO: Remove #isModule when the allowlist is ready.
- return SystemConfig.getInstance().getRollbackWhitelistedPackages().contains(packageName)
- || isModule(packageName);
- }
- /**
- * Returns true if the package name is the name of a module.
- */
- @AnyThread
- private boolean isModule(String packageName) {
- PackageManager pm = mContext.getPackageManager();
- final ModuleInfo moduleInfo;
- try {
- moduleInfo = pm.getModuleInfo(packageName, 0);
- } catch (PackageManager.NameNotFoundException e) {
- return false;
- }
-
- return moduleInfo != null;
+ private boolean isRollbackAllowlisted(String packageName) {
+ return SystemConfig.getInstance().getRollbackWhitelistedPackages().contains(packageName);
}
/**
diff --git a/services/core/java/com/android/server/soundtrigger_middleware/ExternalCaptureStateTracker.java b/services/core/java/com/android/server/soundtrigger_middleware/ExternalCaptureStateTracker.java
index 7977e931c37f..940490411b49 100644
--- a/services/core/java/com/android/server/soundtrigger_middleware/ExternalCaptureStateTracker.java
+++ b/services/core/java/com/android/server/soundtrigger_middleware/ExternalCaptureStateTracker.java
@@ -16,11 +16,6 @@
package com.android.server.soundtrigger_middleware;
-import android.media.ICaptureStateListener;
-import android.os.IBinder;
-import android.os.Parcel;
-import android.os.RemoteException;
-import android.os.ServiceManager;
import android.util.Log;
import java.util.concurrent.Semaphore;
@@ -78,7 +73,11 @@ class ExternalCaptureStateTracker {
* @param active true when external capture is active.
*/
private void setCaptureState(boolean active) {
- mListener.accept(active);
+ try {
+ mListener.accept(active);
+ } catch (Exception e) {
+ Log.e(TAG, "Exception caught while setting capture state", e);
+ }
}
/**
diff --git a/services/core/java/com/android/server/webkit/SystemImpl.java b/services/core/java/com/android/server/webkit/SystemImpl.java
index 201894049b06..68f554cb2758 100644
--- a/services/core/java/com/android/server/webkit/SystemImpl.java
+++ b/services/core/java/com/android/server/webkit/SystemImpl.java
@@ -197,19 +197,6 @@ public class SystemImpl implements SystemInterface {
}
@Override
- public boolean isFallbackLogicEnabled() {
- // Note that this is enabled by default (i.e. if the setting hasn't been set).
- return Settings.Global.getInt(AppGlobals.getInitialApplication().getContentResolver(),
- Settings.Global.WEBVIEW_FALLBACK_LOGIC_ENABLED, 1) == 1;
- }
-
- @Override
- public void enableFallbackLogic(boolean enable) {
- Settings.Global.putInt(AppGlobals.getInitialApplication().getContentResolver(),
- Settings.Global.WEBVIEW_FALLBACK_LOGIC_ENABLED, enable ? 1 : 0);
- }
-
- @Override
public void enablePackageForAllUsers(Context context, String packageName, boolean enable) {
UserManager userManager = (UserManager)context.getSystemService(Context.USER_SERVICE);
for(UserInfo userInfo : userManager.getUsers()) {
diff --git a/services/core/java/com/android/server/webkit/SystemInterface.java b/services/core/java/com/android/server/webkit/SystemInterface.java
index 743740d277ba..09c23a7229ad 100644
--- a/services/core/java/com/android/server/webkit/SystemInterface.java
+++ b/services/core/java/com/android/server/webkit/SystemInterface.java
@@ -41,9 +41,6 @@ public interface SystemInterface {
public void updateUserSetting(Context context, String newProviderName);
public void killPackageDependents(String packageName);
- public boolean isFallbackLogicEnabled();
- public void enableFallbackLogic(boolean enable);
-
public void enablePackageForAllUsers(Context context, String packageName, boolean enable);
public boolean systemIsDebuggable();
diff --git a/services/core/java/com/android/server/webkit/WebViewUpdateServiceImpl.java b/services/core/java/com/android/server/webkit/WebViewUpdateServiceImpl.java
index 11fd7953e08f..55697d39fb99 100644
--- a/services/core/java/com/android/server/webkit/WebViewUpdateServiceImpl.java
+++ b/services/core/java/com/android/server/webkit/WebViewUpdateServiceImpl.java
@@ -43,8 +43,7 @@ import java.io.PrintWriter;
* as the WebView preparation class.
* 2. The SystemServer calls WebViewUpdateService.prepareWebViewInSystemServer. This happens at boot
* and the WebViewUpdateService should not have been accessed before this call. In this call we
- * migrate away from the old fallback logic if necessary and then choose WebView implementation for
- * the first time.
+ * choose WebView implementation for the first time.
* 3. The update service listens for Intents related to package installs and removals. These intents
* are received and processed on the UI thread. Each intent can result in changing WebView
* implementation.
@@ -80,7 +79,6 @@ public class WebViewUpdateServiceImpl {
}
void prepareWebViewInSystemServer() {
- migrateFallbackStateOnBoot();
mWebViewUpdater.prepareWebViewInSystemServer();
if (getCurrentWebViewPackage() == null) {
// We didn't find a valid WebView implementation. Try explicitly re-enabling the
@@ -159,27 +157,6 @@ public class WebViewUpdateServiceImpl {
}
/**
- * If the fallback logic is enabled, re-enable any fallback package for all users, then
- * disable the fallback logic.
- *
- * This migrates away from the old fallback mechanism to the new state where packages are never
- * automatically enableenableisabled.
- */
- private void migrateFallbackStateOnBoot() {
- if (!mSystemInterface.isFallbackLogicEnabled()) return;
-
- WebViewProviderInfo[] webviewProviders = mSystemInterface.getWebViewPackages();
- WebViewProviderInfo fallbackProvider = getFallbackProvider(webviewProviders);
- if (fallbackProvider != null) {
- Slog.i(TAG, "One-time migration: enabling " + fallbackProvider.packageName);
- mSystemInterface.enablePackageForAllUsers(mContext, fallbackProvider.packageName, true);
- } else {
- Slog.i(TAG, "Skipping one-time migration: no fallback provider");
- }
- mSystemInterface.enableFallbackLogic(false);
- }
-
- /**
* Returns the only fallback provider in the set of given packages, or null if there is none.
*/
private static WebViewProviderInfo getFallbackProvider(WebViewProviderInfo[] webviewPackages) {
@@ -217,8 +194,6 @@ public class WebViewUpdateServiceImpl {
*/
void dumpState(PrintWriter pw) {
pw.println("Current WebView Update Service state");
- pw.println(String.format(" Fallback logic enabled: %b",
- mSystemInterface.isFallbackLogicEnabled()));
pw.println(String.format(" Multiprocess enabled: %b", isMultiProcessEnabled()));
mWebViewUpdater.dumpState(pw);
}
diff --git a/services/core/java/com/android/server/wm/ActivityRecord.java b/services/core/java/com/android/server/wm/ActivityRecord.java
index aea944cd52d3..4a7fc7f0c767 100644
--- a/services/core/java/com/android/server/wm/ActivityRecord.java
+++ b/services/core/java/com/android/server/wm/ActivityRecord.java
@@ -621,6 +621,7 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
* 1920x1080, and the actually size on the screen is 960x540, then the scale is 0.5.
*/
private float mSizeCompatScale = 1f;
+
/**
* The bounds in global coordinates for activity in size compatibility mode.
* @see ActivityRecord#hasSizeCompatBounds()
@@ -4761,15 +4762,14 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
supportsEnterPipOnTaskSwitch = false;
break;
case RESUMED:
- // Do nothing if currently in the process of resuming the activity. Otherwise,
- // starting to pause it since it is not visible.
- if (task.mInResumeTopActivity
- && task.topRunningActivity(true /* focusableOnly */) == this) {
+ // If the app is capable of entering PIP, we should try pausing it now
+ // so it can PIP correctly.
+ if (deferHidingClient) {
+ getRootTask().startPausingLocked(
+ mStackSupervisor.mUserLeaving /* userLeaving */,
+ false /* uiSleeping */, null /* resuming */, "makeInvisible");
break;
}
- getRootTask().startPausingLocked(mStackSupervisor.mUserLeaving,
- false /* uiSleeping */, null /* resuming */, "makeInvisible");
- // fall through
case INITIALIZING:
case PAUSING:
case PAUSED:
@@ -6492,6 +6492,7 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
&& !mAtmService.mForceResizableActivities;
}
+ @Override
boolean hasSizeCompatBounds() {
return mSizeCompatBounds != null;
}
@@ -7877,4 +7878,17 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
pictureInPictureArgs.copyOnlySet(p);
getTask().getRootTask().onPictureInPictureParamsChanged();
}
+
+ @Override
+ boolean isSyncFinished() {
+ if (!super.isSyncFinished()) return false;
+ if (!isVisibleRequested()) return true;
+ // If visibleRequested, wait for at-least one visible child.
+ for (int i = mChildren.size() - 1; i >= 0; --i) {
+ if (mChildren.get(i).isVisibleRequested()) {
+ return true;
+ }
+ }
+ return false;
+ }
}
diff --git a/services/core/java/com/android/server/wm/ActivityStackSupervisor.java b/services/core/java/com/android/server/wm/ActivityStackSupervisor.java
index 9ed68b8041db..b4fea904eca5 100644
--- a/services/core/java/com/android/server/wm/ActivityStackSupervisor.java
+++ b/services/core/java/com/android/server/wm/ActivityStackSupervisor.java
@@ -2159,21 +2159,7 @@ public class ActivityStackSupervisor implements RecentTasks.Callbacks {
}
final DisplayContent preferredDisplay = preferredTaskDisplayArea.mDisplayContent;
-
- final boolean singleTaskInstance = preferredDisplay != null
- && preferredDisplay.isSingleTaskInstance();
-
if (preferredDisplay != task.getDisplayContent()) {
- // Suppress the warning toast if the preferredDisplay was set to singleTask.
- // The singleTaskInstance displays will only contain one task and any attempt to
- // launch new task will re-route to the default display.
- if (singleTaskInstance) {
- mService.getTaskChangeNotificationController()
- .notifyActivityLaunchOnSecondaryDisplayRerouted(task.getTaskInfo(),
- preferredDisplay.mDisplayId);
- return;
- }
-
Slog.w(TAG, "Failed to put " + task + " on display " + preferredDisplay.mDisplayId);
// Display a warning toast that we failed to put a task on a secondary display.
mService.getTaskChangeNotificationController()
diff --git a/services/core/java/com/android/server/wm/ActivityTaskManagerInternal.java b/services/core/java/com/android/server/wm/ActivityTaskManagerInternal.java
index 96740128879b..c7d716d8290a 100644
--- a/services/core/java/com/android/server/wm/ActivityTaskManagerInternal.java
+++ b/services/core/java/com/android/server/wm/ActivityTaskManagerInternal.java
@@ -173,13 +173,6 @@ public abstract class ActivityTaskManagerInternal {
public abstract boolean hasResumedActivity(int uid);
/**
- * Notify listeners that contents are drawn for the first time on a single task display.
- *
- * @param displayId An ID of the display on which contents are drawn.
- */
- public abstract void notifySingleTaskDisplayDrawn(int displayId);
-
- /**
* Start activity {@code intents} as if {@code packageName/featureId} on user {@code userId} did
* it.
*
diff --git a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
index 48b0b7d27917..51f7d015e548 100644
--- a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
+++ b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
@@ -2507,13 +2507,6 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub {
if (taskOrgController.handleInterceptBackPressedOnTaskRoot(stack)) {
// This task is handled by a task organizer that has requested the back pressed
// callback
- } else if (stack != null && (stack.isSingleTaskInstance())) {
- // Single-task stacks are used for activities which are presented in floating
- // windows above full screen activities. A task change listener is used to notify
- // SystemUI so the back action can be handled specially.
- final Task task = r.getTask();
- mTaskChangeNotificationController
- .notifyBackPressedOnTaskRoot(task.getTaskInfo());
} else {
moveActivityTaskToBack(token, false /* nonRoot */);
}
@@ -4782,26 +4775,6 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub {
}
/**
- * Makes the display with the given id a single task instance display. I.e the display can only
- * contain one task.
- */
- @Override
- public void setDisplayToSingleTaskInstance(int displayId) {
- mAmInternal.enforceCallingPermission(MANAGE_ACTIVITY_STACKS,
- "setDisplayToSingleTaskInstance");
- final long origId = Binder.clearCallingIdentity();
- try {
- final DisplayContent display =
- mRootWindowContainer.getDisplayContentOrCreate(displayId);
- if (display != null) {
- display.setDisplayToSingleTaskInstance();
- }
- } finally {
- Binder.restoreCallingIdentity(origId);
- }
- }
-
- /**
* Requests that an activity should enter picture-in-picture mode if possible.
*/
@Override
@@ -5136,7 +5109,9 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub {
deferResume);
}
- kept = ensureConfigAndVisibilityAfterUpdate(starting, changes);
+ if (!deferResume) {
+ kept = ensureConfigAndVisibilityAfterUpdate(starting, changes);
+ }
} finally {
continueWindowLayout();
}
@@ -5572,7 +5547,10 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub {
}
void updateTopApp(ActivityRecord topResumedActivity) {
- final ActivityRecord top = topResumedActivity != null ? topResumedActivity
+ // If system is sleeping, use the given record (it should be null) because there won't be
+ // the next resumed activity. Otherwise the process of pausing activity will keep with top
+ // state even the activity has paused and stopped.
+ final ActivityRecord top = mSleeping || topResumedActivity != null ? topResumedActivity
// If there is no resumed activity, it will choose the pausing activity.
: mRootWindowContainer.getTopResumedActivity();
mTopApp = top != null ? top.app : null;
@@ -6030,10 +6008,6 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub {
return allUids.contains(uid);
}
- void notifySingleTaskDisplayEmpty(int displayId) {
- mTaskChangeNotificationController.notifySingleTaskDisplayEmpty(displayId);
- }
-
final class H extends Handler {
static final int REPORT_TIME_TRACKER_MSG = 1;
@@ -6101,11 +6075,6 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub {
}
@Override
- public void notifySingleTaskDisplayDrawn(int displayId) {
- mTaskChangeNotificationController.notifySingleTaskDisplayDrawn(displayId);
- }
-
- @Override
public List<IBinder> getTopVisibleActivities() {
synchronized (mGlobalLock) {
return mRootWindowContainer.getTopVisibleActivities();
diff --git a/services/core/java/com/android/server/wm/AppTransition.java b/services/core/java/com/android/server/wm/AppTransition.java
index 0e47ea8058f1..26c701b99150 100644
--- a/services/core/java/com/android/server/wm/AppTransition.java
+++ b/services/core/java/com/android/server/wm/AppTransition.java
@@ -21,7 +21,6 @@ import static android.view.WindowManager.TRANSIT_ACTIVITY_CLOSE;
import static android.view.WindowManager.TRANSIT_ACTIVITY_OPEN;
import static android.view.WindowManager.TRANSIT_ACTIVITY_RELAUNCH;
import static android.view.WindowManager.TRANSIT_CRASHING_ACTIVITY_CLOSE;
-import static android.view.WindowManager.TRANSIT_DOCK_TASK_FROM_RECENTS;
import static android.view.WindowManager.TRANSIT_FLAG_KEYGUARD_GOING_AWAY_NO_ANIMATION;
import static android.view.WindowManager.TRANSIT_FLAG_KEYGUARD_GOING_AWAY_SUBTLE_ANIMATION;
import static android.view.WindowManager.TRANSIT_FLAG_KEYGUARD_GOING_AWAY_TO_SHADE;
@@ -30,7 +29,6 @@ import static android.view.WindowManager.TRANSIT_KEYGUARD_GOING_AWAY_ON_WALLPAPE
import static android.view.WindowManager.TRANSIT_KEYGUARD_OCCLUDE;
import static android.view.WindowManager.TRANSIT_KEYGUARD_UNOCCLUDE;
import static android.view.WindowManager.TRANSIT_NONE;
-import static android.view.WindowManager.TRANSIT_SHOW_SINGLE_TASK_DISPLAY;
import static android.view.WindowManager.TRANSIT_TASK_CHANGE_WINDOWING_MODE;
import static android.view.WindowManager.TRANSIT_TASK_CLOSE;
import static android.view.WindowManager.TRANSIT_TASK_OPEN;
@@ -92,7 +90,6 @@ import android.content.res.TypedArray;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Color;
-import android.graphics.Path;
import android.graphics.Picture;
import android.graphics.Rect;
import android.graphics.drawable.Drawable;
@@ -134,7 +131,6 @@ import com.android.internal.util.function.pooled.PooledPredicate;
import com.android.server.AttributeCache;
import com.android.server.wm.animation.ClipRectLRAnimation;
import com.android.server.wm.animation.ClipRectTBAnimation;
-import com.android.server.wm.animation.CurvedTranslateAnimation;
import java.io.PrintWriter;
import java.util.ArrayList;
@@ -161,9 +157,6 @@ public class AppTransition implements Dump {
static final Interpolator TOUCH_RESPONSE_INTERPOLATOR =
new PathInterpolator(0.3f, 0f, 0.1f, 1f);
- private static final Interpolator THUMBNAIL_DOCK_INTERPOLATOR =
- new PathInterpolator(0.85f, 0f, 1f, 1f);
-
/**
* Maximum duration for the clip reveal animation. This is used when there is a lot of movement
* involved, to make it more understandable.
@@ -1127,11 +1120,8 @@ public class AppTransition implements Dump {
scale.setInterpolator(interpolator);
scale.setDuration(duration);
Animation alpha = new AlphaAnimation(1f, 0f);
- alpha.setInterpolator(mNextAppTransition == TRANSIT_DOCK_TASK_FROM_RECENTS
- ? THUMBNAIL_DOCK_INTERPOLATOR : mThumbnailFadeOutInterpolator);
- alpha.setDuration(mNextAppTransition == TRANSIT_DOCK_TASK_FROM_RECENTS
- ? duration / 2
- : duration);
+ alpha.setInterpolator(mThumbnailFadeOutInterpolator);
+ alpha.setDuration(duration);
Animation translate = createCurvedMotion(fromX, toX, fromY, toY);
translate.setInterpolator(interpolator);
translate.setDuration(duration);
@@ -1194,44 +1184,15 @@ public class AppTransition implements Dump {
}
private Animation createCurvedMotion(float fromX, float toX, float fromY, float toY) {
-
- // Almost no x-change - use linear animation
- if (Math.abs(toX - fromX) < 1f || mNextAppTransition != TRANSIT_DOCK_TASK_FROM_RECENTS) {
- return new TranslateAnimation(fromX, toX, fromY, toY);
- } else {
- final Path path = createCurvedPath(fromX, toX, fromY, toY);
- return new CurvedTranslateAnimation(path);
- }
- }
-
- private Path createCurvedPath(float fromX, float toX, float fromY, float toY) {
- final Path path = new Path();
- path.moveTo(fromX, fromY);
-
- if (fromY > toY) {
- // If the object needs to go up, move it in horizontal direction first, then vertical.
- path.cubicTo(fromX, fromY, toX, 0.9f * fromY + 0.1f * toY, toX, toY);
- } else {
- // If the object needs to go down, move it in vertical direction first, then horizontal.
- path.cubicTo(fromX, fromY, fromX, 0.1f * fromY + 0.9f * toY, toX, toY);
- }
- return path;
+ return new TranslateAnimation(fromX, toX, fromY, toY);
}
private long getAspectScaleDuration() {
- if (mNextAppTransition == TRANSIT_DOCK_TASK_FROM_RECENTS) {
- return (long) (THUMBNAIL_APP_TRANSITION_DURATION * 1.35f);
- } else {
- return THUMBNAIL_APP_TRANSITION_DURATION;
- }
+ return THUMBNAIL_APP_TRANSITION_DURATION;
}
private Interpolator getAspectScaleInterpolator() {
- if (mNextAppTransition == TRANSIT_DOCK_TASK_FROM_RECENTS) {
- return mFastOutSlowInInterpolator;
- } else {
- return TOUCH_RESPONSE_INTERPOLATOR;
- }
+ return TOUCH_RESPONSE_INTERPOLATOR;
}
/**
@@ -1734,7 +1695,6 @@ public class AppTransition implements Dump {
? WindowAnimation_activityCloseEnterAnimation
: WindowAnimation_activityCloseExitAnimation;
break;
- case TRANSIT_DOCK_TASK_FROM_RECENTS:
case TRANSIT_TASK_OPEN:
animAttr = enter
? WindowAnimation_taskOpenEnterAnimation
@@ -1805,7 +1765,6 @@ public class AppTransition implements Dump {
int getAppStackClipMode() {
return mNextAppTransition == TRANSIT_ACTIVITY_RELAUNCH
- || mNextAppTransition == TRANSIT_DOCK_TASK_FROM_RECENTS
|| mNextAppTransitionType == NEXT_TRANSIT_TYPE_CLIP_REVEAL
|| mNextAppTransition == TRANSIT_KEYGUARD_GOING_AWAY
|| mNextAppTransition == TRANSIT_KEYGUARD_GOING_AWAY_ON_WALLPAPER
@@ -2059,9 +2018,6 @@ public class AppTransition implements Dump {
case TRANSIT_ACTIVITY_RELAUNCH: {
return "TRANSIT_ACTIVITY_RELAUNCH";
}
- case TRANSIT_DOCK_TASK_FROM_RECENTS: {
- return "TRANSIT_DOCK_TASK_FROM_RECENTS";
- }
case TRANSIT_KEYGUARD_GOING_AWAY: {
return "TRANSIT_KEYGUARD_GOING_AWAY";
}
@@ -2083,9 +2039,6 @@ public class AppTransition implements Dump {
case TRANSIT_CRASHING_ACTIVITY_CLOSE: {
return "TRANSIT_CRASHING_ACTIVITY_CLOSE";
}
- case TRANSIT_SHOW_SINGLE_TASK_DISPLAY: {
- return "TRANSIT_SHOW_SINGLE_TASK_DISPLAY";
- }
default: {
return "<UNKNOWN: " + transition + ">";
}
diff --git a/services/core/java/com/android/server/wm/AppTransitionController.java b/services/core/java/com/android/server/wm/AppTransitionController.java
index 57d51c51c12b..14eedf786f4c 100644
--- a/services/core/java/com/android/server/wm/AppTransitionController.java
+++ b/services/core/java/com/android/server/wm/AppTransitionController.java
@@ -21,7 +21,6 @@ import static android.view.WindowManager.TRANSIT_ACTIVITY_CLOSE;
import static android.view.WindowManager.TRANSIT_ACTIVITY_OPEN;
import static android.view.WindowManager.TRANSIT_ACTIVITY_RELAUNCH;
import static android.view.WindowManager.TRANSIT_CRASHING_ACTIVITY_CLOSE;
-import static android.view.WindowManager.TRANSIT_DOCK_TASK_FROM_RECENTS;
import static android.view.WindowManager.TRANSIT_FLAG_KEYGUARD_GOING_AWAY_NO_ANIMATION;
import static android.view.WindowManager.TRANSIT_FLAG_KEYGUARD_GOING_AWAY_SUBTLE_ANIMATION;
import static android.view.WindowManager.TRANSIT_FLAG_KEYGUARD_GOING_AWAY_TO_SHADE;
@@ -29,7 +28,6 @@ import static android.view.WindowManager.TRANSIT_FLAG_KEYGUARD_GOING_AWAY_WITH_W
import static android.view.WindowManager.TRANSIT_KEYGUARD_GOING_AWAY;
import static android.view.WindowManager.TRANSIT_KEYGUARD_GOING_AWAY_ON_WALLPAPER;
import static android.view.WindowManager.TRANSIT_NONE;
-import static android.view.WindowManager.TRANSIT_SHOW_SINGLE_TASK_DISPLAY;
import static android.view.WindowManager.TRANSIT_TASK_CLOSE;
import static android.view.WindowManager.TRANSIT_TASK_OPEN;
import static android.view.WindowManager.TRANSIT_TASK_TO_BACK;
@@ -216,12 +214,6 @@ public class AppTransitionController {
mService.mAtmService.mStackSupervisor.getActivityMetricsLogger().notifyTransitionStarting(
mTempTransitionReasons);
- if (transit == TRANSIT_SHOW_SINGLE_TASK_DISPLAY) {
- mService.mAnimator.addAfterPrepareSurfacesRunnable(() -> {
- mService.mAtmInternal.notifySingleTaskDisplayDrawn(mDisplayContent.getDisplayId());
- });
- }
-
Trace.traceEnd(Trace.TRACE_TAG_WINDOW_MANAGER);
mDisplayContent.pendingLayoutChanges |=
@@ -701,11 +693,9 @@ public class AppTransitionController {
boolean openingAppHasWallpaper, boolean closingAppHasWallpaper) {
// Given no app transition pass it through instead of a wallpaper transition.
// Never convert the crashing transition.
- // Never update the transition for the wallpaper if we are just docking from recents
// Never convert a change transition since the top activity isn't changing and will likely
// still be above an opening wallpaper.
if (transit == TRANSIT_NONE || transit == TRANSIT_CRASHING_ACTIVITY_CLOSE
- || transit == TRANSIT_DOCK_TASK_FROM_RECENTS
|| AppTransition.isChangeTransit(transit)) {
return transit;
}
diff --git a/services/core/java/com/android/server/wm/BLASTSyncEngine.java b/services/core/java/com/android/server/wm/BLASTSyncEngine.java
index 958a7a8f07f8..301783c155e1 100644
--- a/services/core/java/com/android/server/wm/BLASTSyncEngine.java
+++ b/services/core/java/com/android/server/wm/BLASTSyncEngine.java
@@ -18,13 +18,13 @@ package com.android.server.wm;
import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_SYNC_ENGINE;
-import android.util.ArrayMap;
+import android.annotation.NonNull;
import android.util.ArraySet;
+import android.util.SparseArray;
+import android.view.SurfaceControl;
import com.android.internal.protolog.common.ProtoLog;
-import java.util.Set;
-
/**
* Utility class for collecting WindowContainers that will merge transactions.
* For example to use to synchronously resize all the children of a window container
@@ -45,94 +45,122 @@ import java.util.Set;
* 5. If there were no sub windows anywhere in the hierarchy to wait on, then
* transactionReady is immediately invoked, otherwise all the windows are poked
* to redraw and to deliver a buffer to {@link WindowState#finishDrawing}.
- * Once all this drawing is complete the WindowContainer that's ready will be added to the
- * set of ready WindowContainers. When the final onTransactionReady is called, it will merge
- * the transactions of the all the WindowContainers and will be delivered to the
- * TransactionReadyListener
+ * Once all this drawing is complete, all the transactions will be merged and delivered
+ * to TransactionReadyListener.
+ *
+ * This works primarily by setting-up state and then watching/waiting for the registered subtrees
+ * to enter into a "finished" state (either by receiving drawn content or by disappearing). This
+ * checks the subtrees during surface-placement.
*/
class BLASTSyncEngine {
private static final String TAG = "BLASTSyncEngine";
interface TransactionReadyListener {
- void onTransactionReady(int mSyncId, Set<WindowContainer> windowContainersReady);
- };
-
- // Holds state associated with a single synchronous set of operations.
- class SyncState implements TransactionReadyListener {
- int mSyncId;
- int mRemainingTransactions;
- TransactionReadyListener mListener;
+ void onTransactionReady(int mSyncId, SurfaceControl.Transaction transaction);
+ }
+
+ /**
+ * Holds state associated with a single synchronous set of operations.
+ */
+ class SyncGroup {
+ final int mSyncId;
+ final TransactionReadyListener mListener;
boolean mReady = false;
- Set<WindowContainer> mWindowContainersReady = new ArraySet<>();
-
- private void tryFinish() {
- if (mRemainingTransactions == 0 && mReady) {
- ProtoLog.v(WM_DEBUG_SYNC_ENGINE, "SyncSet{%x:%d} Finished. Reporting %d "
- + "containers to %s", BLASTSyncEngine.this.hashCode(), mSyncId,
- mWindowContainersReady.size(), mListener);
- mListener.onTransactionReady(mSyncId, mWindowContainersReady);
- mPendingSyncs.remove(mSyncId);
+ final ArraySet<WindowContainer> mRootMembers = new ArraySet<>();
+ private SurfaceControl.Transaction mOrphanTransaction = null;
+
+ private SyncGroup(TransactionReadyListener listener, int id) {
+ mSyncId = id;
+ mListener = listener;
+ }
+
+ /**
+ * Gets a transaction to dump orphaned operations into. Orphaned operations are operations
+ * that were on the mSyncTransactions of "root" subtrees which have been removed during the
+ * sync period.
+ */
+ @NonNull
+ SurfaceControl.Transaction getOrphanTransaction() {
+ if (mOrphanTransaction == null) {
+ // Lazy since this isn't common
+ mOrphanTransaction = mWm.mTransactionFactory.get();
}
+ return mOrphanTransaction;
}
- public void onTransactionReady(int syncId, Set<WindowContainer> windowContainersReady) {
- mRemainingTransactions--;
- ProtoLog.v(WM_DEBUG_SYNC_ENGINE, "SyncSet{%x:%d} Child ready, now ready=%b"
- + " and waiting on %d transactions", BLASTSyncEngine.this.hashCode(), mSyncId,
- mReady, mRemainingTransactions);
- mWindowContainersReady.addAll(windowContainersReady);
- tryFinish();
+ private void onSurfacePlacement() {
+ if (!mReady) return;
+ ProtoLog.v(WM_DEBUG_SYNC_ENGINE, "SyncGroup %d: onSurfacePlacement checking %s",
+ mSyncId, mRootMembers);
+ for (int i = mRootMembers.size() - 1; i >= 0; --i) {
+ final WindowContainer wc = mRootMembers.valueAt(i);
+ if (!wc.isSyncFinished()) {
+ ProtoLog.v(WM_DEBUG_SYNC_ENGINE, "SyncGroup %d: Unfinished container: %s",
+ mSyncId, wc);
+ return;
+ }
+ }
+ ProtoLog.v(WM_DEBUG_SYNC_ENGINE, "SyncGroup %d: Finished!", mSyncId);
+ SurfaceControl.Transaction merged = mWm.mTransactionFactory.get();
+ if (mOrphanTransaction != null) {
+ merged.merge(mOrphanTransaction);
+ }
+ for (WindowContainer wc : mRootMembers) {
+ wc.finishSync(merged, false /* cancel */);
+ }
+ mListener.onTransactionReady(mSyncId, merged);
+ mActiveSyncs.remove(mSyncId);
}
- void setReady() {
- ProtoLog.v(WM_DEBUG_SYNC_ENGINE, "SyncSet{%x:%d} Set ready",
- BLASTSyncEngine.this.hashCode(), mSyncId);
+ private void setReady() {
+ ProtoLog.v(WM_DEBUG_SYNC_ENGINE, "SyncGroup %d: Set ready", mSyncId);
mReady = true;
- tryFinish();
+ mWm.mWindowPlacerLocked.requestTraversal();
}
- boolean addToSync(WindowContainer wc) {
- ProtoLog.v(WM_DEBUG_SYNC_ENGINE, "SyncSet{%x:%d} Trying to add %s",
- BLASTSyncEngine.this.hashCode(), mSyncId, wc);
- if (wc.prepareForSync(this, mSyncId)) {
- mRemainingTransactions++;
- ProtoLog.v(WM_DEBUG_SYNC_ENGINE, "SyncSet{%x:%d} Added %s. now waiting "
- + "on %d transactions", BLASTSyncEngine.this.hashCode(), mSyncId, wc,
- mRemainingTransactions);
- return true;
+ private void addToSync(WindowContainer wc) {
+ if (!mRootMembers.add(wc)) {
+ return;
}
- return false;
+ ProtoLog.v(WM_DEBUG_SYNC_ENGINE, "SyncGroup %d: Adding to group: %s", mSyncId, wc);
+ wc.setSyncGroup(this);
+ wc.prepareSync();
+ mWm.mWindowPlacerLocked.requestTraversal();
}
- SyncState(TransactionReadyListener l, int id) {
- mListener = l;
- mSyncId = id;
- mRemainingTransactions = 0;
+ void onCancelSync(WindowContainer wc) {
+ mRootMembers.remove(wc);
}
- };
+ }
+ private final WindowManagerService mWm;
private int mNextSyncId = 0;
+ private final SparseArray<SyncGroup> mActiveSyncs = new SparseArray<>();
- private final ArrayMap<Integer, SyncState> mPendingSyncs = new ArrayMap<>();
-
- BLASTSyncEngine() {
+ BLASTSyncEngine(WindowManagerService wms) {
+ mWm = wms;
}
int startSyncSet(TransactionReadyListener listener) {
final int id = mNextSyncId++;
- final SyncState s = new SyncState(listener, id);
- mPendingSyncs.put(id, s);
- ProtoLog.v(WM_DEBUG_SYNC_ENGINE, "SyncSet{%x:%d} Start for %s", hashCode(), id, listener);
+ final SyncGroup s = new SyncGroup(listener, id);
+ mActiveSyncs.put(id, s);
+ ProtoLog.v(WM_DEBUG_SYNC_ENGINE, "SyncGroup %d: Started for listener: %s", id, listener);
return id;
}
- boolean addToSyncSet(int id, WindowContainer wc) {
- final SyncState st = mPendingSyncs.get(id);
- return st.addToSync(wc);
+ void addToSyncSet(int id, WindowContainer wc) {
+ mActiveSyncs.get(id).addToSync(wc);
}
void setReady(int id) {
- final SyncState st = mPendingSyncs.get(id);
- st.setReady();
+ mActiveSyncs.get(id).setReady();
+ }
+
+ void onSurfacePlacement() {
+ // backwards since each state can remove itself if finished
+ for (int i = mActiveSyncs.size() - 1; i >= 0; --i) {
+ mActiveSyncs.valueAt(i).onSurfacePlacement();
+ }
}
}
diff --git a/services/core/java/com/android/server/wm/DisplayContent.java b/services/core/java/com/android/server/wm/DisplayContent.java
index 4a30ca96abb6..2de28beaad58 100644
--- a/services/core/java/com/android/server/wm/DisplayContent.java
+++ b/services/core/java/com/android/server/wm/DisplayContent.java
@@ -605,9 +605,6 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp
*/
private boolean mRemoved;
- /** The display can only contain one task. */
- boolean mSingleTaskInstance;
-
/**
* Non-null if the last size compatibility mode activity is using non-native screen
* configuration. The activity is not able to put in multi-window mode, so it exists only one
@@ -2890,7 +2887,6 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp
mClosingApps.valueAt(i).writeIdentifierToProto(proto, CLOSING_APPS);
}
- proto.write(SINGLE_TASK_INSTANCE, mSingleTaskInstance);
final Task focusedStack = getFocusedStack();
if (focusedStack != null) {
proto.write(FOCUSED_ROOT_TASK_ID, focusedStack.getRootTaskId());
@@ -2935,8 +2931,7 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp
public void dump(PrintWriter pw, String prefix, boolean dumpAll) {
super.dump(pw, prefix, dumpAll);
pw.print(prefix);
- pw.println("Display: mDisplayId=" + mDisplayId + " stacks=" + getStackCount() + (
- mSingleTaskInstance ? " mSingleTaskInstance" : ""));
+ pw.println("Display: mDisplayId=" + mDisplayId + " stacks=" + getStackCount());
final String subPrefix = " " + prefix;
pw.print(subPrefix); pw.print("init="); pw.print(mInitialDisplayWidth); pw.print("x");
pw.print(mInitialDisplayHeight); pw.print(" "); pw.print(mInitialDisplayDensity);
@@ -5077,7 +5072,9 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp
}
}
- kept = mAtmService.ensureConfigAndVisibilityAfterUpdate(starting, changes);
+ if (!deferResume) {
+ kept = mAtmService.ensureConfigAndVisibilityAfterUpdate(starting, changes);
+ }
} finally {
mAtmService.continueWindowLayout();
}
@@ -5303,29 +5300,6 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp
mSleeping = asleep;
}
- void setDisplayToSingleTaskInstance() {
- int tdaCount = reduceOnAllTaskDisplayAreas((taskDisplayArea, count) -> ++count,
- 0 /* initValue */);
- if (tdaCount > 1) {
- throw new IllegalArgumentException(
- "Display already has multiple task display areas. display=" + this);
- }
- final int stackCount = getDefaultTaskDisplayArea().getStackCount();
- if (stackCount > 1) {
- throw new IllegalArgumentException("Display already has multiple stacks. display="
- + this);
- }
- if (stackCount > 0) {
- final Task stack = getDefaultTaskDisplayArea().getStackAt(0);
- if (stack.getChildCount() > 1) {
- throw new IllegalArgumentException("Display stack already has multiple tasks."
- + " display=" + this + " stack=" + stack);
- }
- }
-
- mSingleTaskInstance = true;
- }
-
/**
* Check if the display has {@link Display#FLAG_CAN_SHOW_WITH_INSECURE_KEYGUARD} applied.
*/
@@ -5334,11 +5308,6 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp
return (flags & FLAG_CAN_SHOW_WITH_INSECURE_KEYGUARD) != 0;
}
- /** Returns true if the display can only contain one task */
- boolean isSingleTaskInstance() {
- return mSingleTaskInstance;
- }
-
@VisibleForTesting
void removeAllTasks() {
forAllTasks((t) -> { t.getRootTask().removeChild(t, "removeAllTasks"); });
diff --git a/services/core/java/com/android/server/wm/DisplayPolicy.java b/services/core/java/com/android/server/wm/DisplayPolicy.java
index 0801f68681ab..b0ddb61d34bd 100644
--- a/services/core/java/com/android/server/wm/DisplayPolicy.java
+++ b/services/core/java/com/android/server/wm/DisplayPolicy.java
@@ -188,7 +188,6 @@ import com.android.server.policy.WindowOrientationListener;
import com.android.server.statusbar.StatusBarManagerInternal;
import com.android.server.wallpaper.WallpaperManagerInternal;
import com.android.server.wm.InputMonitor.EventReceiverInputConsumer;
-import com.android.server.wm.utils.InsetUtils;
import java.io.PrintWriter;
import java.util.function.Consumer;
@@ -1439,25 +1438,15 @@ public class DisplayPolicy {
* @param attrs The LayoutParams of the window.
* @param windowToken The token of the window.
* @param outFrame The frame of the window.
- * @param outContentInsets The areas covered by system windows, expressed as positive insets.
- * @param outStableInsets The areas covered by stable system windows irrespective of their
- * current visibility. Expressed as positive insets.
* @param outDisplayCutout The area that has been cut away from the display.
+ * @param outInsetsState The insets state of this display from the client's perspective.
+ * @param localClient Whether the client is from the our process.
* @return Whether to always consume the system bars.
* See {@link #areSystemBarsForcedShownLw(WindowState)}.
*/
boolean getLayoutHint(LayoutParams attrs, WindowToken windowToken, Rect outFrame,
- Rect outContentInsets, Rect outStableInsets,
- DisplayCutout.ParcelableWrapper outDisplayCutout) {
- final int fl = attrs.flags;
- final int pfl = attrs.privateFlags;
- final int sysUiVis = attrs.systemUiVisibility | attrs.subtreeSystemUiVisibility;
-
- final boolean layoutInScreen = (fl & FLAG_LAYOUT_IN_SCREEN) != 0;
- final boolean layoutInScreenAndInsetDecor = layoutInScreen
- && (fl & FLAG_LAYOUT_INSET_DECOR) != 0;
- final boolean screenDecor = (pfl & PRIVATE_FLAG_IS_SCREEN_DECOR) != 0;
-
+ DisplayCutout.ParcelableWrapper outDisplayCutout, InsetsState outInsetsState,
+ boolean localClient) {
final boolean isFixedRotationTransforming =
windowToken != null && windowToken.isFixedRotationTransforming();
final ActivityRecord activity = windowToken != null ? windowToken.asActivityRecord() : null;
@@ -1466,56 +1455,36 @@ public class DisplayPolicy {
// Use token (activity) bounds if it is rotated because its task is not rotated.
? windowToken.getBounds()
: (task != null ? task.getBounds() : null);
+ final InsetsState state =
+ mDisplayContent.getInsetsPolicy().getInsetsForWindowMetrics(attrs);
+ computeWindowBounds(attrs, state, outFrame);
+ if (taskBounds != null) {
+ outFrame.intersect(taskBounds);
+ }
+
+ final int fl = attrs.flags;
+ final int pfl = attrs.privateFlags;
+ final boolean layoutInScreenAndInsetDecor = (fl & FLAG_LAYOUT_IN_SCREEN) != 0
+ && (fl & FLAG_LAYOUT_INSET_DECOR) != 0;
+ final boolean screenDecor = (pfl & PRIVATE_FLAG_IS_SCREEN_DECOR) != 0;
final DisplayFrames displayFrames = isFixedRotationTransforming
? windowToken.getFixedRotationTransformDisplayFrames()
: mDisplayContent.mDisplayFrames;
-
if (layoutInScreenAndInsetDecor && !screenDecor) {
- if ((attrs.flags & FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS) != 0
- || (attrs.getFitInsetsTypes() & Type.navigationBars()) == 0) {
- outFrame.set(displayFrames.mUnrestricted);
- } else {
- outFrame.set(displayFrames.mRestricted);
- }
-
- final boolean isFloatingTask = task != null && task.isFloating();
- final Rect sf = isFloatingTask ? null : displayFrames.mStable;
- final Rect cf;
- if (isFloatingTask) {
- cf = null;
- } else if ((sysUiVis & View.SYSTEM_UI_FLAG_LAYOUT_STABLE) != 0) {
- if ((fl & FLAG_FULLSCREEN) != 0) {
- cf = displayFrames.mStableFullscreen;
- } else {
- cf = displayFrames.mStable;
- }
- } else if ((fl & FLAG_FULLSCREEN) != 0) {
- cf = displayFrames.mUnrestricted;
- } else {
- cf = displayFrames.mCurrent;
- }
-
- if (taskBounds != null) {
- outFrame.intersect(taskBounds);
- }
- InsetUtils.insetsBetweenFrames(outFrame, cf, outContentInsets);
- InsetUtils.insetsBetweenFrames(outFrame, sf, outStableInsets);
- outDisplayCutout.set(displayFrames.mDisplayCutout.calculateRelativeTo(outFrame)
- .getDisplayCutout());
+ outDisplayCutout.set(
+ displayFrames.mDisplayCutout.calculateRelativeTo(outFrame).getDisplayCutout());
} else {
- if (layoutInScreen) {
- outFrame.set(displayFrames.mUnrestricted);
- } else {
- outFrame.set(displayFrames.mStable);
- }
- if (taskBounds != null) {
- outFrame.intersect(taskBounds);
- }
-
- outContentInsets.setEmpty();
- outStableInsets.setEmpty();
outDisplayCutout.set(DisplayCutout.NO_CUTOUT);
}
+
+ final boolean inSizeCompatMode = WindowState.inSizeCompatMode(attrs, windowToken);
+ outInsetsState.set(state, inSizeCompatMode || localClient);
+ if (inSizeCompatMode) {
+ final float compatScale = windowToken != null
+ ? windowToken.getSizeCompatScale()
+ : mDisplayContent.mCompatibleScreenScale;
+ outInsetsState.scale(1f / compatScale);
+ }
return mForceShowSystemBars;
}
@@ -1616,8 +1585,9 @@ public class DisplayPolicy {
*/
public void beginLayoutLw(DisplayFrames displayFrames, int uiMode) {
displayFrames.onBeginLayout();
- updateInsetsStateForDisplayCutout(displayFrames,
- mDisplayContent.getInsetsStateController().getRawInsetsState());
+ final InsetsState state = mDisplayContent.getInsetsStateController().getRawInsetsState();
+ updateInsetsStateForDisplayCutout(displayFrames, state);
+ state.setDisplayFrame(displayFrames.mUnrestricted);
mSystemGestures.screenWidth = displayFrames.mUnrestricted.width();
mSystemGestures.screenHeight = displayFrames.mUnrestricted.height();
@@ -1981,6 +1951,28 @@ public class DisplayPolicy {
return !notFocusableForIm;
}
+ private void computeWindowBounds(WindowManager.LayoutParams attrs, InsetsState state,
+ Rect outBounds) {
+ final @InsetsType int typesToFit = attrs.getFitInsetsTypes();
+ final @InsetsSide int sidesToFit = attrs.getFitInsetsSides();
+ final ArraySet<Integer> types = InsetsState.toInternalType(typesToFit);
+ final Rect dfu = state.getDisplayFrame();
+ Insets insets = Insets.of(0, 0, 0, 0);
+ for (int i = types.size() - 1; i >= 0; i--) {
+ final InsetsSource source = state.peekSource(types.valueAt(i));
+ if (source == null) {
+ continue;
+ }
+ insets = Insets.max(insets, source.calculateInsets(
+ dfu, attrs.isFitInsetsIgnoringVisibility()));
+ }
+ final int left = (sidesToFit & Side.LEFT) != 0 ? insets.left : 0;
+ final int top = (sidesToFit & Side.TOP) != 0 ? insets.top : 0;
+ final int right = (sidesToFit & Side.RIGHT) != 0 ? insets.right : 0;
+ final int bottom = (sidesToFit & Side.BOTTOM) != 0 ? insets.bottom : 0;
+ outBounds.set(dfu.left + left, dfu.top + top, dfu.right - right, dfu.bottom - bottom);
+ }
+
/**
* Called for each window attached to the window manager as layout is proceeding. The
* implementation of this function must take care of setting the window's frame, either here or
@@ -2027,31 +2019,12 @@ public class DisplayPolicy {
sf.set(displayFrames.mStable);
- final @InsetsType int typesToFit = attrs.getFitInsetsTypes();
- final @InsetsSide int sidesToFit = attrs.getFitInsetsSides();
- final ArraySet<Integer> types = InsetsState.toInternalType(typesToFit);
- getRotatedWindowBounds(displayFrames, win, sTmpRect);
- final Rect dfu = sTmpRect;
- Insets insets = Insets.of(0, 0, 0, 0);
- for (int i = types.size() - 1; i >= 0; i--) {
- final InsetsSource source = mDisplayContent.getInsetsPolicy()
- .getInsetsForDispatch(win).peekSource(types.valueAt(i));
- if (source == null) {
- continue;
- }
- insets = Insets.max(insets, source.calculateInsets(
- dfu, attrs.isFitInsetsIgnoringVisibility()));
- }
- final int left = (sidesToFit & Side.LEFT) != 0 ? insets.left : 0;
- final int top = (sidesToFit & Side.TOP) != 0 ? insets.top : 0;
- final int right = (sidesToFit & Side.RIGHT) != 0 ? insets.right : 0;
- final int bottom = (sidesToFit & Side.BOTTOM) != 0 ? insets.bottom : 0;
- df.set(dfu.left + left, dfu.top + top, dfu.right - right, dfu.bottom - bottom);
+ final InsetsState state = mDisplayContent.getInsetsPolicy().getInsetsForWindow(win);
+ computeWindowBounds(attrs, state, df);
if (attached == null) {
pf.set(df);
if ((pfl & PRIVATE_FLAG_INSET_PARENT_FRAME_BY_IME) != 0) {
- final InsetsSource source = mDisplayContent.getInsetsPolicy()
- .getInsetsForDispatch(win).peekSource(ITYPE_IME);
+ final InsetsSource source = state.peekSource(ITYPE_IME);
if (source != null) {
pf.inset(source.calculateInsets(pf, false /* ignoreVisibility */));
}
@@ -2126,6 +2099,7 @@ public class DisplayPolicy {
// They will later be cropped or shifted using the displayFrame in WindowState,
// which prevents overlap with the DisplayCutout.
if (!attachedInParent && !floatingInScreenWindow) {
+ getRotatedWindowBounds(displayFrames, win, sTmpRect);
sTmpRect.set(pf);
pf.intersectUnchecked(displayCutoutSafeExceptMaybeBars);
windowFrames.setParentFrameWasClippedByDisplayCutout(!sTmpRect.equals(pf));
diff --git a/services/core/java/com/android/server/wm/InsetsPolicy.java b/services/core/java/com/android/server/wm/InsetsPolicy.java
index bd05da9fe50a..a2b9cf9c5b3c 100644
--- a/services/core/java/com/android/server/wm/InsetsPolicy.java
+++ b/services/core/java/com/android/server/wm/InsetsPolicy.java
@@ -28,6 +28,7 @@ import static android.view.SyncRtSurfaceTransactionApplier.applyParams;
import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_FORCE_SHOW_STATUS_BAR;
import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_STATUS_FORCE_SHOW_NAVIGATION;
+import android.annotation.NonNull;
import android.annotation.Nullable;
import android.app.StatusBarManager;
import android.util.IntArray;
@@ -202,10 +203,22 @@ class InsetsPolicy {
}
/**
- * @see InsetsStateController#getInsetsForDispatch
+ * @see InsetsStateController#getInsetsForWindow
*/
- InsetsState getInsetsForDispatch(WindowState target) {
- final InsetsState originalState = mStateController.getInsetsForDispatch(target);
+ InsetsState getInsetsForWindow(WindowState target) {
+ final InsetsState originalState = mStateController.getInsetsForWindow(target);
+ return adjustVisibilityForTransientTypes(originalState);
+ }
+
+ /**
+ * @see InsetsStateController#getInsetsForWindowMetrics
+ */
+ InsetsState getInsetsForWindowMetrics(@NonNull WindowManager.LayoutParams attrs) {
+ final InsetsState originalState = mStateController.getInsetsForWindowMetrics(attrs);
+ return adjustVisibilityForTransientTypes(originalState);
+ }
+
+ private InsetsState adjustVisibilityForTransientTypes(InsetsState originalState) {
InsetsState state = originalState;
for (int i = mShowingTransientTypes.size() - 1; i >= 0; i--) {
final @InternalInsetsType int type = mShowingTransientTypes.get(i);
@@ -481,7 +494,7 @@ class InsetsPolicy {
mFocusedWin.getDisplayContent().getBounds(), mFocusedWin.getInsetsState(),
mListener, typesReady, this, mListener.getDurationMs(),
InsetsController.SYSTEM_BARS_INTERPOLATOR,
- show ? ANIMATION_TYPE_SHOW : ANIMATION_TYPE_HIDE);
+ show ? ANIMATION_TYPE_SHOW : ANIMATION_TYPE_HIDE, null /* translator */);
SurfaceAnimationThread.getHandler().post(
() -> mListener.onReady(mAnimationControl, typesReady));
}
diff --git a/services/core/java/com/android/server/wm/InsetsStateController.java b/services/core/java/com/android/server/wm/InsetsStateController.java
index b9c2093fe435..e7f140f989cc 100644
--- a/services/core/java/com/android/server/wm/InsetsStateController.java
+++ b/services/core/java/com/android/server/wm/InsetsStateController.java
@@ -97,14 +97,16 @@ class InsetsStateController {
}
/**
- * When dispatching window state to the client, we'll need to exclude the source that represents
- * the window that is being dispatched. We also need to exclude certain types of insets source
- * for client within specific windowing modes.
+ * Gets the insets state from the perspective of the target. When performing layout of the
+ * target or dispatching insets to the target, we need to exclude sources which should not be
+ * visible to the target. e.g., the source which represents the target window itself, and the
+ * IME source when the target is above IME. We also need to exclude certain types of insets
+ * source for client within specific windowing modes.
*
- * @param target The client we dispatch the state to.
+ * @param target The window associate with the perspective.
* @return The state stripped of the necessary information.
*/
- InsetsState getInsetsForDispatch(@NonNull WindowState target) {
+ InsetsState getInsetsForWindow(@NonNull WindowState target) {
final InsetsState rotatedState = target.mToken.getFixedRotationTransformInsetsState();
if (rotatedState != null) {
return rotatedState;
@@ -112,17 +114,23 @@ class InsetsStateController {
final InsetsSourceProvider provider = target.getControllableInsetProvider();
final @InternalInsetsType int type = provider != null
? provider.getSource().getType() : ITYPE_INVALID;
- return getInsetsForDispatchInner(type, target.getWindowingMode(), target.isAlwaysOnTop(),
+ return getInsetsForTarget(type, target.getWindowingMode(), target.isAlwaysOnTop(),
isAboveIme(target));
}
InsetsState getInsetsForWindowMetrics(@NonNull WindowManager.LayoutParams attrs) {
final @InternalInsetsType int type = getInsetsTypeForLayoutParams(attrs);
final WindowToken token = mDisplayContent.getWindowToken(attrs.token);
+ if (token != null) {
+ final InsetsState rotatedState = token.getFixedRotationTransformInsetsState();
+ if (rotatedState != null) {
+ return rotatedState;
+ }
+ }
final @WindowingMode int windowingMode = token != null
? token.getWindowingMode() : WINDOWING_MODE_UNDEFINED;
final boolean alwaysOnTop = token != null && token.isAlwaysOnTop();
- return getInsetsForDispatchInner(type, windowingMode, alwaysOnTop, isAboveIme(token));
+ return getInsetsForTarget(type, windowingMode, alwaysOnTop, isAboveIme(token));
}
private boolean isAboveIme(WindowContainer target) {
@@ -165,8 +173,11 @@ class InsetsStateController {
return ITYPE_INVALID;
}
- /** @see #getInsetsForDispatch */
- private InsetsState getInsetsForDispatchInner(@InternalInsetsType int type,
+ /**
+ * @see #getInsetsForWindow
+ * @see #getInsetsForWindowMetrics
+ */
+ private InsetsState getInsetsForTarget(@InternalInsetsType int type,
@WindowingMode int windowingMode, boolean isAlwaysOnTop, boolean aboveIme) {
InsetsState state = mState;
@@ -270,7 +281,6 @@ class InsetsStateController {
* Called when a layout pass has occurred.
*/
void onPostLayout() {
- mState.setDisplayFrame(mDisplayContent.getBounds());
for (int i = mProviders.size() - 1; i >= 0; i--) {
mProviders.valueAt(i).onPostLayout();
}
diff --git a/services/core/java/com/android/server/wm/RecentTasks.java b/services/core/java/com/android/server/wm/RecentTasks.java
index d29258049acc..0503c0de5195 100644
--- a/services/core/java/com/android/server/wm/RecentTasks.java
+++ b/services/core/java/com/android/server/wm/RecentTasks.java
@@ -1378,14 +1378,6 @@ class RecentTasks {
break;
}
- // Tasks managed by/associated with an ActivityView should be excluded from recents.
- // singleTaskInstance is set on the VirtualDisplay managed by ActivityView
- // TODO(b/126185105): Find a different signal to use besides isSingleTaskInstance
- final Task rootTask = task.getRootTask();
- if (rootTask != null && rootTask.isSingleTaskInstance()) {
- return false;
- }
-
// If we're in lock task mode, ignore the root task
if (task == mService.getLockTaskController().getRootTask()) {
return false;
diff --git a/services/core/java/com/android/server/wm/ResetTargetTaskHelper.java b/services/core/java/com/android/server/wm/ResetTargetTaskHelper.java
index 9181a0fb0734..e89e59cb8350 100644
--- a/services/core/java/com/android/server/wm/ResetTargetTaskHelper.java
+++ b/services/core/java/com/android/server/wm/ResetTargetTaskHelper.java
@@ -231,11 +231,6 @@ class ResetTargetTaskHelper {
final ActivityTaskManagerService atmService = mTargetStack.mAtmService;
TaskDisplayArea taskDisplayArea = mTargetStack.getDisplayArea();
- final boolean singleTaskInstanceDisplay =
- taskDisplayArea.mDisplayContent.isSingleTaskInstance();
- if (singleTaskInstanceDisplay) {
- taskDisplayArea = atmService.mRootWindowContainer.getDefaultTaskDisplayArea();
- }
final int windowingMode = mTargetStack.getWindowingMode();
final int activityType = mTargetStack.getActivityType();
diff --git a/services/core/java/com/android/server/wm/RootWindowContainer.java b/services/core/java/com/android/server/wm/RootWindowContainer.java
index 7e76e7553a3b..11718dc5fab6 100644
--- a/services/core/java/com/android/server/wm/RootWindowContainer.java
+++ b/services/core/java/com/android/server/wm/RootWindowContainer.java
@@ -38,7 +38,6 @@ import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_SUSTAINED_PER
import static android.view.WindowManager.LayoutParams.TYPE_KEYGUARD_DIALOG;
import static android.view.WindowManager.TRANSIT_CRASHING_ACTIVITY_CLOSE;
import static android.view.WindowManager.TRANSIT_NONE;
-import static android.view.WindowManager.TRANSIT_SHOW_SINGLE_TASK_DISPLAY;
import static android.view.WindowManager.TRANSIT_TASK_TO_BACK;
import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_FOCUS_LIGHT;
@@ -864,6 +863,7 @@ class RootWindowContainer extends WindowContainer<DisplayContent>
mWmService.openSurfaceTransaction();
try {
applySurfaceChangesTransaction();
+ mWmService.mSyncEngine.onSurfacePlacement();
} catch (RuntimeException e) {
Slog.wtf(TAG, "Unhandled exception in Window Manager", e);
} finally {
@@ -2131,13 +2131,6 @@ class RootWindowContainer extends WindowContainer<DisplayContent>
+ displayId);
}
- if (displayContent.isSingleTaskInstance() && displayContent.getStackCount() > 0) {
- // We don't allow moving stacks to single instance display that already has a child.
- Slog.e(TAG, "Can not move stackId=" + stackId
- + " to single task instance display=" + displayContent);
- return;
- }
-
moveStackToTaskDisplayArea(stackId, displayContent.getDefaultTaskDisplayArea(), onTop);
}
@@ -2418,21 +2411,7 @@ class RootWindowContainer extends WindowContainer<DisplayContent>
if (displayShouldSleep) {
stack.goToSleepIfPossible(false /* shuttingDown */);
} else {
- // When the display which can only contain one task turns on, start a
- // special transition.
- // {@link AppTransitionController#handleAppTransitionReady} later picks up
- // the transition, and schedules
- // {@link ITaskStackListener#onSingleTaskDisplayDrawn} callback which is
- // triggered after contents are drawn on the display.
- if (display.isSingleTaskInstance()) {
- display.mDisplayContent.prepareAppTransition(
- TRANSIT_SHOW_SINGLE_TASK_DISPLAY, false,
- 0 /* flags */, true /* forceOverride*/);
- }
stack.awakeFromSleepingLocked();
- if (display.isSingleTaskInstance()) {
- display.executeAppTransition();
- }
if (stack.isFocusedStackOnDisplay()
&& !mStackSupervisor.getKeyguardController()
.isKeyguardOrAodShowing(display.mDisplayId)) {
diff --git a/services/core/java/com/android/server/wm/Session.java b/services/core/java/com/android/server/wm/Session.java
index f84e70eec675..70dbf683d6ec 100644
--- a/services/core/java/com/android/server/wm/Session.java
+++ b/services/core/java/com/android/server/wm/Session.java
@@ -84,6 +84,9 @@ class Session extends IWindowSession.Stub implements IBinder.DeathRecipient {
private final ArraySet<WindowSurfaceController> mAlertWindowSurfaces = new ArraySet<>();
private final DragDropController mDragDropController;
final boolean mCanAddInternalSystemWindow;
+ // If non-system overlays from this process can be hidden by the user or app using
+ // HIDE_NON_SYSTEM_OVERLAY_WINDOWS.
+ final boolean mOverlaysCanBeHidden;
final boolean mCanHideNonSystemOverlayWindows;
final boolean mCanAcquireSleepToken;
private AlertWindowNotification mAlertWindowNotification;
@@ -105,6 +108,8 @@ class Session extends IWindowSession.Stub implements IBinder.DeathRecipient {
INTERNAL_SYSTEM_WINDOW) == PERMISSION_GRANTED;
mCanHideNonSystemOverlayWindows = service.mContext.checkCallingOrSelfPermission(
HIDE_NON_SYSTEM_OVERLAY_WINDOWS) == PERMISSION_GRANTED;
+ mOverlaysCanBeHidden = !mCanAddInternalSystemWindow
+ && !mService.mAtmInternal.isCallerRecents(mUid);
mCanAcquireSleepToken = service.mContext.checkCallingOrSelfPermission(DEVICE_POWER)
== PERMISSION_GRANTED;
mShowingAlertWindowNotificationAllowed = mService.mShowAlertWindowNotifications;
@@ -160,36 +165,32 @@ class Session extends IWindowSession.Stub implements IBinder.DeathRecipient {
@Override
public int addToDisplay(IWindow window, WindowManager.LayoutParams attrs,
int viewVisibility, int displayId, InsetsState requestedVisibility, Rect outFrame,
- Rect outContentInsets, Rect outStableInsets,
DisplayCutout.ParcelableWrapper outDisplayCutout, InputChannel outInputChannel,
InsetsState outInsetsState, InsetsSourceControl[] outActiveControls) {
return mService.addWindow(this, window, attrs, viewVisibility, displayId,
- UserHandle.getUserId(mUid), requestedVisibility, outFrame,
- outContentInsets, outStableInsets, outDisplayCutout, outInputChannel,
- outInsetsState, outActiveControls);
+ UserHandle.getUserId(mUid), requestedVisibility, outFrame, outDisplayCutout,
+ outInputChannel, outInsetsState, outActiveControls);
}
@Override
public int addToDisplayAsUser(IWindow window, WindowManager.LayoutParams attrs,
int viewVisibility, int displayId, int userId, InsetsState requestedVisibility,
- Rect outFrame, Rect outContentInsets, Rect outStableInsets,
- DisplayCutout.ParcelableWrapper outDisplayCutout, InputChannel outInputChannel,
- InsetsState outInsetsState, InsetsSourceControl[] outActiveControls) {
+ Rect outFrame, DisplayCutout.ParcelableWrapper outDisplayCutout,
+ InputChannel outInputChannel, InsetsState outInsetsState,
+ InsetsSourceControl[] outActiveControls) {
return mService.addWindow(this, window, attrs, viewVisibility, displayId, userId,
- requestedVisibility, outFrame, outContentInsets, outStableInsets, outDisplayCutout,
- outInputChannel, outInsetsState, outActiveControls);
+ requestedVisibility, outFrame, outDisplayCutout, outInputChannel, outInsetsState,
+ outActiveControls);
}
@Override
public int addToDisplayWithoutInputChannel(IWindow window, WindowManager.LayoutParams attrs,
- int viewVisibility, int displayId, Rect outContentInsets, Rect outStableInsets,
- InsetsState outInsetsState) {
+ int viewVisibility, int displayId, InsetsState outInsetsState) {
return mService.addWindow(this, window, attrs, viewVisibility, displayId,
UserHandle.getUserId(mUid), mDummyRequestedVisibility,
- new Rect() /* outFrame */, outContentInsets, outStableInsets,
- new DisplayCutout.ParcelableWrapper() /* cutout */, null /* outInputChannel */,
- outInsetsState, mDummyControls);
+ new Rect() /* outFrame */, new DisplayCutout.ParcelableWrapper() /* cutout */,
+ null /* outInputChannel */, outInsetsState, mDummyControls);
}
@Override
@@ -534,7 +535,7 @@ class Session extends IWindowSession.Stub implements IBinder.DeathRecipient {
boolean changed;
- if (!mCanAddInternalSystemWindow) {
+ if (mOverlaysCanBeHidden) {
// We want to track non-system signature apps adding alert windows so we can post an
// on-going notification for the user to control their visibility.
if (visible) {
diff --git a/services/core/java/com/android/server/wm/Task.java b/services/core/java/com/android/server/wm/Task.java
index ecee46e895d0..1cee9c68edf5 100644
--- a/services/core/java/com/android/server/wm/Task.java
+++ b/services/core/java/com/android/server/wm/Task.java
@@ -67,7 +67,6 @@ import static android.view.WindowManager.TRANSIT_ACTIVITY_CLOSE;
import static android.view.WindowManager.TRANSIT_ACTIVITY_OPEN;
import static android.view.WindowManager.TRANSIT_CRASHING_ACTIVITY_CLOSE;
import static android.view.WindowManager.TRANSIT_NONE;
-import static android.view.WindowManager.TRANSIT_SHOW_SINGLE_TASK_DISPLAY;
import static android.view.WindowManager.TRANSIT_TASK_CHANGE_WINDOWING_MODE;
import static android.view.WindowManager.TRANSIT_TASK_CLOSE;
import static android.view.WindowManager.TRANSIT_TASK_OPEN;
@@ -3204,10 +3203,6 @@ class Task extends WindowContainer<WindowContainer> {
if (DEBUG_STACK) Slog.i(TAG, "removeTask: removing taskId=" + mTaskId);
EventLogTags.writeWmTaskRemoved(mTaskId, "removeTask");
- if (mDisplayContent != null && mDisplayContent.isSingleTaskInstance()) {
- mAtmService.notifySingleTaskDisplayEmpty(mDisplayContent.mDisplayId);
- }
-
// If applicable let the TaskOrganizer know the Task is vanishing.
setTaskOrganizer(null);
@@ -5196,11 +5191,6 @@ class Task extends WindowContainer<WindowContainer> {
!PRESERVE_WINDOWS);
}
- /** @return true if the stack can only contain one task */
- boolean isSingleTaskInstance() {
- return mDisplayContent != null && mDisplayContent.isSingleTaskInstance();
- }
-
final boolean isHomeOrRecentsStack() {
return isActivityTypeHome() || isActivityTypeRecents();
}
@@ -6354,13 +6344,6 @@ class Task extends WindowContainer<WindowContainer> {
if (newTask) {
if (r.mLaunchTaskBehind) {
transit = TRANSIT_TASK_OPEN_BEHIND;
- } else if (dc.isSingleTaskInstance()) {
- // If a new task is being launched in a single task display, we don't need
- // to play normal animation, but need to trigger a callback when an app
- // transition is actually handled. So ignore already prepared activity, and
- // override it.
- transit = TRANSIT_SHOW_SINGLE_TASK_DISPLAY;
- keepCurTransition = false;
} else {
// If a new task is being launched, then mark the existing top activity as
// supporting picture-in-picture while pausing only if the starting activity
@@ -6781,15 +6764,6 @@ class Task extends WindowContainer<WindowContainer> {
// nothing to do!
if (noAnimation) {
ActivityOptions.abort(options);
- } else if (isSingleTaskInstance()) {
- // When a task is moved front on the display which can only contain one task, start
- // a special transition.
- // {@link AppTransitionController#handleAppTransitionReady} later picks up the
- // transition, and schedules
- // {@link ITaskStackListener#onSingleTaskDisplayDrawn} callback which is triggered
- // after contents are drawn on the display.
- updateTransitLocked(TRANSIT_SHOW_SINGLE_TASK_DISPLAY, options,
- true /* forceOverride */);
} else {
updateTransitLocked(TRANSIT_TASK_TO_FRONT, options, false /* forceOverride */);
}
@@ -6837,9 +6811,6 @@ class Task extends WindowContainer<WindowContainer> {
mStackSupervisor.mNoAnimActivities.add(r);
}
ActivityOptions.abort(options);
- } else if (isSingleTaskInstance()) {
- updateTransitLocked(TRANSIT_SHOW_SINGLE_TASK_DISPLAY, options,
- true /* forceOverride */);
} else {
updateTransitLocked(TRANSIT_TASK_TO_FRONT, options, false /* forceOverride */);
}
@@ -7205,10 +7176,6 @@ class Task extends WindowContainer<WindowContainer> {
}
void addChild(WindowContainer child, final boolean toTop, boolean showForAllUsers) {
- if (isSingleTaskInstance() && hasChild()) {
- throw new IllegalStateException("Can only have one child on stack=" + this);
- }
-
Task task = child.asTask();
try {
diff --git a/services/core/java/com/android/server/wm/TaskChangeNotificationController.java b/services/core/java/com/android/server/wm/TaskChangeNotificationController.java
index 2a241183ff1f..5364f9c58657 100644
--- a/services/core/java/com/android/server/wm/TaskChangeNotificationController.java
+++ b/services/core/java/com/android/server/wm/TaskChangeNotificationController.java
@@ -54,14 +54,12 @@ class TaskChangeNotificationController {
private static final int NOTIFY_ACTIVITY_LAUNCH_ON_SECONDARY_DISPLAY_REROUTED_MSG = 19;
private static final int NOTIFY_SIZE_COMPAT_MODE_ACTIVITY_CHANGED_MSG = 20;
private static final int NOTIFY_BACK_PRESSED_ON_TASK_ROOT = 21;
- private static final int NOTIFY_SINGLE_TASK_DISPLAY_DRAWN = 22;
- private static final int NOTIFY_TASK_DISPLAY_CHANGED_LISTENERS_MSG = 23;
- private static final int NOTIFY_TASK_LIST_UPDATED_LISTENERS_MSG = 24;
- private static final int NOTIFY_SINGLE_TASK_DISPLAY_EMPTY = 25;
- private static final int NOTIFY_TASK_LIST_FROZEN_UNFROZEN_MSG = 26;
- private static final int NOTIFY_TASK_FOCUS_CHANGED_MSG = 27;
- private static final int NOTIFY_TASK_REQUESTED_ORIENTATION_CHANGED_MSG = 28;
- private static final int NOTIFY_ACTIVITY_ROTATED_MSG = 29;
+ private static final int NOTIFY_TASK_DISPLAY_CHANGED_LISTENERS_MSG = 22;
+ private static final int NOTIFY_TASK_LIST_UPDATED_LISTENERS_MSG = 23;
+ private static final int NOTIFY_TASK_LIST_FROZEN_UNFROZEN_MSG = 24;
+ private static final int NOTIFY_TASK_FOCUS_CHANGED_MSG = 25;
+ private static final int NOTIFY_TASK_REQUESTED_ORIENTATION_CHANGED_MSG = 26;
+ private static final int NOTIFY_ACTIVITY_ROTATED_MSG = 27;
// Delay in notifying task stack change listeners (in millis)
private static final int NOTIFY_TASK_STACK_CHANGE_LISTENERS_DELAY = 100;
@@ -156,14 +154,6 @@ class TaskChangeNotificationController {
l.onSizeCompatModeActivityChanged(m.arg1, (IBinder) m.obj);
};
- private final TaskStackConsumer mNotifySingleTaskDisplayDrawn = (l, m) -> {
- l.onSingleTaskDisplayDrawn(m.arg1);
- };
-
- private final TaskStackConsumer mNotifySingleTaskDisplayEmpty = (l, m) -> {
- l.onSingleTaskDisplayEmpty(m.arg1);
- };
-
private final TaskStackConsumer mNotifyTaskDisplayChanged = (l, m) -> {
l.onTaskDisplayChanged(m.arg1, m.arg2);
};
@@ -261,12 +251,6 @@ class TaskChangeNotificationController {
case NOTIFY_BACK_PRESSED_ON_TASK_ROOT:
forAllRemoteListeners(mNotifyBackPressedOnTaskRoot, msg);
break;
- case NOTIFY_SINGLE_TASK_DISPLAY_DRAWN:
- forAllRemoteListeners(mNotifySingleTaskDisplayDrawn, msg);
- break;
- case NOTIFY_SINGLE_TASK_DISPLAY_EMPTY:
- forAllRemoteListeners(mNotifySingleTaskDisplayEmpty, msg);
- break;
case NOTIFY_TASK_DISPLAY_CHANGED_LISTENERS_MSG:
forAllRemoteListeners(mNotifyTaskDisplayChanged, msg);
break;
@@ -520,27 +504,6 @@ class TaskChangeNotificationController {
}
/**
- * Notify listeners that contents are drawn for the first time on a single task display.
- */
- void notifySingleTaskDisplayDrawn(int displayId) {
- final Message msg = mHandler.obtainMessage(NOTIFY_SINGLE_TASK_DISPLAY_DRAWN,
- displayId, 0 /* unused */);
- forAllLocalListeners(mNotifySingleTaskDisplayDrawn, msg);
- msg.sendToTarget();
- }
-
- /**
- * Notify listeners that the last task is removed from a single task display.
- */
- void notifySingleTaskDisplayEmpty(int displayId) {
- final Message msg = mHandler.obtainMessage(
- NOTIFY_SINGLE_TASK_DISPLAY_EMPTY,
- displayId, 0 /* unused */);
- forAllLocalListeners(mNotifySingleTaskDisplayEmpty, msg);
- msg.sendToTarget();
- }
-
- /**
* Notify listeners that a task is reparented to another display.
*/
void notifyTaskDisplayChanged(int taskId, int newDisplayId) {
diff --git a/services/core/java/com/android/server/wm/TaskDisplayArea.java b/services/core/java/com/android/server/wm/TaskDisplayArea.java
index 830ad5d6043b..c6b9e48f6a57 100644
--- a/services/core/java/com/android/server/wm/TaskDisplayArea.java
+++ b/services/core/java/com/android/server/wm/TaskDisplayArea.java
@@ -311,9 +311,6 @@ final class TaskDisplayArea extends DisplayArea<Task> {
@Override
void addChild(Task task, int position) {
if (DEBUG_STACK) Slog.d(TAG_WM, "Set task=" + task + " on taskDisplayArea=" + this);
- if (mDisplayContent.mSingleTaskInstance && getStackCount() == 1) {
- throw new IllegalStateException("addChild: Can only have one task on display=" + this);
- }
addStackReferenceIfNeeded(task);
position = findPositionForStack(position, task, true /* adding */);
@@ -1020,14 +1017,6 @@ final class TaskDisplayArea extends DisplayArea<Task> {
*/
Task createStack(int windowingMode, int activityType, boolean onTop, ActivityInfo info,
Intent intent, boolean createdByOrganizer) {
- if (mDisplayContent.mSingleTaskInstance && getStackCount() > 0) {
- // Create stack on default display instead since this display can only contain 1 stack.
- // TODO: Kinda a hack, but better that having the decision at each call point. Hoping
- // this goes away once ActivityView is no longer using virtual displays.
- return mRootWindowContainer.getDefaultTaskDisplayArea().createStack(
- windowingMode, activityType, onTop, info, intent, createdByOrganizer);
- }
-
if (activityType == ACTIVITY_TYPE_UNDEFINED && !createdByOrganizer) {
// Can't have an undefined stack type yet...so re-map to standard. Anyone that wants
// anything else should be passing it in anyways...except for the task organizer.
diff --git a/services/core/java/com/android/server/wm/TaskOrganizerController.java b/services/core/java/com/android/server/wm/TaskOrganizerController.java
index 48550ed016c3..6486b78eb601 100644
--- a/services/core/java/com/android/server/wm/TaskOrganizerController.java
+++ b/services/core/java/com/android/server/wm/TaskOrganizerController.java
@@ -161,17 +161,18 @@ class TaskOrganizerController extends ITaskOrganizerController.Stub {
return;
}
ProtoLog.v(WM_DEBUG_WINDOW_ORGANIZER, "Task info changed taskId=%d", task.mTaskId);
- mDeferTaskOrgCallbacksConsumer.accept(() -> {
- if (!task.isOrganized()) {
- // This is safe to ignore if the task is no longer organized
- return;
- }
- try {
- mTaskOrganizer.onTaskInfoChanged(taskInfo);
- } catch (RemoteException e) {
- Slog.e(TAG, "Exception sending onTaskInfoChanged callback", e);
- }
- });
+ if (!task.isOrganized()) {
+ // This is safe to ignore if the task is no longer organized
+ return;
+ }
+ try {
+ // Purposely notify of task info change immediately instead of deferring (like
+ // appear and vanish) to allow info changes (such as new PIP params) to flow
+ // without waiting.
+ mTaskOrganizer.onTaskInfoChanged(taskInfo);
+ } catch (RemoteException e) {
+ Slog.e(TAG, "Exception sending onTaskInfoChanged callback", e);
+ }
}
void onBackPressedOnTaskRoot(Task task) {
@@ -182,17 +183,15 @@ class TaskOrganizerController extends ITaskOrganizerController.Stub {
// by the organizer that don't receive that signal
return;
}
- mDeferTaskOrgCallbacksConsumer.accept(() -> {
- if (!task.isOrganized()) {
- // This is safe to ignore if the task is no longer organized
- return;
- }
- try {
- mTaskOrganizer.onBackPressedOnTaskRoot(task.getTaskInfo());
- } catch (Exception e) {
- Slog.e(TAG, "Exception sending onBackPressedOnTaskRoot callback", e);
- }
- });
+ if (!task.isOrganized()) {
+ // This is safe to ignore if the task is no longer organized
+ return;
+ }
+ try {
+ mTaskOrganizer.onBackPressedOnTaskRoot(task.getTaskInfo());
+ } catch (Exception e) {
+ Slog.e(TAG, "Exception sending onBackPressedOnTaskRoot callback", e);
+ }
}
}
@@ -390,6 +389,10 @@ class TaskOrganizerController extends ITaskOrganizerController.Stub {
}
void onTaskAppeared(ITaskOrganizer organizer, Task task) {
+ // Don't send onTaskAppeared signal for task created by organizer since we will return it in
+ // the creation call.
+ if (task.mCreatedByOrganizer) return;
+
final TaskOrganizerState state = mTaskOrganizerStates.get(organizer.asBinder());
state.addTask(task);
}
@@ -402,7 +405,7 @@ class TaskOrganizerController extends ITaskOrganizerController.Stub {
}
@Override
- public RunningTaskInfo createRootTask(int displayId, int windowingMode) {
+ public TaskAppearedInfo createRootTask(int displayId, int windowingMode) {
enforceStackPermission("createRootTask()");
final long origId = Binder.clearCallingIdentity();
try {
@@ -419,7 +422,11 @@ class TaskOrganizerController extends ITaskOrganizerController.Stub {
true /* createdByOrganizer */);
RunningTaskInfo out = task.getTaskInfo();
mLastSentTaskInfos.put(task, out);
- return out;
+ final TaskOrganizerState state =
+ mTaskOrganizerStates.get(task.mTaskOrganizer.asBinder());
+ final SurfaceControl outSurfaceControl = state.addTaskWithoutCallback(task,
+ "TaskOrganizerController.createRootTask");
+ return new TaskAppearedInfo(task.getTaskInfo(), outSurfaceControl);
}
} finally {
Binder.restoreCallingIdentity(origId);
diff --git a/services/core/java/com/android/server/wm/TaskSnapshotSurface.java b/services/core/java/com/android/server/wm/TaskSnapshotSurface.java
index e8c4491d3677..aab5da6de214 100644
--- a/services/core/java/com/android/server/wm/TaskSnapshotSurface.java
+++ b/services/core/java/com/android/server/wm/TaskSnapshotSurface.java
@@ -242,9 +242,8 @@ class TaskSnapshotSurface implements StartingSurface {
try {
final int res = session.addToDisplay(window, layoutParams,
View.GONE, activity.getDisplayContent().getDisplayId(), mTmpInsetsState,
- tmpFrames.frame, tmpFrames.contentInsets, tmpFrames.stableInsets,
- tmpFrames.displayCutout, null /* outInputChannel */, mTmpInsetsState,
- mTempControls);
+ tmpFrames.frame, tmpFrames.displayCutout, null /* outInputChannel */,
+ mTmpInsetsState, mTempControls);
if (res < 0) {
Slog.w(TAG, "Failed to add snapshot starting window res=" + res);
return null;
diff --git a/services/core/java/com/android/server/wm/Transition.java b/services/core/java/com/android/server/wm/Transition.java
index fc67cd22ee69..ac86698c630f 100644
--- a/services/core/java/com/android/server/wm/Transition.java
+++ b/services/core/java/com/android/server/wm/Transition.java
@@ -17,6 +17,7 @@
package com.android.server.wm;
+import static android.view.Display.DEFAULT_DISPLAY;
import static android.view.WindowManager.TRANSIT_FLAG_KEYGUARD_GOING_AWAY_NO_ANIMATION;
import static android.view.WindowManager.TRANSIT_FLAG_KEYGUARD_GOING_AWAY_SUBTLE_ANIMATION;
import static android.view.WindowManager.TRANSIT_FLAG_KEYGUARD_GOING_AWAY_TO_SHADE;
@@ -31,7 +32,6 @@ import android.os.RemoteException;
import android.util.ArrayMap;
import android.util.ArraySet;
import android.util.Slog;
-import android.view.Display;
import android.view.SurfaceControl;
import android.view.WindowManager;
import android.view.animation.Animation;
@@ -43,7 +43,6 @@ import com.android.internal.protolog.common.ProtoLog;
import java.util.ArrayList;
import java.util.Map;
-import java.util.Set;
/**
* Represents a logical transition.
@@ -70,6 +69,7 @@ class Transition extends Binder implements BLASTSyncEngine.TransactionReadyListe
private int mSyncId;
private @WindowManager.TransitionFlags int mFlags;
private final TransitionController mController;
+ private final BLASTSyncEngine mSyncEngine;
final ArrayMap<WindowContainer, ChangeInfo> mParticipants = new ArrayMap<>();
private int mState = STATE_COLLECTING;
private boolean mReadyCalled = false;
@@ -79,7 +79,8 @@ class Transition extends Binder implements BLASTSyncEngine.TransactionReadyListe
mType = type;
mFlags = flags;
mController = controller;
- mSyncId = mController.mSyncEngine.startSyncSet(this);
+ mSyncEngine = mController.mAtm.mWindowManager.mSyncEngine;
+ mSyncId = mSyncEngine.startSyncSet(this);
}
/**
@@ -104,10 +105,8 @@ class Transition extends Binder implements BLASTSyncEngine.TransactionReadyListe
if (mSyncId < 0) return;
ProtoLog.v(ProtoLogGroup.WM_DEBUG_WINDOW_TRANSITIONS, "Collecting in transition %d: %s",
mSyncId, wc);
- // Add to sync set before checking contains because it may not have added it at other
- // times (eg. if wc was previously invisible).
- mController.mSyncEngine.addToSyncSet(mSyncId, wc);
if (mParticipants.containsKey(wc)) return;
+ mSyncEngine.addToSyncSet(mSyncId, wc);
mParticipants.put(wc, new ChangeInfo());
}
@@ -125,8 +124,7 @@ class Transition extends Binder implements BLASTSyncEngine.TransactionReadyListe
}
ProtoLog.v(ProtoLogGroup.WM_DEBUG_WINDOW_TRANSITIONS,
"Finish collecting in transition %d", mSyncId);
- mController.mSyncEngine.setReady(mSyncId);
- mController.mAtm.mWindowManager.mWindowPlacerLocked.requestTraversal();
+ mSyncEngine.setReady(mSyncId);
}
/** The transition has finished animating and is ready to finalize WM state */
@@ -146,7 +144,7 @@ class Transition extends Binder implements BLASTSyncEngine.TransactionReadyListe
}
@Override
- public void onTransactionReady(int syncId, Set<WindowContainer> windowContainersReady) {
+ public void onTransactionReady(int syncId, SurfaceControl.Transaction transaction) {
if (syncId != mSyncId) {
Slog.e(TAG, "Unexpected Sync ID " + syncId + ". Expected " + mSyncId);
return;
@@ -155,10 +153,8 @@ class Transition extends Binder implements BLASTSyncEngine.TransactionReadyListe
mController.moveToPlaying(this);
final TransitionInfo info = calculateTransitionInfo(mType, mParticipants);
- SurfaceControl.Transaction mergedTransaction = new SurfaceControl.Transaction();
- int displayId = Display.DEFAULT_DISPLAY;
- for (WindowContainer container : windowContainersReady) {
- container.mergeBlastSyncTransaction(mergedTransaction);
+ int displayId = DEFAULT_DISPLAY;
+ for (WindowContainer container : mParticipants.keySet()) {
displayId = container.mDisplayContent.getDisplayId();
}
@@ -168,14 +164,14 @@ class Transition extends Binder implements BLASTSyncEngine.TransactionReadyListe
try {
ProtoLog.v(ProtoLogGroup.WM_DEBUG_WINDOW_TRANSITIONS,
"Calling onTransitionReady: %s", info);
- mController.getTransitionPlayer().onTransitionReady(this, info, mergedTransaction);
+ mController.getTransitionPlayer().onTransitionReady(this, info, transaction);
} catch (RemoteException e) {
// If there's an exception when trying to send the mergedTransaction to the
// client, we should immediately apply it here so the transactions aren't lost.
- mergedTransaction.apply();
+ transaction.apply();
}
} else {
- mergedTransaction.apply();
+ transaction.apply();
}
mSyncId = -1;
}
diff --git a/services/core/java/com/android/server/wm/TransitionController.java b/services/core/java/com/android/server/wm/TransitionController.java
index d102c19bfff9..7cdc177e1b9b 100644
--- a/services/core/java/com/android/server/wm/TransitionController.java
+++ b/services/core/java/com/android/server/wm/TransitionController.java
@@ -51,7 +51,6 @@ class TransitionController {
Arrays.sort(SUPPORTED_LEGACY_TRANSIT_TYPES);
}
- final BLASTSyncEngine mSyncEngine = new BLASTSyncEngine();
private ITransitionPlayer mTransitionPlayer;
private final IBinder.DeathRecipient mTransitionPlayerDeath = () -> mTransitionPlayer = null;
final ActivityTaskManagerService mAtm;
diff --git a/services/core/java/com/android/server/wm/WindowContainer.java b/services/core/java/com/android/server/wm/WindowContainer.java
index 0edaa1d821df..da3a92856fe5 100644
--- a/services/core/java/com/android/server/wm/WindowContainer.java
+++ b/services/core/java/com/android/server/wm/WindowContainer.java
@@ -58,6 +58,7 @@ import static com.android.server.wm.WindowStateAnimator.STACK_CLIP_AFTER_ANIM;
import android.annotation.CallSuper;
import android.annotation.IntDef;
+import android.annotation.NonNull;
import android.annotation.Nullable;
import android.app.WindowConfiguration;
import android.content.pm.ActivityInfo;
@@ -96,7 +97,6 @@ import java.lang.ref.WeakReference;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.LinkedList;
-import java.util.Set;
import java.util.function.BiFunction;
import java.util.function.Consumer;
import java.util.function.Function;
@@ -109,8 +109,7 @@ import java.util.function.Predicate;
* changes are made to this class.
*/
class WindowContainer<E extends WindowContainer> extends ConfigurationContainer<E>
- implements Comparable<WindowContainer>, Animatable, SurfaceFreezer.Freezable,
- BLASTSyncEngine.TransactionReadyListener {
+ implements Comparable<WindowContainer>, Animatable, SurfaceFreezer.Freezable {
private static final String TAG = TAG_WITH_CLASS_NAME ? "WindowContainer" : TAG_WM;
@@ -290,16 +289,35 @@ class WindowContainer<E extends WindowContainer> extends ConfigurationContainer<
*/
RemoteToken mRemoteToken = null;
- BLASTSyncEngine mBLASTSyncEngine = new BLASTSyncEngine();
- SurfaceControl.Transaction mBLASTSyncTransaction;
- boolean mUsingBLASTSyncTransaction = false;
- BLASTSyncEngine.TransactionReadyListener mWaitingListener;
- int mWaitingSyncId;
+ /** This isn't participating in a sync. */
+ public static final int SYNC_STATE_NONE = 0;
+
+ /** This is currently waiting for itself to finish drawing. */
+ public static final int SYNC_STATE_WAITING_FOR_DRAW = 1;
+
+ /** This container is ready, but it might still have unfinished children. */
+ public static final int SYNC_STATE_READY = 2;
+
+ @IntDef(prefix = { "SYNC_STATE_" }, value = {
+ SYNC_STATE_NONE,
+ SYNC_STATE_WAITING_FOR_DRAW,
+ SYNC_STATE_READY,
+ })
+ @interface SyncState {}
+
+ /**
+ * If non-null, references the sync-group directly waiting on this container. Otherwise, this
+ * container is only being waited-on by its parents (if in a sync-group). This has implications
+ * on how this container is handled during parent changes.
+ */
+ BLASTSyncEngine.SyncGroup mSyncGroup = null;
+ final SurfaceControl.Transaction mSyncTransaction;
+ @SyncState int mSyncState = SYNC_STATE_NONE;
WindowContainer(WindowManagerService wms) {
mWmService = wms;
mPendingTransaction = wms.mTransactionFactory.get();
- mBLASTSyncTransaction = wms.mTransactionFactory.get();
+ mSyncTransaction = wms.mTransactionFactory.get();
mSurfaceAnimator = new SurfaceAnimator(this, this::onAnimationFinished, wms);
mSurfaceFreezer = new SurfaceFreezer(this, wms);
}
@@ -357,6 +375,7 @@ class WindowContainer<E extends WindowContainer> extends ConfigurationContainer<
// Send onParentChanged notification here is we disabled sending it in setParent for
// reparenting case.
onParentChanged(newParent, oldParent);
+ onSyncReparent(oldParent, newParent);
}
final protected void setParent(WindowContainer<WindowContainer> parent) {
@@ -372,6 +391,7 @@ class WindowContainer<E extends WindowContainer> extends ConfigurationContainer<
onDisplayChanged(mParent.mDisplayContent);
}
onParentChanged(mParent, oldParent);
+ onSyncReparent(oldParent, mParent);
}
}
@@ -612,6 +632,8 @@ class WindowContainer<E extends WindowContainer> extends ConfigurationContainer<
scheduleAnimation();
}
+ // This must happen after updating the surface so that sync transactions can be handled
+ // properly.
if (mParent != null) {
mParent.removeChild(this);
}
@@ -2247,8 +2269,8 @@ class WindowContainer<E extends WindowContainer> extends ConfigurationContainer<
* {@link #getPendingTransaction()}
*/
public Transaction getSyncTransaction() {
- if (mUsingBLASTSyncTransaction) {
- return mBLASTSyncTransaction;
+ if (mSyncState != SYNC_STATE_NONE) {
+ return mSyncTransaction;
}
return getPendingTransaction();
@@ -2895,69 +2917,140 @@ class WindowContainer<E extends WindowContainer> extends ConfigurationContainer<
}
}
- @Override
- public void onTransactionReady(int mSyncId, Set<WindowContainer> windowContainersReady) {
- if (mWaitingListener == null) {
- return;
- }
-
- windowContainersReady.add(this);
- mWaitingListener.onTransactionReady(mWaitingSyncId, windowContainersReady);
-
- mWaitingListener = null;
- mWaitingSyncId = -1;
- }
-
/**
- * Returns true if any of the children elected to participate in the Sync
+ * Call this when this container finishes drawing content.
+ *
+ * @return {@code true} if consumed (this container is part of a sync group).
*/
- boolean addChildrenToSyncSet(int localId) {
- boolean willSync = false;
+ boolean onSyncFinishedDrawing() {
+ if (mSyncState == SYNC_STATE_NONE) return false;
+ mSyncState = SYNC_STATE_READY;
+ mWmService.mWindowPlacerLocked.requestTraversal();
+ ProtoLog.v(WM_DEBUG_SYNC_ENGINE, "onSyncFinishedDrawing %s", this);
+ return true;
+ }
- for (int i = 0; i < mChildren.size(); i++) {
- final WindowContainer child = mChildren.get(i);
- willSync |= mBLASTSyncEngine.addToSyncSet(localId, child);
+ void setSyncGroup(@NonNull BLASTSyncEngine.SyncGroup group) {
+ ProtoLog.v(WM_DEBUG_SYNC_ENGINE, "setSyncGroup #%d on %s", group.mSyncId, this);
+ if (group != null) {
+ if (mSyncGroup != null && mSyncGroup != group) {
+ throw new IllegalStateException("Can't sync on 2 engines simultaneously");
+ }
}
- return willSync;
+ mSyncGroup = group;
}
- boolean setPendingListener(BLASTSyncEngine.TransactionReadyListener waitingListener,
- int waitingId) {
- // If we are invisible, no need to sync, likewise if we are already engaged in a sync,
- // we can't support overlapping syncs on a single container yet.
- if (!isVisible() || mWaitingListener != null) {
- ProtoLog.v(WM_DEBUG_SYNC_ENGINE, "- NOT adding to sync: visible=%b "
- + "hasListener=%b", isVisible(), mWaitingListener != null);
+ /**
+ * Prepares this container for participation in a sync-group. This includes preparing all its
+ * children.
+ *
+ * @return {@code true} if something changed (eg. this wasn't already in the sync group).
+ */
+ boolean prepareSync() {
+ if (mSyncState != SYNC_STATE_NONE) {
+ // Already part of sync
return false;
}
- mUsingBLASTSyncTransaction = true;
-
- // Make sure to set these before we call setReady in case the sync was a no-op
- mWaitingSyncId = waitingId;
- mWaitingListener = waitingListener;
+ for (int i = getChildCount() - 1; i >= 0; --i) {
+ final WindowContainer child = getChildAt(i);
+ child.prepareSync();
+ }
+ mSyncState = SYNC_STATE_READY;
return true;
}
- boolean prepareForSync(BLASTSyncEngine.TransactionReadyListener waitingListener,
- int waitingId) {
- boolean willSync = setPendingListener(waitingListener, waitingId);
- if (!willSync) {
- return false;
- }
-
- int localId = mBLASTSyncEngine.startSyncSet(this);
- willSync |= addChildrenToSyncSet(localId);
- mBLASTSyncEngine.setReady(localId);
+ boolean useBLASTSync() {
+ return mSyncState != SYNC_STATE_NONE;
+ }
- return willSync;
+ /**
+ * Recursively finishes/cleans-up sync state of this subtree and collects all the sync
+ * transactions into `outMergedTransaction`.
+ * @param outMergedTransaction A transaction to merge all the recorded sync operations into.
+ * @param cancel If true, this is being finished because it is leaving the sync group rather
+ * than due to the sync group completing.
+ */
+ void finishSync(Transaction outMergedTransaction, boolean cancel) {
+ if (mSyncState == SYNC_STATE_NONE) return;
+ ProtoLog.v(WM_DEBUG_SYNC_ENGINE, "finishSync cancel=%b for %s", cancel, this);
+ outMergedTransaction.merge(mSyncTransaction);
+ for (int i = mChildren.size() - 1; i >= 0; --i) {
+ mChildren.get(i).finishSync(outMergedTransaction, cancel);
+ }
+ mSyncState = SYNC_STATE_NONE;
+ if (cancel && mSyncGroup != null) mSyncGroup.onCancelSync(this);
+ mSyncGroup = null;
}
- boolean useBLASTSync() {
- return mUsingBLASTSyncTransaction;
+ /**
+ * Checks if the subtree rooted at this container is finished syncing (everything is ready or
+ * not visible). NOTE, this is not const: it will cancel/prepare itself depending on its state
+ * in the hierarchy.
+ *
+ * @return {@code true} if this subtree is finished waiting for sync participants.
+ */
+ boolean isSyncFinished() {
+ if (!isVisibleRequested()) {
+ return true;
+ }
+ if (mSyncState == SYNC_STATE_NONE) {
+ prepareSync();
+ }
+ if (mSyncState == SYNC_STATE_WAITING_FOR_DRAW) {
+ return false;
+ }
+ // READY
+ // Loop from top-down.
+ for (int i = mChildren.size() - 1; i >= 0; --i) {
+ final WindowContainer child = mChildren.get(i);
+ final boolean childFinished = child.isSyncFinished();
+ if (childFinished && child.isVisibleRequested() && child.fillsParent()) {
+ // Any lower children will be covered-up, so we can consider this finished.
+ return true;
+ }
+ if (!childFinished) {
+ return false;
+ }
+ }
+ return true;
}
- void mergeBlastSyncTransaction(Transaction t) {
- t.merge(mBLASTSyncTransaction);
- mUsingBLASTSyncTransaction = false;
+ /**
+ * Called during reparent to handle sync state when the hierarchy changes.
+ * If this is in a sync group and gets reparented out, it will cancel syncing.
+ * If this is not in a sync group and gets parented into one, it will prepare itself.
+ * If its moving around within a sync-group, it needs to restart its syncing since a
+ * hierarchy change implies a configuration change.
+ */
+ private void onSyncReparent(WindowContainer oldParent, WindowContainer newParent) {
+ if (newParent == null || newParent.mSyncState == SYNC_STATE_NONE) {
+ if (mSyncState == SYNC_STATE_NONE) {
+ return;
+ }
+ if (newParent == null) {
+ // This is getting removed.
+ if (oldParent.mSyncState != SYNC_STATE_NONE) {
+ // In order to keep the transaction in sync, merge it into the parent.
+ finishSync(oldParent.mSyncTransaction, true /* cancel */);
+ } else if (mSyncGroup != null) {
+ // This is watched directly by the sync-group, so merge this transaction into
+ // into the sync-group so it isn't lost
+ finishSync(mSyncGroup.getOrphanTransaction(), true /* cancel */);
+ } else {
+ throw new IllegalStateException("This container is in sync mode without a sync"
+ + " group: " + this);
+ }
+ return;
+ } else if (mSyncGroup == null) {
+ // This is being reparented out of the sync-group. To prevent ordering issues on
+ // this container, immediately apply/cancel sync on it.
+ finishSync(getPendingTransaction(), true /* cancel */);
+ return;
+ }
+ // Otherwise this is the "root" of a synced subtree, so continue on to preparation.
+ }
+ // This container's situation has changed so we need to restart its sync.
+ mSyncState = SYNC_STATE_NONE;
+ prepareSync();
}
}
diff --git a/services/core/java/com/android/server/wm/WindowFrames.java b/services/core/java/com/android/server/wm/WindowFrames.java
index d96b6457f9db..259dee48fb39 100644
--- a/services/core/java/com/android/server/wm/WindowFrames.java
+++ b/services/core/java/com/android/server/wm/WindowFrames.java
@@ -207,28 +207,6 @@ public class WindowFrames {
return (mLastFrame.width() != mFrame.width()) || (mLastFrame.height() != mFrame.height());
}
- // TODO(b/118118435): Remove after migration.
- /**
- * Calculate the insets for the type
- * {@link android.view.WindowManager.LayoutParams#TYPE_DOCK_DIVIDER}
- *
- * @param cutoutInsets The insets for the cutout.
- */
- void calculateDockedDividerInsets(Rect cutoutInsets) {
- // For the docked divider, we calculate the stable insets like a full-screen window
- // so it can use it to calculate the snap positions.
- mTmpRect.set(mDisplayFrame);
- mTmpRect.inset(cutoutInsets);
- mTmpRect.intersectUnchecked(mStableFrame);
- InsetUtils.insetsBetweenFrames(mDisplayFrame, mTmpRect, mStableInsets);
-
- // The divider doesn't care about insets in any case, so set it to empty so we don't
- // trigger a relayout when moving it.
- mContentInsets.setEmpty();
- mVisibleInsets.setEmpty();
- mDisplayCutout = WmDisplayCutout.NO_CUTOUT;
- }
-
/**
* Calculate the insets for a window.
*
diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java
index 40b770fc67ec..66f2e4d8dc2c 100644
--- a/services/core/java/com/android/server/wm/WindowManagerService.java
+++ b/services/core/java/com/android/server/wm/WindowManagerService.java
@@ -225,7 +225,7 @@ import android.view.IOnKeyguardExitResult;
import android.view.IPinnedStackListener;
import android.view.IRecentsAnimationRunner;
import android.view.IRotationWatcher;
-import android.view.IScrollCaptureController;
+import android.view.IScrollCaptureCallbacks;
import android.view.ISystemGestureExclusionListener;
import android.view.IWallpaperVisibilityListener;
import android.view.IWindow;
@@ -667,6 +667,8 @@ public class WindowManagerService extends IWindowManager.Stub
// Whether to enable BLASTSyncEngine Transaction passing.
final boolean mUseBLASTSync = false;
+ final BLASTSyncEngine mSyncEngine;
+
int mDockedStackCreateMode = SPLIT_SCREEN_CREATE_MODE_TOP_OR_LEFT;
Rect mDockedStackCreateBounds;
@@ -1191,6 +1193,8 @@ public class WindowManagerService extends IWindowManager.Stub
DeviceConfig.NAMESPACE_WINDOW_MANAGER_NATIVE_BOOT,
WM_USE_BLAST_ADAPTER_FLAG, false);
+ mSyncEngine = new BLASTSyncEngine(this);
+
mWindowPlacerLocked = new WindowSurfacePlacer(this);
mTaskSnapshotController = new TaskSnapshotController(this);
@@ -1376,7 +1380,6 @@ public class WindowManagerService extends IWindowManager.Stub
public int addWindow(Session session, IWindow client, LayoutParams attrs, int viewVisibility,
int displayId, int requestUserId, InsetsState requestedVisibility, Rect outFrame,
- Rect outContentInsets, Rect outStableInsets,
DisplayCutout.ParcelableWrapper outDisplayCutout, InputChannel outInputChannel,
InsetsState outInsetsState, InsetsSourceControl[] outActiveControls) {
Arrays.fill(outActiveControls, null);
@@ -1691,11 +1694,10 @@ public class WindowManagerService extends IWindowManager.Stub
prepareNoneTransitionForRelaunching(activity);
}
- if (displayPolicy.getLayoutHint(win.mAttrs, token, outFrame, outContentInsets,
- outStableInsets, outDisplayCutout)) {
+ if (displayPolicy.getLayoutHint(win.mAttrs, token, outFrame, outDisplayCutout,
+ outInsetsState, win.isClientLocal())) {
res |= WindowManagerGlobal.ADD_FLAG_ALWAYS_CONSUME_SYSTEM_BARS;
}
- outInsetsState.set(win.getInsetsState(), win.isClientLocal());
if (mInTouchMode) {
res |= WindowManagerGlobal.ADD_FLAG_IN_TOUCH_MODE;
@@ -6902,16 +6904,17 @@ public class WindowManagerService extends IWindowManager.Stub
*
* @param displayId the display for the request
* @param behindClient token for a window, used to filter the search to windows behind it
- * @param taskId specifies the id of a task the result must belong to or -1 to ignore task ids
- * @param controller the controller to receive results; a call to either
- * {@link IScrollCaptureController#onClientConnected} or
- * {@link IScrollCaptureController#onClientUnavailable}.
+ * @param taskId specifies the id of a task the result must belong to or -1 to match any task
+ * @param callbacks to receive responses
*/
public void requestScrollCapture(int displayId, @Nullable IBinder behindClient, int taskId,
- IScrollCaptureController controller) {
+ IScrollCaptureCallbacks callbacks) {
if (!checkCallingPermission(READ_FRAME_BUFFER, "requestScrollCapture()")) {
throw new SecurityException("Requires READ_FRAME_BUFFER permission");
}
+ if (behindClient != null && !isWindowToken(behindClient)) {
+ throw new IllegalArgumentException("behindClient must be a window token");
+ }
final long token = Binder.clearCallingIdentity();
try {
synchronized (mGlobalLock) {
@@ -6919,26 +6922,26 @@ public class WindowManagerService extends IWindowManager.Stub
if (dc == null) {
ProtoLog.e(WM_ERROR,
"Invalid displayId for requestScrollCapture: %d", displayId);
- controller.onClientUnavailable();
+ callbacks.onUnavailable();
return;
}
WindowState topWindow = null;
if (behindClient != null) {
- topWindow = windowForClientLocked(null, behindClient, /* throwOnError*/ true);
+ topWindow = windowForClientLocked(null, behindClient, /* throwOnError*/ false);
}
WindowState targetWindow = dc.findScrollCaptureTargetWindow(topWindow, taskId);
if (targetWindow == null) {
- controller.onClientUnavailable();
+ callbacks.onUnavailable();
return;
}
// Forward to the window for handling.
try {
- targetWindow.mClient.requestScrollCapture(controller);
+ targetWindow.mClient.requestScrollCapture(callbacks);
} catch (RemoteException e) {
ProtoLog.w(WM_ERROR,
"requestScrollCapture: caught exception dispatching to window."
+ "token=%s", targetWindow.mClient.asBinder());
- controller.onClientUnavailable();
+ callbacks.onUnavailable();
}
}
} catch (RemoteException e) {
@@ -8244,9 +8247,9 @@ public class WindowManagerService extends IWindowManager.Stub
}
@Override
- public boolean getWindowInsets(WindowManager.LayoutParams attrs,
- int displayId, Rect outContentInsets, Rect outStableInsets,
+ public boolean getWindowInsets(WindowManager.LayoutParams attrs, int displayId,
DisplayCutout.ParcelableWrapper outDisplayCutout, InsetsState outInsetsState) {
+ final boolean fromLocal = Binder.getCallingPid() == myPid();
final long origId = Binder.clearCallingIdentity();
try {
synchronized (mGlobalLock) {
@@ -8256,13 +8259,8 @@ public class WindowManagerService extends IWindowManager.Stub
+ "could not be found!");
}
final WindowToken windowToken = dc.getWindowToken(attrs.token);
- final InsetsStateController insetsStateController =
- dc.getInsetsStateController();
- outInsetsState.set(insetsStateController.getInsetsForWindowMetrics(attrs));
-
return dc.getDisplayPolicy().getLayoutHint(attrs, windowToken,
- mTmpRect /* outFrame */, outContentInsets, outStableInsets,
- outDisplayCutout);
+ mTmpRect /* outFrame */, outDisplayCutout, outInsetsState, fromLocal);
}
} finally {
Binder.restoreCallingIdentity(origId);
diff --git a/services/core/java/com/android/server/wm/WindowOrganizerController.java b/services/core/java/com/android/server/wm/WindowOrganizerController.java
index 5e07f5187c54..ae152d253d17 100644
--- a/services/core/java/com/android/server/wm/WindowOrganizerController.java
+++ b/services/core/java/com/android/server/wm/WindowOrganizerController.java
@@ -57,7 +57,6 @@ import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
-import java.util.Set;
/**
* Server side implementation for the interface for organizing windows
@@ -84,7 +83,6 @@ class WindowOrganizerController extends IWindowOrganizerController.Stub
private final ActivityTaskManagerService mService;
private final WindowManagerGlobalLock mGlobalLock;
- private final BLASTSyncEngine mBLASTSyncEngine = new BLASTSyncEngine();
private final HashMap<Integer, IWindowContainerTransactionCallback>
mTransactionCallbacksByPendingSyncId = new HashMap();
@@ -505,7 +503,7 @@ class WindowOrganizerController extends IWindowOrganizerController.Stub
@VisibleForTesting
int startSyncWithOrganizer(IWindowContainerTransactionCallback callback) {
- int id = mBLASTSyncEngine.startSyncSet(this);
+ int id = mService.mWindowManager.mSyncEngine.startSyncSet(this);
mTransactionCallbacksByPendingSyncId.put(id, callback);
return id;
}
@@ -513,31 +511,26 @@ class WindowOrganizerController extends IWindowOrganizerController.Stub
@VisibleForTesting
void setSyncReady(int id) {
ProtoLog.v(WM_DEBUG_WINDOW_ORGANIZER, "Set sync ready, syncId=%d", id);
- mBLASTSyncEngine.setReady(id);
+ mService.mWindowManager.mSyncEngine.setReady(id);
}
@VisibleForTesting
void addToSyncSet(int syncId, WindowContainer wc) {
- mBLASTSyncEngine.addToSyncSet(syncId, wc);
+ mService.mWindowManager.mSyncEngine.addToSyncSet(syncId, wc);
}
@Override
- public void onTransactionReady(int syncId, Set<WindowContainer> windowContainersReady) {
+ public void onTransactionReady(int syncId, SurfaceControl.Transaction t) {
ProtoLog.v(WM_DEBUG_WINDOW_ORGANIZER, "Transaction ready, syncId=%d", syncId);
final IWindowContainerTransactionCallback callback =
mTransactionCallbacksByPendingSyncId.get(syncId);
- SurfaceControl.Transaction mergedTransaction = new SurfaceControl.Transaction();
- for (WindowContainer container : windowContainersReady) {
- container.mergeBlastSyncTransaction(mergedTransaction);
- }
-
try {
- callback.onTransactionReady(syncId, mergedTransaction);
+ callback.onTransactionReady(syncId, t);
} catch (RemoteException e) {
// If there's an exception when trying to send the mergedTransaction to the client, we
// should immediately apply it here so the transactions aren't lost.
- mergedTransaction.apply();
+ t.apply();
}
mTransactionCallbacksByPendingSyncId.remove(syncId);
diff --git a/services/core/java/com/android/server/wm/WindowState.java b/services/core/java/com/android/server/wm/WindowState.java
index 90c3d6cb85af..a4b4fcb79656 100644
--- a/services/core/java/com/android/server/wm/WindowState.java
+++ b/services/core/java/com/android/server/wm/WindowState.java
@@ -251,10 +251,8 @@ import com.android.server.wm.utils.WmDisplayCutout;
import java.io.PrintWriter;
import java.lang.ref.WeakReference;
import java.util.ArrayList;
-import java.util.Collections;
import java.util.Comparator;
import java.util.List;
-import java.util.Set;
import java.util.function.Predicate;
/** A window in the window manager. */
@@ -658,15 +656,6 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP
private static final StringBuilder sTmpSB = new StringBuilder();
/**
- * Whether the next surfacePlacement call should notify that the blast sync is ready.
- * This is set to true when {@link #finishDrawing(Transaction)} is called so
- * {@link #onTransactionReady(int, Set)} is called after the next surfacePlacement. This allows
- * Transactions to get flushed into the syncTransaction before notifying {@link BLASTSyncEngine}
- * that this WindowState is ready.
- */
- private boolean mNotifyBlastOnSurfacePlacement;
-
- /**
* Compares two window sub-layers and returns -1 if the first is lesser than the second in terms
* of z-order and 1 otherwise.
*/
@@ -706,15 +695,6 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP
*/
int mFrameRateSelectionPriority = RefreshRatePolicy.LAYER_PRIORITY_UNSET;
- /**
- * BLASTSyncEngine ID corresponding to a sync-set for all
- * our children. We add our children to this set in Sync,
- * but we save it and don't mark it as ready until finishDrawing
- * this way we have a two way latch between all our children finishing
- * and drawing ourselves.
- */
- private int mLocalSyncId = -1;
-
static final int BLAST_TIMEOUT_DURATION = 5000; /* milliseconds */
private final WindowProcessController mWpcForDisplayConfigChanges;
@@ -977,16 +957,20 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP
mSession.windowAddedLocked(mAttrs.packageName);
}
+ boolean inSizeCompatMode() {
+ return inSizeCompatMode(mAttrs, mActivityRecord);
+ }
+
/**
* @return {@code true} if the application runs in size compatibility mode.
* @see android.content.res.CompatibilityInfo#supportsScreen
- * @see ActivityRecord#inSizeCompatMode
+ * @see ActivityRecord#inSizeCompatMode()
*/
- boolean inSizeCompatMode() {
- return (mAttrs.privateFlags & PRIVATE_FLAG_COMPATIBLE_WINDOW) != 0
- || (mActivityRecord != null && mActivityRecord.hasSizeCompatBounds()
- // Exclude starting window because it is not displayed by the application.
- && mAttrs.type != TYPE_APPLICATION_STARTING);
+ static boolean inSizeCompatMode(WindowManager.LayoutParams attrs, WindowToken windowToken) {
+ return (attrs.privateFlags & PRIVATE_FLAG_COMPATIBLE_WINDOW) != 0
+ || (windowToken != null && windowToken.hasSizeCompatBounds()
+ // Exclude starting window because it is not displayed by the application.
+ && attrs.type != TYPE_APPLICATION_STARTING);
}
/**
@@ -1224,14 +1208,8 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP
Math.min(windowFrames.mStableFrame.bottom, windowFrames.mFrame.bottom));
}
- if (mAttrs.type == TYPE_DOCK_DIVIDER) {
- final WmDisplayCutout c = windowFrames.mDisplayCutout.calculateRelativeTo(
- windowFrames.mDisplayFrame);
- windowFrames.calculateDockedDividerInsets(c.getDisplayCutout().getSafeInsets());
- } else {
- windowFrames.calculateInsets(windowsAreFloating, isFullscreenAndFillsDisplay,
- getDisplayFrames(dc.mDisplayFrames).mUnrestricted);
- }
+ windowFrames.calculateInsets(windowsAreFloating, isFullscreenAndFillsDisplay,
+ getDisplayFrames(dc.mDisplayFrames).mUnrestricted);
windowFrames.setDisplayCutout(
windowFrames.mDisplayCutout.calculateRelativeTo(windowFrames.mFrame));
@@ -1545,7 +1523,12 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP
* modification according to the state of transient bars.
*/
InsetsState getInsetsState() {
- return getDisplayContent().getInsetsPolicy().getInsetsForDispatch(this);
+ InsetsState state = getDisplayContent().getInsetsPolicy().getInsetsForWindow(this);
+ if (inSizeCompatMode()) {
+ state = new InsetsState(state, true);
+ state.scale(mInvGlobalScale);
+ }
+ return state;
}
@Override
@@ -2228,7 +2211,6 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP
void removeIfPossible() {
super.removeIfPossible();
removeIfPossible(false /*keepVisibleDeadWindow*/);
- immediatelyNotifyBlastSync();
}
private void removeIfPossible(boolean keepVisibleDeadWindow) {
@@ -3057,7 +3039,7 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP
}
void setForceHideNonSystemOverlayWindowIfNeeded(boolean forceHide) {
- if (mOwnerCanAddInternalSystemWindow
+ if (!mSession.mOverlaysCanBeHidden
|| (!isSystemAlertWindowType(mAttrs.type) && mAttrs.type != TYPE_TOAST)) {
return;
}
@@ -3607,11 +3589,6 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP
backdropFrame.set(0, 0, displayInfo.logicalWidth, displayInfo.logicalHeight);
}
outFrames.displayCutout.set(mWindowFrames.mDisplayCutout.getDisplayCutout());
-
- // TODO(b/149813814): Remove legacy insets.
- outFrames.contentInsets.set(mWindowFrames.mLastContentInsets);
- outFrames.visibleInsets.set(mWindowFrames.mLastVisibleInsets);
- outFrames.stableInsets.set(mWindowFrames.mLastStableInsets);
}
void reportResized() {
@@ -5330,7 +5307,6 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP
updateFrameRateSelectionPriorityIfNeeded();
mWinAnimator.prepareSurfaceLocked(SurfaceControl.getGlobalTransaction(), true);
- notifyBlastSyncTransaction();
super.prepareSurfaces();
}
@@ -5644,7 +5620,7 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP
* into the state of the control target.
*
* @param insetProvider the provider which should not be visible to the client.
- * @see InsetsStateController#getInsetsForDispatch(WindowState)
+ * @see InsetsStateController#getInsetsForWindow(WindowState)
*/
void setControllableInsetProvider(InsetsSourceProvider insetProvider) {
mControllableInsetProvider = insetProvider;
@@ -5761,13 +5737,6 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP
void setViewVisibility(int viewVisibility) {
mViewVisibility = viewVisibility;
- // The viewVisibility is set to GONE with a client request to relayout. If this occurs and
- // there's a blast sync transaction waiting, finishDrawing will never be called since the
- // client will not render when visibility is GONE. Therefore, call finishDrawing here to
- // prevent system server from blocking on a window that will not draw.
- if (viewVisibility == View.GONE && mUsingBLASTSyncTransaction) {
- immediatelyNotifyBlastSync();
- }
}
SurfaceControl getClientViewRootSurface() {
@@ -5775,86 +5744,57 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP
}
@Override
- boolean prepareForSync(BLASTSyncEngine.TransactionReadyListener waitingListener,
- int waitingId) {
- // If the window is goneForLayout, relayout won't be called so we'd just wait forever.
- if (isGoneForLayout()) {
- return false;
- }
- boolean willSync = setPendingListener(waitingListener, waitingId);
- if (!willSync) {
+ boolean prepareSync() {
+ if (!super.prepareSync()) {
return false;
}
- requestRedrawForSync();
-
- mLocalSyncId = mBLASTSyncEngine.startSyncSet(this);
- addChildrenToSyncSet(mLocalSyncId);
-
// In the WindowContainer implementation we immediately mark ready
// since a generic WindowContainer only needs to wait for its
// children to finish and is immediately ready from its own
// perspective but at the WindowState level we need to wait for ourselves
- // to draw even if the children draw first our don't need to sync, so we omit
- // the set ready call until later in finishDrawing()
+ // to draw even if the children draw first our don't need to sync, so we start
+ // in WAITING state rather than READY.
+ mSyncState = SYNC_STATE_WAITING_FOR_DRAW;
+ requestRedrawForSync();
+
mWmService.mH.removeMessages(WINDOW_STATE_BLAST_SYNC_TIMEOUT, this);
mWmService.mH.sendNewMessageDelayed(WINDOW_STATE_BLAST_SYNC_TIMEOUT, this,
BLAST_TIMEOUT_DURATION);
-
return true;
}
boolean finishDrawing(SurfaceControl.Transaction postDrawTransaction) {
- if (!mUsingBLASTSyncTransaction) {
+ if (!onSyncFinishedDrawing()) {
return mWinAnimator.finishDrawingLocked(postDrawTransaction);
}
if (postDrawTransaction != null) {
- mBLASTSyncTransaction.merge(postDrawTransaction);
+ mSyncTransaction.merge(postDrawTransaction);
}
- mNotifyBlastOnSurfacePlacement = true;
mWinAnimator.finishDrawingLocked(null);
// We always want to force a traversal after a finish draw for blast sync.
return true;
}
- private void notifyBlastSyncTransaction() {
+ void immediatelyNotifyBlastSync() {
+ finishDrawing(null);
mWmService.mH.removeMessages(WINDOW_STATE_BLAST_SYNC_TIMEOUT, this);
-
- if (!mNotifyBlastOnSurfacePlacement || mWaitingListener == null) {
- mNotifyBlastOnSurfacePlacement = false;
- return;
- }
+ if (!useBLASTSync()) return;
final Task task = getTask();
if (task != null) {
final SurfaceControl.Transaction t = task.getMainWindowSizeChangeTransaction();
if (t != null) {
- mBLASTSyncTransaction.merge(t);
+ mSyncTransaction.merge(t);
}
task.setMainWindowSizeChangeTransaction(null);
}
-
- // If localSyncId is >0 then we are syncing with children and will
- // invoke transaction ready from our own #transactionReady callback
- // we just need to signal our side of the sync (setReady). But if we
- // have no sync operation at this level transactionReady will never
- // be invoked and we need to invoke it ourself.
- if (mLocalSyncId >= 0) {
- mBLASTSyncEngine.setReady(mLocalSyncId);
- return;
- }
-
- mWaitingListener.onTransactionReady(mWaitingSyncId, Collections.singleton(this));
-
- mWaitingSyncId = 0;
- mWaitingListener = null;
- mNotifyBlastOnSurfacePlacement = false;
}
- void immediatelyNotifyBlastSync() {
- finishDrawing(null);
- notifyBlastSyncTransaction();
+ @Override
+ boolean fillsParent() {
+ return mAttrs.type == TYPE_APPLICATION_STARTING;
}
/**
diff --git a/services/core/java/com/android/server/wm/WindowStateAnimator.java b/services/core/java/com/android/server/wm/WindowStateAnimator.java
index 972d0d46cec0..0111d4883eea 100644
--- a/services/core/java/com/android/server/wm/WindowStateAnimator.java
+++ b/services/core/java/com/android/server/wm/WindowStateAnimator.java
@@ -859,6 +859,7 @@ class WindowStateAnimator {
if (displayed) {
w.mToken.hasVisible = true;
+ mSurfaceController.setBackgroundBlurRadius(w.mAttrs.backgroundBlurRadius);
}
}
diff --git a/services/core/java/com/android/server/wm/WindowSurfaceController.java b/services/core/java/com/android/server/wm/WindowSurfaceController.java
index feecda79b6d7..21cb9a74c74e 100644
--- a/services/core/java/com/android/server/wm/WindowSurfaceController.java
+++ b/services/core/java/com/android/server/wm/WindowSurfaceController.java
@@ -63,6 +63,8 @@ class WindowSurfaceController {
private float mLastDsdy = 0;
private float mLastDtdy = 1;
+ private int mLastBackgroundBlurRadius = 0;
+
private float mSurfaceAlpha = 0;
private int mSurfaceLayer = 0;
@@ -268,6 +270,26 @@ class WindowSurfaceController {
}
}
+ void setBackgroundBlurRadius(int radius) {
+ ProtoLog.i(WM_SHOW_TRANSACTIONS, "SURFACE backgroundBlur=%o: %s", radius, title);
+
+ if (mSurfaceControl == null || radius == mLastBackgroundBlurRadius) {
+ return;
+ }
+ mLastBackgroundBlurRadius = radius;
+
+ if (SHOW_LIGHT_TRANSACTIONS) Slog.i(TAG, ">>> OPEN TRANSACTION setBackgroundBlurRadius");
+ mService.openSurfaceTransaction();
+ try {
+ mSurfaceControl.setBackgroundBlurRadius(radius);
+ } finally {
+ mService.closeSurfaceTransaction("setBackgroundBlurRadius");
+ if (SHOW_LIGHT_TRANSACTIONS) {
+ Slog.i(TAG, "<<< CLOSE TRANSACTION setBackgroundBlurRadius");
+ }
+ }
+ }
+
void setSecure(boolean isSecure) {
ProtoLog.i(WM_SHOW_TRANSACTIONS, "SURFACE isSecure=%b: %s", isSecure, title);
diff --git a/services/core/java/com/android/server/wm/WindowToken.java b/services/core/java/com/android/server/wm/WindowToken.java
index fa0b8cce5f70..5ced6a52050b 100644
--- a/services/core/java/com/android/server/wm/WindowToken.java
+++ b/services/core/java/com/android/server/wm/WindowToken.java
@@ -335,6 +335,13 @@ class WindowToken extends WindowContainer<WindowState> {
}
/**
+ * @return {@code true} if this window token has bounds for size compatibility mode.
+ */
+ boolean hasSizeCompatBounds() {
+ return false;
+ }
+
+ /**
* Returns true if the new window is considered greater than the existing window in terms of
* z-order.
*/
diff --git a/services/core/jni/Android.bp b/services/core/jni/Android.bp
index 30f6fa68396e..d6a56ba531d0 100644
--- a/services/core/jni/Android.bp
+++ b/services/core/jni/Android.bp
@@ -21,6 +21,7 @@ cc_library_static {
"BroadcastRadio/TunerCallback.cpp",
"BroadcastRadio/convert.cpp",
"BroadcastRadio/regions.cpp",
+ "gnss/GnssConfiguration.cpp",
"stats/PowerStatsPuller.cpp",
"stats/SubsystemSleepStatePuller.cpp",
"com_android_server_adb_AdbDebuggingManager.cpp",
diff --git a/services/core/jni/com_android_server_SystemServer.cpp b/services/core/jni/com_android_server_SystemServer.cpp
index 76b171337bb9..43f50bfc33d5 100644
--- a/services/core/jni/com_android_server_SystemServer.cpp
+++ b/services/core/jni/com_android_server_SystemServer.cpp
@@ -23,6 +23,7 @@
#include <jni.h>
#include <nativehelper/JNIHelp.h>
+#include <android/hidl/manager/1.2/IServiceManager.h>
#include <binder/IServiceManager.h>
#include <hidl/HidlTransportSupport.h>
#include <incremental_service.h>
@@ -64,6 +65,7 @@ static void android_server_SystemServer_startHidlServices(JNIEnv* env, jobject /
using ::android::frameworks::stats::V1_0::IStats;
using ::android::frameworks::stats::V1_0::implementation::StatsHal;
using ::android::hardware::configureRpcThreadpool;
+ using ::android::hidl::manager::V1_0::IServiceManager;
status_t err;
@@ -74,15 +76,22 @@ static void android_server_SystemServer_startHidlServices(JNIEnv* env, jobject /
sp<ISensorManager> sensorService = new SensorManager(vm);
err = sensorService->registerAsService();
- ALOGE_IF(err != OK, "Cannot register %s: %d", ISensorManager::descriptor, err);
+ LOG_ALWAYS_FATAL_IF(err != OK, "Cannot register %s: %d", ISensorManager::descriptor, err);
sp<ISchedulingPolicyService> schedulingService = new SchedulingPolicyService();
- err = schedulingService->registerAsService();
- ALOGE_IF(err != OK, "Cannot register %s: %d", ISchedulingPolicyService::descriptor, err);
+ if (IServiceManager::Transport::HWBINDER ==
+ hardware::defaultServiceManager1_2()->getTransport(ISchedulingPolicyService::descriptor,
+ "default")) {
+ err = schedulingService->registerAsService("default");
+ LOG_ALWAYS_FATAL_IF(err != OK, "Cannot register %s: %d",
+ ISchedulingPolicyService::descriptor, err);
+ } else {
+ ALOGW("%s is deprecated. Skipping registration.", ISchedulingPolicyService::descriptor);
+ }
sp<IStats> statsHal = new StatsHal();
err = statsHal->registerAsService();
- ALOGE_IF(err != OK, "Cannot register %s: %d", IStats::descriptor, err);
+ LOG_ALWAYS_FATAL_IF(err != OK, "Cannot register %s: %d", IStats::descriptor, err);
}
static void android_server_SystemServer_initZygoteChildHeapProfiling(JNIEnv* /* env */,
diff --git a/services/core/jni/com_android_server_location_GnssLocationProvider.cpp b/services/core/jni/com_android_server_location_GnssLocationProvider.cpp
index 31b9ad617fba..e9d048a69966 100644
--- a/services/core/jni/com_android_server_location_GnssLocationProvider.cpp
+++ b/services/core/jni/com_android_server_location_GnssLocationProvider.cpp
@@ -14,8 +14,8 @@
* limitations under the License.
*/
-#define LOG_TAG "GnssLocationProvider"
-
+// Define LOG_TAG and LOG_NDEBUG before <log/log.h> to overwrite the default values.
+#define LOG_TAG "GnssLocationProviderJni"
#define LOG_NDEBUG 0
#include <android/hardware/gnss/1.0/IGnss.h>
@@ -39,6 +39,7 @@
#include <nativehelper/JNIHelp.h>
#include "android_runtime/AndroidRuntime.h"
#include "android_runtime/Log.h"
+#include "gnss/GnssConfiguration.h"
#include "hardware_legacy/power.h"
#include "jni.h"
#include "utils/Log.h"
@@ -59,7 +60,6 @@ static jclass class_gnssMeasurement;
static jclass class_location;
static jclass class_gnssNavigationMessage;
static jclass class_gnssClock;
-static jclass class_gnssConfiguration_halInterfaceVersion;
static jclass class_gnssAntennaInfoBuilder;
static jclass class_phaseCenterOffset;
static jclass class_sphericalCorrections;
@@ -125,7 +125,6 @@ static jmethodID method_locationCtor;
static jmethodID method_gnssNavigationMessageCtor;
static jmethodID method_gnssClockCtor;
static jmethodID method_gnssMeasurementCtor;
-static jmethodID method_halInterfaceVersionCtor;
static jmethodID method_gnssAntennaInfoBuilderCtor;
static jmethodID method_phaseCenterOffsetCtor;
static jmethodID method_sphericalCorrectionsCtor;
@@ -149,6 +148,7 @@ using android::status_t;
using android::String16;
using android::wp;
using android::binder::Status;
+using android::gnss::GnssConfigurationInterface;
using android::hardware::Return;
using android::hardware::Void;
@@ -192,10 +192,6 @@ using IGnss_V3_0 = android::hardware::gnss::V3_0::IGnss;
using IGnssCallback_V1_0 = android::hardware::gnss::V1_0::IGnssCallback;
using IGnssCallback_V2_0 = android::hardware::gnss::V2_0::IGnssCallback;
using IGnssCallback_V2_1 = android::hardware::gnss::V2_1::IGnssCallback;
-using IGnssConfiguration_V1_0 = android::hardware::gnss::V1_0::IGnssConfiguration;
-using IGnssConfiguration_V1_1 = android::hardware::gnss::V1_1::IGnssConfiguration;
-using IGnssConfiguration_V2_0 = android::hardware::gnss::V2_0::IGnssConfiguration;
-using IGnssConfiguration_V2_1 = android::hardware::gnss::V2_1::IGnssConfiguration;
using IGnssDebug_V1_0 = android::hardware::gnss::V1_0::IGnssDebug;
using IGnssDebug_V2_0 = android::hardware::gnss::V2_0::IGnssDebug;
using IGnssAntennaInfo = android::hardware::gnss::V2_1::IGnssAntennaInfo;
@@ -269,11 +265,6 @@ sp<IGnssBatching_V1_0> gnssBatchingIface = nullptr;
sp<IGnssBatching_V2_0> gnssBatchingIface_V2_0 = nullptr;
sp<IGnssDebug_V1_0> gnssDebugIface = nullptr;
sp<IGnssDebug_V2_0> gnssDebugIface_V2_0 = nullptr;
-sp<IGnssConfigurationAidl> gnssConfigurationAidlIface = nullptr;
-sp<IGnssConfiguration_V1_0> gnssConfigurationIface = nullptr;
-sp<IGnssConfiguration_V1_1> gnssConfigurationIface_V1_1 = nullptr;
-sp<IGnssConfiguration_V2_0> gnssConfigurationIface_V2_0 = nullptr;
-sp<IGnssConfiguration_V2_1> gnssConfigurationIface_V2_1 = nullptr;
sp<IGnssNi> gnssNiIface = nullptr;
sp<IGnssMeasurement_V1_0> gnssMeasurementIface = nullptr;
sp<IGnssMeasurement_V1_1> gnssMeasurementIface_V1_1 = nullptr;
@@ -285,6 +276,8 @@ sp<IMeasurementCorrections_V1_1> gnssCorrectionsIface_V1_1 = nullptr;
sp<IGnssVisibilityControl> gnssVisibilityControlIface = nullptr;
sp<IGnssAntennaInfo> gnssAntennaInfoIface = nullptr;
+std::unique_ptr<GnssConfigurationInterface> gnssConfigurationIface = nullptr;
+
#define WAKE_LOCK_NAME "GPS"
namespace android {
@@ -467,12 +460,6 @@ static jboolean checkAidlStatus(const Status& status, const char* errorMessage)
return JNI_TRUE;
}
-static jobject createHalInterfaceVersionJavaObject(JNIEnv* env, jint major, jint minor) {
- jobject version = env->NewObject(class_gnssConfiguration_halInterfaceVersion,
- method_halInterfaceVersionCtor, major, minor);
- return version;
-}
-
struct ScopedJniString {
ScopedJniString(JNIEnv* env, jstring javaString) : mEnv(env), mJavaString(javaString) {
mNativeString = mEnv->GetStringUTFChars(mJavaString, nullptr);
@@ -2159,13 +2146,6 @@ static void android_location_GnssNative_class_init_once(JNIEnv* env, jclass claz
class_gnssClock = (jclass) env->NewGlobalRef(gnssClockClass);
method_gnssClockCtor = env->GetMethodID(class_gnssClock, "<init>", "()V");
- jclass gnssConfiguration_halInterfaceVersionClass = env->FindClass(
- "com/android/server/location/gnss/GnssConfiguration$HalInterfaceVersion");
- class_gnssConfiguration_halInterfaceVersion =
- (jclass) env->NewGlobalRef(gnssConfiguration_halInterfaceVersionClass);
- method_halInterfaceVersionCtor =
- env->GetMethodID(class_gnssConfiguration_halInterfaceVersion, "<init>", "(II)V");
-
jclass arrayListClass = env->FindClass("java/util/ArrayList");
class_arrayList = (jclass)env->NewGlobalRef(arrayListClass);
method_arrayListCtor = env->GetMethodID(class_arrayList, "<init>", "()V");
@@ -2173,6 +2153,8 @@ static void android_location_GnssNative_class_init_once(JNIEnv* env, jclass claz
jclass doubleArrayClass = env->FindClass("[D");
class_doubleArray = (jclass)env->NewGlobalRef(doubleArrayClass);
+
+ gnss::GnssConfiguration_class_init_once(env);
}
/* Initialization needed at system boot and whenever GNSS service dies. */
@@ -2373,44 +2355,38 @@ static void android_location_GnssNative_init_once(JNIEnv* env, jobject obj,
if (gnssHalAidl != nullptr) {
sp<IGnssConfigurationAidl> gnssConfigurationAidl;
auto status = gnssHalAidl->getExtensionGnssConfiguration(&gnssConfigurationAidl);
- if (status.isOk()) {
- gnssConfigurationAidlIface = gnssConfigurationAidl;
- } else {
- ALOGD("Unable to get a handle to GnssConfiguration AIDL interface.");
+ if (checkAidlStatus(status,
+ "Unable to get a handle to GnssConfiguration AIDL interface.")) {
+ gnssConfigurationIface =
+ std::make_unique<android::gnss::GnssConfiguration>(gnssConfigurationAidl);
}
} else if (gnssHal_V2_1 != nullptr) {
auto gnssConfiguration = gnssHal_V2_1->getExtensionGnssConfiguration_2_1();
- if (!gnssConfiguration.isOk()) {
- ALOGD("Unable to get a handle to GnssConfiguration_V2_1");
- } else {
- gnssConfigurationIface_V2_1 = gnssConfiguration;
- gnssConfigurationIface_V2_0 = gnssConfigurationIface_V2_1;
- gnssConfigurationIface_V1_1 = gnssConfigurationIface_V2_1;
- gnssConfigurationIface = gnssConfigurationIface_V2_1;
+ if (checkHidlReturn(gnssConfiguration,
+ "Unable to get a handle to GnssConfiguration_V2_1")) {
+ gnssConfigurationIface =
+ std::make_unique<android::gnss::GnssConfiguration_V2_1>(gnssConfiguration);
}
} else if (gnssHal_V2_0 != nullptr) {
auto gnssConfiguration = gnssHal_V2_0->getExtensionGnssConfiguration_2_0();
- if (!gnssConfiguration.isOk()) {
- ALOGD("Unable to get a handle to GnssConfiguration_V2_0");
- } else {
- gnssConfigurationIface_V2_0 = gnssConfiguration;
- gnssConfigurationIface_V1_1 = gnssConfigurationIface_V2_0;
- gnssConfigurationIface = gnssConfigurationIface_V2_0;
+ if (checkHidlReturn(gnssConfiguration,
+ "Unable to get a handle to GnssConfiguration_V2_0")) {
+ gnssConfigurationIface =
+ std::make_unique<android::gnss::GnssConfiguration_V2_0>(gnssConfiguration);
}
} else if (gnssHal_V1_1 != nullptr) {
auto gnssConfiguration = gnssHal_V1_1->getExtensionGnssConfiguration_1_1();
- if (!gnssConfiguration.isOk()) {
- ALOGD("Unable to get a handle to GnssConfiguration_V1_1");
- } else {
- gnssConfigurationIface_V1_1 = gnssConfiguration;
- gnssConfigurationIface = gnssConfigurationIface_V1_1;
+ if (checkHidlReturn(gnssConfiguration,
+ "Unable to get a handle to GnssConfiguration_V1_1")) {
+ gnssConfigurationIface =
+ std::make_unique<android::gnss::GnssConfiguration_V1_1>(gnssConfiguration);
}
} else {
- auto gnssConfiguration_V1_0 = gnssHal->getExtensionGnssConfiguration();
- if (!gnssConfiguration_V1_0.isOk()) {
- ALOGD("Unable to get a handle to GnssConfiguration");
- } else {
- gnssConfigurationIface = gnssConfiguration_V1_0;
+ auto gnssConfiguration = gnssHal->getExtensionGnssConfiguration();
+ if (checkHidlReturn(gnssConfiguration,
+ "Unable to get a handle to GnssConfiguration_V1_0")) {
+ gnssConfigurationIface =
+ std::make_unique<android::gnss::GnssConfiguration_V1_0>(gnssConfiguration);
}
}
@@ -2466,25 +2442,10 @@ static jboolean android_location_GnssNetworkConnectivityHandler_is_agps_ril_supp
static jobject android_location_GnssConfiguration_get_gnss_configuration_version(
JNIEnv* env, jclass /* jclazz */) {
- jint major, minor;
- if (gnssConfigurationIface_V2_1 != nullptr) {
- major = 2;
- minor = 1;
- }
- else if (gnssConfigurationIface_V2_0 != nullptr) {
- major = 2;
- minor = 0;
- } else if (gnssConfigurationIface_V1_1 != nullptr) {
- major = 1;
- minor = 1;
- } else if (gnssConfigurationIface != nullptr) {
- major = 1;
- minor = 0;
- } else {
+ if (gnssConfigurationIface == nullptr) {
return nullptr;
}
-
- return createHalInterfaceVersionJavaObject(env, major, minor);
+ return gnssConfigurationIface->getVersion(env);
}
/* Initialization needed each time the GPS service is shutdown. */
@@ -3486,203 +3447,89 @@ static jboolean android_location_GnssNavigationMessageProvider_stop_navigation_m
static jboolean android_location_GnssConfiguration_set_emergency_supl_pdn(JNIEnv*,
jobject,
jint emergencySuplPdn) {
- if (gnssConfigurationIface == nullptr && gnssConfigurationAidlIface == nullptr) {
+ if (gnssConfigurationIface == nullptr) {
ALOGE("%s: IGnssConfiguration interface not available.", __func__);
return JNI_FALSE;
}
-
- if (gnssConfigurationAidlIface != nullptr) {
- auto status = gnssConfigurationAidlIface->setEmergencySuplPdn(emergencySuplPdn);
- return checkAidlStatus(status, "gnssConfigurationAidlIface setEmergencySuplPdn() failed.");
- }
-
- auto result = gnssConfigurationIface->setEmergencySuplPdn(emergencySuplPdn);
- return checkHidlReturn(result, "IGnssConfiguration setEmergencySuplPdn() failed.");
+ return gnssConfigurationIface->setEmergencySuplPdn(emergencySuplPdn);
}
static jboolean android_location_GnssConfiguration_set_supl_version(JNIEnv*,
jobject,
jint version) {
- if (gnssConfigurationIface == nullptr && gnssConfigurationAidlIface == nullptr) {
+ if (gnssConfigurationIface == nullptr) {
ALOGE("%s: IGnssConfiguration interface not available.", __func__);
return JNI_FALSE;
}
-
- if (gnssConfigurationAidlIface != nullptr) {
- auto status = gnssConfigurationAidlIface->setSuplVersion(version);
- return checkAidlStatus(status, "gnssConfigurationAidlIface setSuplVersion() failed.");
- }
-
- auto result = gnssConfigurationIface->setSuplVersion(version);
- return checkHidlReturn(result, "IGnssConfiguration setSuplVersion() failed.");
+ return gnssConfigurationIface->setSuplVersion(version);
}
static jboolean android_location_GnssConfiguration_set_supl_es(JNIEnv*,
jobject,
jint suplEs) {
- if (gnssConfigurationIface_V2_0 != nullptr || gnssConfigurationIface_V2_1 != nullptr ||
- gnssConfigurationAidlIface != nullptr) {
- ALOGI("Config parameter SUPL_ES is deprecated in IGnssConfiguration.hal version 2.0 and higher.");
- return JNI_FALSE;
- }
-
if (gnssConfigurationIface == nullptr) {
ALOGE("%s: IGnssConfiguration interface not available.", __func__);
return JNI_FALSE;
}
-
- auto result = gnssConfigurationIface->setSuplEs(suplEs);
- return checkHidlReturn(result, "IGnssConfiguration setSuplEs() failed.");
+ return gnssConfigurationIface->setSuplEs(suplEs);
}
static jboolean android_location_GnssConfiguration_set_supl_mode(JNIEnv*,
jobject,
jint mode) {
- if (gnssConfigurationIface == nullptr && gnssConfigurationAidlIface == nullptr) {
+ if (gnssConfigurationIface == nullptr) {
ALOGE("%s: IGnssConfiguration interface not available.", __func__);
return JNI_FALSE;
}
-
- if (gnssConfigurationAidlIface != nullptr) {
- auto status = gnssConfigurationAidlIface->setSuplMode(mode);
- return checkAidlStatus(status, "gnssConfigurationAidlIface setSuplMode() failed.");
- }
-
- auto result = gnssConfigurationIface->setSuplMode(mode);
- return checkHidlReturn(result, "IGnssConfiguration setSuplMode() failed.");
+ return gnssConfigurationIface->setSuplMode(mode);
}
static jboolean android_location_GnssConfiguration_set_gps_lock(JNIEnv*,
jobject,
jint gpsLock) {
- if (gnssConfigurationIface_V2_0 != nullptr || gnssConfigurationIface_V2_1 != nullptr ||
- gnssConfigurationAidlIface != nullptr) {
- ALOGI("Config parameter GPS_LOCK is deprecated in IGnssConfiguration.hal version 2.0.");
- return JNI_FALSE;
- }
-
if (gnssConfigurationIface == nullptr) {
ALOGE("%s: IGnssConfiguration interface not available.", __func__);
return JNI_FALSE;
}
-
- auto result = gnssConfigurationIface->setGpsLock(gpsLock);
- return checkHidlReturn(result, "IGnssConfiguration setGpsLock() failed.");
+ return gnssConfigurationIface->setGpsLock(gpsLock);
}
static jboolean android_location_GnssConfiguration_set_lpp_profile(JNIEnv*,
jobject,
jint lppProfile) {
- if (gnssConfigurationIface == nullptr && gnssConfigurationAidlIface == nullptr) {
+ if (gnssConfigurationIface == nullptr) {
ALOGE("%s: IGnssConfiguration interface not available.", __func__);
return JNI_FALSE;
}
-
- if (gnssConfigurationAidlIface != nullptr) {
- auto status = gnssConfigurationAidlIface->setLppProfile(lppProfile);
- return checkAidlStatus(status, "gnssConfigurationAidlIface setLppProfile() failed.");
- }
-
- auto result = gnssConfigurationIface->setLppProfile(lppProfile);
- return checkHidlReturn(result, "IGnssConfiguration setLppProfile() failed.");
+ return gnssConfigurationIface->setLppProfile(lppProfile);
}
static jboolean android_location_GnssConfiguration_set_gnss_pos_protocol_select(JNIEnv*,
jobject,
jint gnssPosProtocol) {
- if (gnssConfigurationIface == nullptr && gnssConfigurationAidlIface == nullptr) {
+ if (gnssConfigurationIface == nullptr) {
ALOGE("%s: IGnssConfiguration interface not available.", __func__);
return JNI_FALSE;
}
-
- if (gnssConfigurationAidlIface != nullptr) {
- auto status = gnssConfigurationAidlIface->setGlonassPositioningProtocol(gnssPosProtocol);
- return checkAidlStatus(status,
- "gnssConfigurationAidlIface setGlonassPositioningProtocol() "
- "failed.");
- }
-
- auto result = gnssConfigurationIface->setGlonassPositioningProtocol(gnssPosProtocol);
- return checkHidlReturn(result, "IGnssConfiguration setGlonassPositioningProtocol() failed.");
+ return gnssConfigurationIface->setGlonassPositioningProtocol(gnssPosProtocol);
}
static jboolean android_location_GnssConfiguration_set_satellite_blacklist(
JNIEnv* env, jobject, jintArray constellations, jintArray sv_ids) {
- if (gnssConfigurationIface_V1_1 == nullptr && gnssConfigurationIface_V2_1 == nullptr &&
- gnssConfigurationAidlIface == nullptr) {
+ if (gnssConfigurationIface == nullptr) {
ALOGI("IGnssConfiguration interface does not support satellite blacklist.");
return JNI_FALSE;
}
-
- jint *constellation_array = env->GetIntArrayElements(constellations, 0);
- if (nullptr == constellation_array) {
- ALOGI("GetIntArrayElements returns nullptr.");
- return JNI_FALSE;
- }
- jsize length = env->GetArrayLength(constellations);
-
- jint *sv_id_array = env->GetIntArrayElements(sv_ids, 0);
- if (nullptr == sv_id_array) {
- ALOGI("GetIntArrayElements returns nullptr.");
- return JNI_FALSE;
- }
-
- if (length != env->GetArrayLength(sv_ids)) {
- ALOGI("Lengths of constellations and sv_ids are inconsistent.");
- return JNI_FALSE;
- }
-
- if (gnssConfigurationAidlIface != nullptr) {
- std::vector<BlocklistedSource> sources;
- sources.resize(length);
-
- for (int i = 0; i < length; i++) {
- sources[i].constellation = static_cast<GnssConstellationType>(constellation_array[i]);
- sources[i].svid = sv_id_array[i];
- }
-
- auto status = gnssConfigurationAidlIface->setBlocklist(sources);
- return checkAidlStatus(status, "gnssConfigurationAidlIface setBlocklist() failed.");
- } else if (gnssConfigurationIface_V2_1 != nullptr) {
- hidl_vec<IGnssConfiguration_V2_1::BlacklistedSource> sources;
- sources.resize(length);
-
- for (int i = 0; i < length; i++) {
- sources[i].constellation = static_cast<GnssConstellationType_V2_0>(constellation_array[i]);
- sources[i].svid = sv_id_array[i];
- }
-
- auto result = gnssConfigurationIface_V2_1->setBlacklist_2_1(sources);
- return checkHidlReturn(result, "IGnssConfiguration_V2_1 setBlacklist_2_1() failed.");
- }
-
- hidl_vec<IGnssConfiguration_V1_1::BlacklistedSource> sources;
- sources.resize(length);
-
- for (int i = 0; i < length; i++) {
- sources[i].constellation = static_cast<GnssConstellationType_V1_0>(constellation_array[i]);
- sources[i].svid = sv_id_array[i];
- }
-
- auto result = gnssConfigurationIface_V1_1->setBlacklist(sources);
- return checkHidlReturn(result, "IGnssConfiguration setBlacklist() failed.");
+ return gnssConfigurationIface->setBlocklist(env, constellations, sv_ids);
}
static jboolean android_location_GnssConfiguration_set_es_extension_sec(
JNIEnv*, jobject, jint emergencyExtensionSeconds) {
- if (gnssConfigurationIface_V2_0 == nullptr && gnssConfigurationAidlIface == nullptr) {
- ALOGI("Config parameter ES_EXTENSION_SEC is not supported in IGnssConfiguration.hal"
- " versions earlier than 2.0.");
+ if (gnssConfigurationIface == nullptr) {
+ ALOGE("%s: IGnssConfiguration interface not available.", __func__);
return JNI_FALSE;
}
-
- if (gnssConfigurationAidlIface != nullptr) {
- auto status = gnssConfigurationAidlIface->setEsExtensionSec(emergencyExtensionSeconds);
- return checkAidlStatus(status, "gnssConfigurationAidlIface setEsExtensionSec() failed.");
- }
-
- auto result = gnssConfigurationIface_V2_0->setEsExtensionSec(emergencyExtensionSeconds);
- return checkHidlReturn(result, "IGnssConfiguration setEsExtensionSec() failed.");
+ return gnssConfigurationIface->setEsExtensionSec(emergencyExtensionSeconds);
}
static jint android_location_GnssBatchingProvider_get_batch_size(JNIEnv*, jclass) {
diff --git a/services/core/jni/gnss/GnssConfiguration.cpp b/services/core/jni/gnss/GnssConfiguration.cpp
new file mode 100644
index 000000000000..8610c75e7e76
--- /dev/null
+++ b/services/core/jni/gnss/GnssConfiguration.cpp
@@ -0,0 +1,264 @@
+/*
+ * 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.
+ */
+
+// Define LOG_TAG before <log/log.h> to overwrite the default value.
+#define LOG_TAG "GnssConfigurationJni"
+
+#include "GnssConfiguration.h"
+
+using android::hardware::gnss::GnssConstellationType;
+using GnssConstellationType_V1_0 = android::hardware::gnss::V1_0::GnssConstellationType;
+using GnssConstellationType_V2_0 = android::hardware::gnss::V2_0::GnssConstellationType;
+
+using android::binder::Status;
+using android::hardware::hidl_vec;
+using android::hardware::Return;
+
+using android::hardware::gnss::IGnssConfiguration;
+using IGnssConfiguration_V1_0 = android::hardware::gnss::V1_0::IGnssConfiguration;
+using IGnssConfiguration_V1_1 = android::hardware::gnss::V1_1::IGnssConfiguration;
+using IGnssConfiguration_V2_0 = android::hardware::gnss::V2_0::IGnssConfiguration;
+using IGnssConfiguration_V2_1 = android::hardware::gnss::V2_1::IGnssConfiguration;
+
+using android::hardware::gnss::BlocklistedSource;
+using BlocklistedSource_V1_1 = IGnssConfiguration_V1_1::BlacklistedSource;
+using BlocklistedSource_V2_1 = IGnssConfiguration_V2_1::BlacklistedSource;
+
+namespace {
+
+jclass class_gnssConfiguration_halInterfaceVersion;
+jmethodID method_halInterfaceVersionCtor;
+
+jboolean checkAidlStatus(const Status& status, const char* errorMessage) {
+ if (!status.isOk()) {
+ ALOGE("%s AIDL transport error: %s", errorMessage, status.toString8().c_str());
+ return JNI_FALSE;
+ }
+ return JNI_TRUE;
+}
+
+template <class T>
+inline void logHidlError(Return<T>& result, const char* errorMessage) {
+ ALOGE("%s HIDL transport error: %s", errorMessage, result.description().c_str());
+}
+
+template <class T>
+jboolean checkHidlReturn(Return<T>& result, const char* errorMessage) {
+ if (!result.isOk()) {
+ logHidlError(result, errorMessage);
+ return JNI_FALSE;
+ } else {
+ return JNI_TRUE;
+ }
+}
+
+jobject createHalInterfaceVersionJavaObject(JNIEnv* env, jint major, jint minor) {
+ return env->NewObject(class_gnssConfiguration_halInterfaceVersion,
+ method_halInterfaceVersionCtor, major, minor);
+}
+
+} // anonymous namespace
+
+namespace android::gnss {
+
+void GnssConfiguration_class_init_once(JNIEnv* env) {
+ jclass gnssConfiguration_halInterfaceVersionClass = env->FindClass(
+ "com/android/server/location/gnss/GnssConfiguration$HalInterfaceVersion");
+ class_gnssConfiguration_halInterfaceVersion =
+ (jclass)env->NewGlobalRef(gnssConfiguration_halInterfaceVersionClass);
+ method_halInterfaceVersionCtor =
+ env->GetMethodID(class_gnssConfiguration_halInterfaceVersion, "<init>", "(II)V");
+}
+
+// Implementation of GnssConfiguration (AIDL HAL)
+
+GnssConfiguration::GnssConfiguration(const sp<IGnssConfiguration>& iGnssConfiguration)
+ : mIGnssConfiguration(iGnssConfiguration) {}
+
+jobject GnssConfiguration::getVersion(JNIEnv* env) {
+ return createHalInterfaceVersionJavaObject(env, 3, 0);
+}
+
+jboolean GnssConfiguration::setEmergencySuplPdn(jint enable) {
+ auto status = mIGnssConfiguration->setEmergencySuplPdn(enable);
+ return checkAidlStatus(status, "IGnssConfiguration setEmergencySuplPdn() failed.");
+}
+
+jboolean GnssConfiguration::setSuplVersion(jint version) {
+ auto status = mIGnssConfiguration->setSuplVersion(version);
+ return checkAidlStatus(status, "IGnssConfiguration setSuplVersion() failed.");
+}
+
+jboolean GnssConfiguration::setSuplEs(jint enable) {
+ ALOGI("Config parameter SUPL_ES is deprecated in IGnssConfiguration AIDL HAL.");
+ return JNI_FALSE;
+}
+
+jboolean GnssConfiguration::setSuplMode(jint mode) {
+ auto status = mIGnssConfiguration->setSuplMode(mode);
+ return checkAidlStatus(status, "IGnssConfiguration setSuplMode() failed.");
+}
+
+jboolean GnssConfiguration::setGpsLock(jint gpsLock) {
+ ALOGI("Config parameter GPS_LOCK is not supported in IGnssConfiguration AIDL HAL.");
+ return JNI_FALSE;
+}
+
+jboolean GnssConfiguration::setLppProfile(jint lppProfile) {
+ auto status = mIGnssConfiguration->setLppProfile(lppProfile);
+ return checkAidlStatus(status, "IGnssConfiguration setLppProfile() failed.");
+}
+
+jboolean GnssConfiguration::setGlonassPositioningProtocol(jint gnssPosProtocol) {
+ auto status = mIGnssConfiguration->setGlonassPositioningProtocol(gnssPosProtocol);
+ return checkAidlStatus(status, "IGnssConfiguration setGlonassPositioningProtocol() failed.");
+}
+
+jboolean GnssConfiguration::setEsExtensionSec(jint emergencyExtensionSeconds) {
+ auto status = mIGnssConfiguration->setEsExtensionSec(emergencyExtensionSeconds);
+ return checkAidlStatus(status, "IGnssConfiguration setEsExtensionSec() failed.");
+}
+
+jboolean GnssConfiguration::setBlocklist(JNIEnv* env, jintArray& constellations,
+ jintArray& sv_ids) {
+ auto sources =
+ getBlocklistedSources<BlocklistedSource, GnssConstellationType>(env, constellations,
+ sv_ids);
+ auto status = mIGnssConfiguration->setBlocklist(sources);
+ return checkAidlStatus(status, "IGnssConfiguration setBlocklist() failed.");
+}
+
+// Implementation of GnssConfiguration_V1_0
+
+GnssConfiguration_V1_0::GnssConfiguration_V1_0(
+ const sp<IGnssConfiguration_V1_0>& iGnssConfiguration)
+ : mIGnssConfiguration_V1_0(iGnssConfiguration) {}
+
+jobject GnssConfiguration_V1_0::getVersion(JNIEnv* env) {
+ return createHalInterfaceVersionJavaObject(env, 1, 0);
+}
+
+jboolean GnssConfiguration_V1_0::setEmergencySuplPdn(jint enable) {
+ auto result = mIGnssConfiguration_V1_0->setEmergencySuplPdn(enable);
+ return checkHidlReturn(result, "IGnssConfiguration setEmergencySuplPdn() failed.");
+}
+
+jboolean GnssConfiguration_V1_0::setSuplVersion(jint version) {
+ auto result = mIGnssConfiguration_V1_0->setSuplVersion(version);
+ return checkHidlReturn(result, "IGnssConfiguration setSuplVersion() failed.");
+}
+
+jboolean GnssConfiguration_V1_0::setSuplEs(jint enable) {
+ auto result = mIGnssConfiguration_V1_0->setSuplEs(enable);
+ return checkHidlReturn(result, "IGnssConfiguration setSuplEs() failed.");
+}
+
+jboolean GnssConfiguration_V1_0::setSuplMode(jint mode) {
+ auto result = mIGnssConfiguration_V1_0->setSuplMode(mode);
+ return checkHidlReturn(result, "IGnssConfiguration setSuplMode() failed.");
+}
+
+jboolean GnssConfiguration_V1_0::setGpsLock(jint gpsLock) {
+ auto result = mIGnssConfiguration_V1_0->setGpsLock(gpsLock);
+ return checkHidlReturn(result, "IGnssConfiguration setGpsLock() failed.");
+}
+
+jboolean GnssConfiguration_V1_0::setLppProfile(jint lppProfile) {
+ auto result = mIGnssConfiguration_V1_0->setLppProfile(lppProfile);
+ return checkHidlReturn(result, "IGnssConfiguration setLppProfile() failed.");
+}
+
+jboolean GnssConfiguration_V1_0::setGlonassPositioningProtocol(jint gnssPosProtocol) {
+ auto result = mIGnssConfiguration_V1_0->setGlonassPositioningProtocol(gnssPosProtocol);
+ return checkHidlReturn(result, "IGnssConfiguration setGlonassPositioningProtocol() failed.");
+}
+
+jboolean GnssConfiguration_V1_0::setEsExtensionSec(jint emergencyExtensionSeconds) {
+ ALOGI("Config parameter ES_EXTENSION_SEC is not supported in IGnssConfiguration.hal"
+ " versions earlier than 2.0.");
+ return JNI_FALSE;
+}
+
+jboolean GnssConfiguration_V1_0::setBlocklist(JNIEnv* env, jintArray& constellations,
+ jintArray& sv_ids) {
+ ALOGI("IGnssConfiguration interface does not support satellite blocklist.");
+ return JNI_FALSE;
+}
+
+// Implementation of GnssConfiguration_V1_1
+
+GnssConfiguration_V1_1::GnssConfiguration_V1_1(
+ const sp<IGnssConfiguration_V1_1>& iGnssConfiguration)
+ : GnssConfiguration_V1_0{iGnssConfiguration}, mIGnssConfiguration_V1_1(iGnssConfiguration) {}
+
+jobject GnssConfiguration_V1_1::getVersion(JNIEnv* env) {
+ return createHalInterfaceVersionJavaObject(env, 1, 1);
+}
+
+jboolean GnssConfiguration_V1_1::setBlocklist(JNIEnv* env, jintArray& constellations,
+ jintArray& sv_ids) {
+ auto sources = getBlocklistedSources<BlocklistedSource_V1_1,
+ GnssConstellationType_V1_0>(env, constellations, sv_ids);
+ auto result = mIGnssConfiguration_V1_1->setBlacklist(sources);
+ return checkHidlReturn(result, "IGnssConfiguration setBlocklist() failed.");
+}
+
+// Implementation of GnssConfiguration_V2_0
+
+GnssConfiguration_V2_0::GnssConfiguration_V2_0(
+ const sp<IGnssConfiguration_V2_0>& iGnssConfiguration)
+ : GnssConfiguration_V1_1{iGnssConfiguration}, mIGnssConfiguration_V2_0(iGnssConfiguration) {}
+
+jobject GnssConfiguration_V2_0::getVersion(JNIEnv* env) {
+ return createHalInterfaceVersionJavaObject(env, 2, 0);
+}
+
+jboolean GnssConfiguration_V2_0::setSuplEs(jint enable) {
+ ALOGI("Config parameter SUPL_ES is deprecated in IGnssConfiguration.hal version 2.0 and "
+ "higher.");
+ return JNI_FALSE;
+}
+
+jboolean GnssConfiguration_V2_0::setGpsLock(jint enable) {
+ ALOGI("Config parameter GPS_LOCK is deprecated in IGnssConfiguration.hal version 2.0 and "
+ "higher.");
+ return JNI_FALSE;
+}
+
+jboolean GnssConfiguration_V2_0::setEsExtensionSec(jint emergencyExtensionSeconds) {
+ auto result = mIGnssConfiguration_V2_0->setEsExtensionSec(emergencyExtensionSeconds);
+ return checkHidlReturn(result, "IGnssConfiguration setEsExtensionSec() failed.");
+}
+
+// Implementation of GnssConfiguration_V2_1
+
+GnssConfiguration_V2_1::GnssConfiguration_V2_1(
+ const sp<IGnssConfiguration_V2_1>& iGnssConfiguration)
+ : GnssConfiguration_V2_0{iGnssConfiguration}, mIGnssConfiguration_V2_1(iGnssConfiguration) {}
+
+jobject GnssConfiguration_V2_1::getVersion(JNIEnv* env) {
+ return createHalInterfaceVersionJavaObject(env, 2, 1);
+}
+
+jboolean GnssConfiguration_V2_1::setBlocklist(JNIEnv* env, jintArray& constellations,
+ jintArray& sv_ids) {
+ auto sources = getBlocklistedSources<BlocklistedSource_V2_1,
+ GnssConstellationType_V2_0>(env, constellations, sv_ids);
+ auto result = mIGnssConfiguration_V2_1->setBlacklist_2_1(sources);
+ return checkHidlReturn(result, "IGnssConfiguration setBlocklist() failed.");
+}
+
+} // namespace android::gnss
diff --git a/services/core/jni/gnss/GnssConfiguration.h b/services/core/jni/gnss/GnssConfiguration.h
new file mode 100644
index 000000000000..ea0f178b7132
--- /dev/null
+++ b/services/core/jni/gnss/GnssConfiguration.h
@@ -0,0 +1,168 @@
+/*
+ * 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.
+ */
+
+#ifndef _ANDROID_SERVER_GNSS_GNSSCONFIGURATION_H
+#define _ANDROID_SERVER_GNSS_GNSSCONFIGURATION_H
+
+#pragma once
+
+#ifndef LOG_TAG
+#error LOG_TAG must be defined before including this file.
+#endif
+
+#include <android/hardware/gnss/1.0/IGnssConfiguration.h>
+#include <android/hardware/gnss/1.1/IGnssConfiguration.h>
+#include <android/hardware/gnss/2.0/IGnssConfiguration.h>
+#include <android/hardware/gnss/2.1/IGnssConfiguration.h>
+#include <android/hardware/gnss/BnGnssConfiguration.h>
+#include <log/log.h>
+
+#include "jni.h"
+
+namespace android::gnss {
+
+void GnssConfiguration_class_init_once(JNIEnv* env);
+
+class GnssConfigurationInterface {
+public:
+ virtual ~GnssConfigurationInterface() {}
+ virtual jobject getVersion(JNIEnv* env) = 0;
+ virtual jboolean setEmergencySuplPdn(jint enable) = 0;
+ virtual jboolean setSuplVersion(jint version) = 0;
+ virtual jboolean setSuplEs(jint enable) = 0;
+ virtual jboolean setSuplMode(jint mode) = 0;
+ virtual jboolean setGpsLock(jint gpsLock) = 0;
+ virtual jboolean setLppProfile(jint lppProfile) = 0;
+ virtual jboolean setGlonassPositioningProtocol(jint gnssPosProtocol) = 0;
+ virtual jboolean setEsExtensionSec(jint emergencyExtensionSeconds) = 0;
+ virtual jboolean setBlocklist(JNIEnv* env, jintArray& constellations, jintArray& sv_ids) = 0;
+
+protected:
+ template <class T_BlocklistSource, class T_ConstellationType>
+ hardware::hidl_vec<T_BlocklistSource> getBlocklistedSources(JNIEnv* env,
+ jintArray& constellations,
+ jintArray& sv_ids) {
+ jint* constellation_array = env->GetIntArrayElements(constellations, 0);
+ if (nullptr == constellation_array) {
+ ALOGI("GetIntArrayElements returns nullptr.");
+ return JNI_FALSE;
+ }
+
+ jsize length = env->GetArrayLength(constellations);
+
+ jint* sv_id_array = env->GetIntArrayElements(sv_ids, 0);
+ if (nullptr == sv_id_array) {
+ ALOGI("GetIntArrayElements returns nullptr.");
+ return JNI_FALSE;
+ }
+
+ if (length != env->GetArrayLength(sv_ids)) {
+ ALOGI("Lengths of constellations and sv_ids are inconsistent.");
+ return JNI_FALSE;
+ }
+
+ hardware::hidl_vec<T_BlocklistSource> sources;
+ sources.resize(length);
+
+ for (int i = 0; i < length; i++) {
+ sources[i].constellation = static_cast<T_ConstellationType>(constellation_array[i]);
+ sources[i].svid = sv_id_array[i];
+ }
+
+ env->ReleaseIntArrayElements(constellations, constellation_array, 0);
+ env->ReleaseIntArrayElements(sv_ids, sv_id_array, 0);
+
+ return sources;
+ }
+};
+
+class GnssConfiguration : public GnssConfigurationInterface {
+public:
+ GnssConfiguration(const sp<android::hardware::gnss::IGnssConfiguration>& iGnssConfiguration);
+ jobject getVersion(JNIEnv* env) override;
+ jboolean setEmergencySuplPdn(jint enable) override;
+ jboolean setSuplVersion(jint version) override;
+ jboolean setSuplEs(jint enable) override;
+ jboolean setSuplMode(jint mode) override;
+ jboolean setGpsLock(jint gpsLock) override;
+ jboolean setLppProfile(jint lppProfile) override;
+ jboolean setGlonassPositioningProtocol(jint gnssPosProtocol) override;
+ jboolean setEsExtensionSec(jint emergencyExtensionSeconds) override;
+ jboolean setBlocklist(JNIEnv* env, jintArray& constellations, jintArray& sv_ids) override;
+
+private:
+ const sp<android::hardware::gnss::IGnssConfiguration> mIGnssConfiguration;
+};
+
+class GnssConfiguration_V1_0 : public GnssConfigurationInterface {
+public:
+ GnssConfiguration_V1_0(
+ const sp<android::hardware::gnss::V1_0::IGnssConfiguration>& iGnssConfiguration);
+ jobject getVersion(JNIEnv* env) override;
+ jboolean setEmergencySuplPdn(jint enable);
+ jboolean setSuplVersion(jint version) override;
+ jboolean setSuplEs(jint enable) override;
+ jboolean setSuplMode(jint mode) override;
+ jboolean setGpsLock(jint gpsLock) override;
+ jboolean setLppProfile(jint lppProfile);
+ jboolean setGlonassPositioningProtocol(jint gnssPosProtocol) override;
+ jboolean setEsExtensionSec(jint emergencyExtensionSeconds) override;
+ jboolean setBlocklist(JNIEnv* env, jintArray& constellations, jintArray& sv_ids) override;
+
+private:
+ const sp<android::hardware::gnss::V1_0::IGnssConfiguration> mIGnssConfiguration_V1_0;
+};
+
+class GnssConfiguration_V1_1 : public GnssConfiguration_V1_0 {
+public:
+ GnssConfiguration_V1_1(
+ const sp<android::hardware::gnss::V1_1::IGnssConfiguration>& iGnssConfiguration);
+
+ jobject getVersion(JNIEnv* env) override;
+
+ jboolean setBlocklist(JNIEnv* env, jintArray& constellations, jintArray& sv_ids) override;
+
+private:
+ const sp<android::hardware::gnss::V1_1::IGnssConfiguration> mIGnssConfiguration_V1_1;
+};
+
+class GnssConfiguration_V2_0 : public GnssConfiguration_V1_1 {
+public:
+ GnssConfiguration_V2_0(
+ const sp<android::hardware::gnss::V2_0::IGnssConfiguration>& iGnssConfiguration);
+ jobject getVersion(JNIEnv* env) override;
+ jboolean setSuplEs(jint enable) override;
+ jboolean setGpsLock(jint enable) override;
+ jboolean setEsExtensionSec(jint emergencyExtensionSeconds) override;
+
+private:
+ const sp<android::hardware::gnss::V2_0::IGnssConfiguration> mIGnssConfiguration_V2_0;
+};
+
+class GnssConfiguration_V2_1 : public GnssConfiguration_V2_0 {
+public:
+ GnssConfiguration_V2_1(
+ const sp<android::hardware::gnss::V2_1::IGnssConfiguration>& iGnssConfiguration);
+ jobject getVersion(JNIEnv* env) override;
+ jboolean setBlocklist(JNIEnv* env, jintArray& constellations, jintArray& sv_ids) override;
+
+private:
+ const sp<android::hardware::gnss::V2_1::IGnssConfiguration> mIGnssConfiguration_V2_1;
+};
+
+} // namespace android::gnss
+
+#endif // _ANDROID_SERVER_GNSS_GNSSCONFIGURATION_H
diff --git a/services/core/xsd/platform-compat-config.xsd b/services/core/xsd/platform-compat-config.xsd
index 5a4c682f52eb..992470816068 100644
--- a/services/core/xsd/platform-compat-config.xsd
+++ b/services/core/xsd/platform-compat-config.xsd
@@ -29,6 +29,7 @@
<xs:attribute type="xs:boolean" name="disabled"/>
<xs:attribute type="xs:boolean" name="loggingOnly"/>
<xs:attribute type="xs:int" name="enableAfterTargetSdk"/>
+ <xs:attribute type="xs:int" name="enableSinceTargetSdk"/>
<xs:attribute type="xs:string" name="description"/>
</xs:extension>
</xs:simpleContent>
diff --git a/services/core/xsd/platform-compat-schema/current.txt b/services/core/xsd/platform-compat-schema/current.txt
index 7def58d56a26..e3640edd0201 100644
--- a/services/core/xsd/platform-compat-schema/current.txt
+++ b/services/core/xsd/platform-compat-schema/current.txt
@@ -6,6 +6,7 @@ package com.android.server.compat.config {
method public String getDescription();
method public boolean getDisabled();
method public int getEnableAfterTargetSdk();
+ method public int getEnableSinceTargetSdk();
method public long getId();
method public boolean getLoggingOnly();
method public String getName();
@@ -13,6 +14,7 @@ package com.android.server.compat.config {
method public void setDescription(String);
method public void setDisabled(boolean);
method public void setEnableAfterTargetSdk(int);
+ method public void setEnableSinceTargetSdk(int);
method public void setId(long);
method public void setLoggingOnly(boolean);
method public void setName(String);
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/CertificateMonitor.java b/services/devicepolicy/java/com/android/server/devicepolicy/CertificateMonitor.java
index aa38880d6d7d..fdde4ea36583 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/CertificateMonitor.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/CertificateMonitor.java
@@ -205,9 +205,10 @@ public class CertificateMonitor {
dialogIntent.setComponent(targetInfo.getComponentName());
}
+ // Simple notification clicks are immutable
PendingIntent notifyIntent = mInjector.pendingIntentGetActivityAsUser(userContext, 0,
- dialogIntent, PendingIntent.FLAG_UPDATE_CURRENT, null,
- UserHandle.of(parentUserId));
+ dialogIntent, PendingIntent.FLAG_UPDATE_CURRENT | PendingIntent.FLAG_IMMUTABLE,
+ null, UserHandle.of(parentUserId));
return new Notification.Builder(userContext, SystemNotificationChannels.SECURITY)
.setSmallIcon(smallIconId)
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
index 177b7b46bb24..745d6452cdac 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
@@ -2153,9 +2153,11 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
mInjector.binderWithCleanCallingIdentity(() -> {
int affectedUserHandle = parent ? getProfileParentId(userHandle) : userHandle;
AlarmManager am = mInjector.getAlarmManager();
+ // Broadcast alarms sent by system are immutable
PendingIntent pi = PendingIntent.getBroadcastAsUser(context, REQUEST_EXPIRE_PASSWORD,
new Intent(ACTION_EXPIRED_PASSWORD_NOTIFICATION),
- PendingIntent.FLAG_ONE_SHOT | PendingIntent.FLAG_UPDATE_CURRENT,
+ PendingIntent.FLAG_ONE_SHOT | PendingIntent.FLAG_UPDATE_CURRENT
+ | PendingIntent.FLAG_IMMUTABLE,
UserHandle.of(affectedUserHandle));
am.cancel(pi);
if (alarmTime != 0) {
@@ -2178,9 +2180,9 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
ActiveAdmin getActiveAdminUncheckedLocked(ComponentName who, int userHandle, boolean parent) {
ensureLocked();
if (parent) {
- Preconditions.checkCallAuthorization(isManagedProfile(userHandle), String.format(
+ Preconditions.checkCallAuthorization(isManagedProfile(userHandle),
"You can not call APIs on the parent profile outside a managed profile, "
- + "userId = %d", userHandle));
+ + "userId = %d", userHandle);
}
ActiveAdmin admin = getActiveAdminUncheckedLocked(who, userHandle);
if (admin != null && parent) {
@@ -2195,61 +2197,61 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
reqPolicy, /* permission= */ null);
}
- @NonNull ActiveAdmin getDeviceOwnerOfCallerLocked(final CallerIdentity caller) {
+ @NonNull ActiveAdmin getDeviceOwnerLocked(final CallerIdentity caller) {
ensureLocked();
ComponentName doComponent = mOwners.getDeviceOwnerComponent();
Preconditions.checkState(doComponent != null,
- String.format("No device owner for user %d", caller.getUid()));
+ "No device owner for user %d", caller.getUid());
// Use the user ID of the caller instead of mOwners.getDeviceOwnerUserId() because
// secondary, affiliated users will have their own admin.
ActiveAdmin doAdmin = getUserData(caller.getUserId()).mAdminMap.get(doComponent);
Preconditions.checkState(doAdmin != null,
- String.format("Device owner %s for user %d not found", doComponent,
- caller.getUid()));
+ "Device owner %s for user %d not found", doComponent,
+ caller.getUid());
Preconditions.checkCallAuthorization(doAdmin.getUid() == caller.getUid(),
- String.format("Admin %s is not owned by uid %d, but uid %d", doComponent,
- caller.getUid(), doAdmin.getUid()));
+ "Admin %s is not owned by uid %d, but uid %d", doComponent,
+ caller.getUid(), doAdmin.getUid());
Preconditions.checkCallAuthorization(
doAdmin.info.getComponent().equals(caller.getComponentName()),
- String.format("Caller component %s is not device owner",
- caller.getComponentName()));
+ "Caller component %s is not device owner",
+ caller.getComponentName());
return doAdmin;
}
- @NonNull ActiveAdmin getProfileOwnerOfCallerLocked(final CallerIdentity caller) {
+ @NonNull ActiveAdmin getProfileOwnerLocked(final CallerIdentity caller) {
ensureLocked();
final ComponentName poAdminComponent = mOwners.getProfileOwnerComponent(caller.getUserId());
Preconditions.checkState(poAdminComponent != null,
- String.format("No profile owner for user %d", caller.getUid()));
+ "No profile owner for user %d", caller.getUid());
ActiveAdmin poAdmin = getUserData(caller.getUserId()).mAdminMap.get(poAdminComponent);
Preconditions.checkState(poAdmin != null,
- String.format("No device profile owner for caller %d", caller.getUid()));
+ "No device profile owner for caller %d", caller.getUid());
Preconditions.checkCallAuthorization(poAdmin.getUid() == caller.getUid(),
- String.format("Admin %s is not owned by uid %d", poAdminComponent,
- caller.getUid()));
+ "Admin %s is not owned by uid %d", poAdminComponent,
+ caller.getUid());
Preconditions.checkCallAuthorization(
poAdmin.info.getComponent().equals(caller.getComponentName()),
- String.format("Caller component %s is not profile owner",
- caller.getComponentName()));
+ "Caller component %s is not profile owner",
+ caller.getComponentName());
return poAdmin;
}
@NonNull ActiveAdmin getOrganizationOwnedProfileOwnerLocked(final CallerIdentity caller) {
- final ActiveAdmin profileOwner = getProfileOwnerOfCallerLocked(caller);
+ final ActiveAdmin profileOwner = getProfileOwnerLocked(caller);
Preconditions.checkCallAuthorization(
mOwners.isProfileOwnerOfOrganizationOwnedDevice(caller.getUserId()),
- String.format("Admin %s is not of an org-owned device",
- profileOwner.info.getComponent()));
+ "Admin %s is not of an org-owned device",
+ profileOwner.info.getComponent());
return profileOwner;
}
@@ -2266,10 +2268,10 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
}
if (poAdminComponent != null) {
- return getProfileOwnerOfCallerLocked(caller);
+ return getProfileOwnerLocked(caller);
}
- return getDeviceOwnerOfCallerLocked(caller);
+ return getDeviceOwnerLocked(caller);
}
@NonNull ActiveAdmin getParentOfAdminIfRequired(ActiveAdmin admin, boolean parent) {
@@ -3377,7 +3379,7 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
updatePasswordQualityCacheForUserGroup(userId);
saveSettingsLocked(userId);
}
- maybeLogPasswordComplexitySet(who, userId, parent, passwordPolicy);
+ logPasswordQualitySetIfSecurityLogEnabled(who, userId, parent, passwordPolicy);
});
}
DevicePolicyEventLogger
@@ -3591,7 +3593,7 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
updatePasswordValidityCheckpointLocked(userId, parent);
saveSettingsLocked(userId);
}
- maybeLogPasswordComplexitySet(who, userId, parent, passwordPolicy);
+ logPasswordQualitySetIfSecurityLogEnabled(who, userId, parent, passwordPolicy);
}
DevicePolicyEventLogger
.createEvent(DevicePolicyEnums.SET_PASSWORD_MINIMUM_LENGTH)
@@ -3869,7 +3871,7 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
updatePasswordValidityCheckpointLocked(userId, parent);
saveSettingsLocked(userId);
}
- maybeLogPasswordComplexitySet(who, userId, parent, passwordPolicy);
+ logPasswordQualitySetIfSecurityLogEnabled(who, userId, parent, passwordPolicy);
}
DevicePolicyEventLogger
.createEvent(DevicePolicyEnums.SET_PASSWORD_MINIMUM_UPPER_CASE)
@@ -3899,7 +3901,7 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
updatePasswordValidityCheckpointLocked(userId, parent);
saveSettingsLocked(userId);
}
- maybeLogPasswordComplexitySet(who, userId, parent, passwordPolicy);
+ logPasswordQualitySetIfSecurityLogEnabled(who, userId, parent, passwordPolicy);
}
DevicePolicyEventLogger
.createEvent(DevicePolicyEnums.SET_PASSWORD_MINIMUM_LOWER_CASE)
@@ -3931,7 +3933,7 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
updatePasswordValidityCheckpointLocked(userId, parent);
saveSettingsLocked(userId);
}
- maybeLogPasswordComplexitySet(who, userId, parent, passwordPolicy);
+ logPasswordQualitySetIfSecurityLogEnabled(who, userId, parent, passwordPolicy);
}
DevicePolicyEventLogger
.createEvent(DevicePolicyEnums.SET_PASSWORD_MINIMUM_LETTERS)
@@ -3963,7 +3965,7 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
updatePasswordValidityCheckpointLocked(userId, parent);
saveSettingsLocked(userId);
}
- maybeLogPasswordComplexitySet(who, userId, parent, passwordPolicy);
+ logPasswordQualitySetIfSecurityLogEnabled(who, userId, parent, passwordPolicy);
}
DevicePolicyEventLogger
.createEvent(DevicePolicyEnums.SET_PASSWORD_MINIMUM_NUMERIC)
@@ -3995,7 +3997,7 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
updatePasswordValidityCheckpointLocked(userId, parent);
saveSettingsLocked(userId);
}
- maybeLogPasswordComplexitySet(who, userId, parent, passwordPolicy);
+ logPasswordQualitySetIfSecurityLogEnabled(who, userId, parent, passwordPolicy);
}
DevicePolicyEventLogger
.createEvent(DevicePolicyEnums.SET_PASSWORD_MINIMUM_SYMBOLS)
@@ -4028,7 +4030,7 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
updatePasswordValidityCheckpointLocked(userId, parent);
saveSettingsLocked(userId);
}
- maybeLogPasswordComplexitySet(who, userId, parent, passwordPolicy);
+ logPasswordQualitySetIfSecurityLogEnabled(who, userId, parent, passwordPolicy);
}
DevicePolicyEventLogger
.createEvent(DevicePolicyEnums.SET_PASSWORD_MINIMUM_NON_LETTER)
@@ -4158,9 +4160,9 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
final CallerIdentity caller = getCallerIdentity();
Preconditions.checkCallAuthorization(hasFullCrossUsersPermission(caller, userHandle));
- Preconditions.checkCallAuthorization(isManagedProfile(userHandle), String.format(
+ Preconditions.checkCallAuthorization(isManagedProfile(userHandle),
"can not call APIs refering to the parent profile outside a managed profile, "
- + "userId = %d", userHandle));
+ + "userId = %d", userHandle);
synchronized (getLockObject()) {
final int targetUser = getProfileParentId(userHandle);
@@ -4182,9 +4184,9 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
final CallerIdentity caller = getCallerIdentity();
Preconditions.checkCallAuthorization(hasFullCrossUsersPermission(caller, userHandle));
- Preconditions.checkCallAuthorization(!isManagedProfile(userHandle), String.format(
+ Preconditions.checkCallAuthorization(!isManagedProfile(userHandle),
"You can not check password sufficiency for a managed profile, userId = %d",
- userHandle));
+ userHandle);
enforceUserUnlocked(userHandle);
synchronized (getLockObject()) {
@@ -4395,12 +4397,13 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
return mInjector.binderWithCleanCallingIdentity(() -> mUserManager.getUserInfo(userId));
}
- private boolean setPasswordPrivileged(@NonNull String password, int flags, int callingUid) {
+ private boolean setPasswordPrivileged(@NonNull String password, int flags,
+ CallerIdentity caller) {
// Only allow setting password on an unsecured user
- if (isLockScreenSecureUnchecked(UserHandle.getUserId(callingUid))) {
+ if (isLockScreenSecureUnchecked(caller.getUserId())) {
throw new SecurityException("Cannot change current password");
}
- return resetPasswordInternal(password, 0, null, flags, callingUid);
+ return resetPasswordInternal(password, 0, null, flags, caller);
}
@Override
@@ -4410,19 +4413,22 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
return false;
}
if (password == null) password = "";
- final int callingUid = mInjector.binderGetCallingUid();
- final int userHandle = mInjector.userHandleGetCallingUserId();
+ final CallerIdentity caller = getCallerIdentity();
+ final int userHandle = caller.getUserId();
// As of R, only privlleged caller holding RESET_PASSWORD can call resetPassword() to
// set password to an unsecured user.
if (hasCallingPermission(permission.RESET_PASSWORD)) {
- return setPasswordPrivileged(password, flags, callingUid);
+ return setPasswordPrivileged(password, flags, caller);
}
+ // If caller has PO (or DO) throw or fail silently depending on its target SDK level.
+ Preconditions.checkCallAuthorization(
+ isDeviceOwner(caller) || isProfileOwner(caller),
+ String.format("UID %d is not a device or profile owner", caller.getUid()));
+
synchronized (getLockObject()) {
- // If caller has PO (or DO) throw or fail silently depending on its target SDK level.
- ActiveAdmin admin = getActiveAdminWithPolicyForUidLocked(
- null, DeviceAdminInfo.USES_POLICY_PROFILE_OWNER, callingUid);
+ ActiveAdmin admin = getDeviceOrProfileOwnerAdminLocked(userHandle);
if (admin != null) {
if (getTargetSdk(admin.info.getPackageName(), userHandle) < Build.VERSION_CODES.O) {
Slog.e(LOG_TAG, "DPC can no longer call resetPassword()");
@@ -4444,7 +4450,8 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
}
private boolean resetPasswordInternal(String password, long tokenHandle, byte[] token,
- int flags, int callingUid) {
+ int flags, CallerIdentity caller) {
+ final int callingUid = caller.getUid();
final int userHandle = UserHandle.getUserId(callingUid);
synchronized (getLockObject()) {
final PasswordMetrics minMetrics = getPasswordMinimumMetrics(userHandle);
@@ -4473,7 +4480,7 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
return false;
}
- boolean callerIsDeviceOwnerAdmin = isCallerDeviceOwner(callingUid);
+ boolean callerIsDeviceOwnerAdmin = isDeviceOwner(caller);
boolean doNotAskCredentialsOnBoot =
(flags & DevicePolicyManager.RESET_PASSWORD_DO_NOT_ASK_CREDENTIALS_ON_BOOT) != 0;
if (callerIsDeviceOwnerAdmin && doNotAskCredentialsOnBoot) {
@@ -5010,7 +5017,7 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
ApplicationInfo ai = mInjector.getIPackageManager().getApplicationInfo(
packageName, 0, caller.getUserId());
Preconditions.checkArgument(ai != null,
- String.format("Provided package %s is not installed", packageName));
+ "Provided package %s is not installed", packageName);
granteeUid = ai.uid;
} catch (RemoteException e) {
throw new IllegalStateException("Failure getting grantee uid", e);
@@ -5388,14 +5395,14 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
// Retrieve the user ID of the calling process.
final int userId = caller.getUserId();
final boolean hasDoDelegation = !Collections.disjoint(scopes, DEVICE_OWNER_DELEGATIONS);
+ // Ensure calling process is device/profile owner.
+ if (hasDoDelegation) {
+ Preconditions.checkCallAuthorization(isDeviceOwner(caller));
+ } else {
+ Preconditions.checkCallAuthorization(isDeviceOwner(caller) || isProfileOwner(caller));
+ }
+
synchronized (getLockObject()) {
- // Ensure calling process is device/profile owner.
- if (hasDoDelegation) {
- Preconditions.checkCallAuthorization(isDeviceOwner(caller));
- } else {
- // TODO move whole condition out of synchronized block
- getActiveAdminForCallerLocked(who, DeviceAdminInfo.USES_POLICY_PROFILE_OWNER);
- }
// Ensure the delegate is installed (skip this for DELEGATION_CERT_INSTALL in pre-N).
if (shouldCheckIfDelegatePackageIsInstalled(delegatePackage,
getTargetSdk(who.getPackageName(), userId), scopes)) {
@@ -5516,11 +5523,10 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
}
// Retrieve the user ID of the calling process.
- final int userId = mInjector.userHandleGetCallingUserId();
+ final CallerIdentity caller = getCallerIdentity(who);
+ Preconditions.checkCallAuthorization(isDeviceOwner(caller) || isProfileOwner(caller));
synchronized (getLockObject()) {
- // Ensure calling process is device/profile owner.
- getActiveAdminForCallerLocked(who, DeviceAdminInfo.USES_POLICY_PROFILE_OWNER);
- return getDelegatePackagesInternalLocked(scope, userId);
+ return getDelegatePackagesInternalLocked(scope, caller.getUserId());
}
}
@@ -5629,7 +5635,7 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
private boolean isCallerDelegate(CallerIdentity caller, String scope) {
Objects.requireNonNull(caller.getPackageName(), "callerPackage is null");
Preconditions.checkArgument(Arrays.asList(DELEGATIONS).contains(scope),
- String.format("Unexpected delegation scope: %s", scope));
+ "Unexpected delegation scope: %s", scope);
synchronized (getLockObject()) {
// Retrieve user policy data.
@@ -5649,11 +5655,12 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
String delegatePackage, String scope) {
Objects.requireNonNull(who, "ComponentName is null");
- final int userId = mInjector.userHandleGetCallingUserId();
+ final CallerIdentity caller = getCallerIdentity(who);
+ // Ensure calling process is device/profile owner.
+ Preconditions.checkCallAuthorization(isProfileOwner(caller) || isDeviceOwner(caller));
+
synchronized (getLockObject()) {
- // Ensure calling process is device/profile owner.
- getActiveAdminForCallerLocked(who, DeviceAdminInfo.USES_POLICY_PROFILE_OWNER);
- final DevicePolicyData policy = getUserData(userId);
+ final DevicePolicyData policy = getUserData(caller.getUserId());
if (delegatePackage != null) {
// Set package as a delegate for scope if it is not already one.
@@ -5866,7 +5873,7 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
+ "organization-owned device.");
}
if ((flags & WIPE_RESET_PROTECTION_DATA) != 0) {
- Preconditions.checkCallAuthorization(isCallerDeviceOwner(caller.getUid())
+ Preconditions.checkCallAuthorization(isDeviceOwner(caller)
|| calledByProfileOwnerOnOrgOwnedDevice,
"Only device owners or profile owners of organization-owned device can set "
+ "WIPE_RESET_PROTECTION_DATA");
@@ -5877,7 +5884,7 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
admin = getActiveAdminForCallerLocked(null, DeviceAdminInfo.USES_POLICY_WIPE_DATA);
}
Preconditions.checkCallAuthorization(admin != null,
- String.format("No active admin for user %d", caller.getUserId()));
+ "No active admin for user %d", caller.getUserId());
if (TextUtils.isEmpty(wipeReasonForUser)) {
if (calledByProfileOwnerOnOrgOwnedDevice && !calledOnParentInstance) {
@@ -6103,8 +6110,8 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
Preconditions.checkCallAuthorization(isSystemUid(caller));
// Managed Profile password can only be changed when it has a separate challenge.
if (!isSeparateProfileChallengeEnabled(userId)) {
- Preconditions.checkCallAuthorization(!isManagedProfile(userId), String.format("You can "
- + "not set the active password for a managed profile, userId = %d", userId));
+ Preconditions.checkCallAuthorization(!isManagedProfile(userId), "You can "
+ + "not set the active password for a managed profile, userId = %d", userId);
}
DevicePolicyData policy = getUserData(userId);
@@ -6157,9 +6164,9 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
Preconditions.checkCallAuthorization(hasFullCrossUsersPermission(caller, userHandle));
Preconditions.checkCallAuthorization(hasCallingOrSelfPermission(BIND_DEVICE_ADMIN));
if (!isSeparateProfileChallengeEnabled(userHandle)) {
- Preconditions.checkCallAuthorization(!isManagedProfile(userHandle), String.format(
+ Preconditions.checkCallAuthorization(!isManagedProfile(userHandle),
"You can not report failed password attempt if separate profile challenge is "
- + "not in place for a managed profile, userId = %d", userHandle));
+ + "not in place for a managed profile, userId = %d", userHandle);
}
boolean wipeData = false;
@@ -6625,8 +6632,8 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
}
synchronized (getLockObject()) {
- ActiveAdmin ap = getActiveAdminForCallerLocked(who,
- DeviceAdminInfo.USES_POLICY_PROFILE_OWNER, parent);
+ ActiveAdmin ap = getParentOfAdminIfRequired(getProfileOwnerOrDeviceOwnerLocked(caller),
+ parent);
if (ap.disableScreenCapture != disabled) {
ap.disableScreenCapture = disabled;
saveSettingsLocked(caller.getUserId());
@@ -7309,9 +7316,15 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
private boolean isDeviceOwner(CallerIdentity caller) {
synchronized (getLockObject()) {
- return mOwners.hasDeviceOwner()
- && mOwners.getDeviceOwnerUserId() == caller.getUserId()
- && mOwners.getDeviceOwnerComponent().equals(caller.getComponentName());
+ if (!mOwners.hasDeviceOwner() || mOwners.getDeviceOwnerUserId() != caller.getUserId()) {
+ return false;
+ }
+
+ if (caller.hasAdminComponent()) {
+ return mOwners.getDeviceOwnerComponent().equals(caller.getComponentName());
+ } else {
+ return isUidDeviceOwnerLocked(caller.getUid());
+ }
}
}
@@ -7341,8 +7354,43 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
* @return true if {@code identity} is a profile owner, false otherwise.
*/
public boolean isProfileOwner(CallerIdentity caller) {
- final ComponentName profileOwner = getProfileOwner(caller.getUserId());
- return profileOwner != null && profileOwner.equals(caller.getComponentName());
+ synchronized (getLockObject()) {
+ final ComponentName profileOwner = getProfileOwner(caller.getUserId());
+ // No profile owner.
+ if (profileOwner == null) {
+ return false;
+ }
+ // The admin ComponentName was specified, check it directly.
+ if (caller.hasAdminComponent()) {
+ return profileOwner.equals(caller.getComponentName());
+ } else {
+ return isUidProfileOwnerLocked(caller.getUid());
+ }
+ }
+ }
+
+ /**
+ * Checks if the app uid provided is the profile owner. This method should only be called
+ * if no componentName is available.
+ *
+ * @param appUid UID of the caller.
+ * @return true if the caller is the profile owner
+ */
+ private boolean isUidProfileOwnerLocked(int appUid) {
+ ensureLocked();
+
+ final int userId = UserHandle.getUserId(appUid);
+ final ComponentName profileOwnerComponent = mOwners.getProfileOwnerComponent(userId);
+ if (profileOwnerComponent == null) {
+ return false;
+ }
+ for (ActiveAdmin admin : getUserData(userId).mAdminList) {
+ final ComponentName currentAdminComponent = admin.info.getComponent();
+ if (admin.getUid() == appUid && profileOwnerComponent.equals(currentAdminComponent)) {
+ return true;
+ }
+ }
+ return false;
}
private boolean hasProfileOwner(int userId) {
@@ -7652,8 +7700,7 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
enforceUserUnlocked(userId);
synchronized (getLockObject()) {
// Check if this is the profile owner who is calling
- final ActiveAdmin admin =
- getActiveAdminForCallerLocked(who, DeviceAdminInfo.USES_POLICY_PROFILE_OWNER);
+ final ActiveAdmin admin = getProfileOwnerOrDeviceOwnerLocked(caller);
mInjector.binderWithCleanCallingIdentity(() -> {
clearProfileOwnerLocked(admin, userId);
@@ -7840,7 +7887,7 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
// Current user has a managed-profile, but current user is not managed, so
// rather than moving to finalized state, go back to unmanaged once
// profile provisioning is complete.
- if (newState == DevicePolicyManager.STATE_USER_UNMANAGED) {
+ if (newState == DevicePolicyManager.STATE_USER_PROFILE_FINALIZED) {
return;
}
break;
@@ -8368,8 +8415,10 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
}
private void enforceCanCallLockTaskLocked(ComponentName who) {
- getActiveAdminForCallerLocked(who, DeviceAdminInfo.USES_POLICY_PROFILE_OWNER);
- final int userId = mInjector.userHandleGetCallingUserId();
+ final CallerIdentity caller = getAdminCallerIdentity(who);
+ Preconditions.checkCallAuthorization(isProfileOwner(caller) || isDeviceOwner(caller));
+
+ final int userId = caller.getUserId();
if (!canUserUseLockTaskLocked(userId)) {
throw new SecurityException("User " + userId + " is not allowed to use lock task");
}
@@ -8533,10 +8582,11 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
public void addPersistentPreferredActivity(ComponentName who, IntentFilter filter,
ComponentName activity) {
Objects.requireNonNull(who, "ComponentName is null");
- final int userHandle = UserHandle.getCallingUserId();
- synchronized (getLockObject()) {
- getActiveAdminForCallerLocked(who, DeviceAdminInfo.USES_POLICY_PROFILE_OWNER);
+ final CallerIdentity caller = getCallerIdentity(who);
+ Preconditions.checkCallAuthorization(isProfileOwner(caller) || isDeviceOwner(caller));
+ final int userHandle = caller.getUserId();
+ synchronized (getLockObject()) {
long id = mInjector.binderClearCallingIdentity();
try {
mIPackageManager.addPersistentPreferredActivity(filter, activity, userHandle);
@@ -8559,10 +8609,11 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
@Override
public void clearPackagePersistentPreferredActivities(ComponentName who, String packageName) {
Objects.requireNonNull(who, "ComponentName is null");
- final int userHandle = UserHandle.getCallingUserId();
- synchronized (getLockObject()) {
- getActiveAdminForCallerLocked(who, DeviceAdminInfo.USES_POLICY_PROFILE_OWNER);
+ final CallerIdentity caller = getCallerIdentity(who);
+ Preconditions.checkCallAuthorization(isProfileOwner(caller) || isDeviceOwner(caller));
+ final int userHandle = caller.getUserId();
+ synchronized (getLockObject()) {
long id = mInjector.binderClearCallingIdentity();
try {
mIPackageManager.clearPackagePersistentPreferredActivities(packageName, userHandle);
@@ -8666,7 +8717,7 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
synchronized (getLockObject()) {
final String componentName = agent.flattenToString();
- if (caller.hasAdminComponent()) {
+ if (admin != null) {
final ActiveAdmin ap = getActiveAdminUncheckedLocked(admin, userHandle, parent);
if (ap == null) return null;
TrustAgentInfo trustAgentInfo = ap.trustAgentInfos.get(componentName);
@@ -8714,10 +8765,11 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
@Override
public void setRestrictionsProvider(ComponentName who, ComponentName permissionProvider) {
Objects.requireNonNull(who, "ComponentName is null");
- synchronized (getLockObject()) {
- getActiveAdminForCallerLocked(who, DeviceAdminInfo.USES_POLICY_PROFILE_OWNER);
+ final CallerIdentity caller = getCallerIdentity(who);
+ Preconditions.checkCallAuthorization(isProfileOwner(caller) || isDeviceOwner(caller));
- int userHandle = UserHandle.getCallingUserId();
+ synchronized (getLockObject()) {
+ int userHandle = caller.getUserId();
DevicePolicyData userData = getUserData(userHandle);
userData.mRestrictionsProvider = permissionProvider;
saveSettingsLocked(userHandle);
@@ -8736,10 +8788,10 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
@Override
public void addCrossProfileIntentFilter(ComponentName who, IntentFilter filter, int flags) {
Objects.requireNonNull(who, "ComponentName is null");
- int callingUserId = UserHandle.getCallingUserId();
+ final CallerIdentity caller = getCallerIdentity(who);
+ Preconditions.checkCallAuthorization(isProfileOwner(caller) || isDeviceOwner(caller));
+ int callingUserId = caller.getUserId();
synchronized (getLockObject()) {
- getActiveAdminForCallerLocked(who, DeviceAdminInfo.USES_POLICY_PROFILE_OWNER);
-
long id = mInjector.binderClearCallingIdentity();
try {
UserInfo parent = mUserManager.getProfileParent(callingUserId);
@@ -8785,9 +8837,11 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
@Override
public void clearCrossProfileIntentFilters(ComponentName who) {
Objects.requireNonNull(who, "ComponentName is null");
- int callingUserId = UserHandle.getCallingUserId();
+ final CallerIdentity caller = getCallerIdentity(who);
+ Preconditions.checkCallAuthorization(isProfileOwner(caller) || isDeviceOwner(caller));
+
+ int callingUserId = caller.getUserId();
synchronized (getLockObject()) {
- getActiveAdminForCallerLocked(who, DeviceAdminInfo.USES_POLICY_PROFILE_OWNER);
long id = mInjector.binderClearCallingIdentity();
try {
UserInfo parent = mUserManager.getProfileParent(callingUserId);
@@ -9462,10 +9516,11 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
@Override
public int logoutUser(ComponentName who) {
Objects.requireNonNull(who, "ComponentName is null");
+ final CallerIdentity caller = getCallerIdentity(who);
+ Preconditions.checkCallAuthorization(isProfileOwner(caller) || isDeviceOwner(caller));
- final int callingUserId = mInjector.userHandleGetCallingUserId();
+ final int callingUserId = caller.getUserId();
synchronized (getLockObject()) {
- getActiveAdminForCallerLocked(who, DeviceAdminInfo.USES_POLICY_PROFILE_OWNER);
if (!isUserAffiliatedWithDeviceLocked(callingUserId)) {
throw new SecurityException("Admin " + who +
" is neither the device owner or affiliated user's profile owner.");
@@ -9627,9 +9682,8 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
int userHandle = caller.getUserId();
synchronized (getLockObject()) {
- final ActiveAdmin activeAdmin =
- getActiveAdminForCallerLocked(who,
- DeviceAdminInfo.USES_POLICY_PROFILE_OWNER, parent);
+ final ActiveAdmin activeAdmin = getParentOfAdminIfRequired(
+ getProfileOwnerOrDeviceOwnerLocked(caller), parent);
if (isDeviceOwner(caller)) {
if (!UserRestrictionsUtils.canDeviceOwnerChange(key)) {
@@ -9948,9 +10002,9 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
boolean result;
synchronized (getLockObject()) {
Preconditions.checkCallAuthorization(
- isUserAffiliatedWithDeviceLocked(caller.getUserId()), String.format(
+ isUserAffiliatedWithDeviceLocked(caller.getUserId()),
"Admin %s is neither the device owner or "
- + "affiliated user's profile owner.", who));
+ + "affiliated user's profile owner.", who);
final long id = mInjector.binderClearCallingIdentity();
try {
if (VERBOSE_LOG) {
@@ -10332,12 +10386,12 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
final CallerIdentity caller = getCallerIdentity(who);
Preconditions.checkCallAuthorization(isDeviceOwner(caller) || isProfileOwner(caller));
Preconditions.checkCallAuthorization(!isManagedProfile(caller.getUserId()),
- String.format("User %d is not allowed to call setSecondaryLockscreenEnabled",
- caller.getUserId()));
+ "User %d is not allowed to call setSecondaryLockscreenEnabled",
+ caller.getUserId());
// Allow testOnly admins to bypass supervision config requirement.
Preconditions.checkCallAuthorization(isAdminTestOnlyLocked(who, caller.getUserId())
- || isDefaultSupervisor(caller), String.format("Admin %s is not the "
- + "default supervision component", caller.getComponentName()));
+ || isDefaultSupervisor(caller), "Admin %s is not the "
+ + "default supervision component", caller.getComponentName());
synchronized (getLockObject()) {
DevicePolicyData policy = getUserData(caller.getUserId());
@@ -10546,19 +10600,17 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
public void setSystemSetting(ComponentName who, String setting, String value) {
Objects.requireNonNull(who, "ComponentName is null");
Preconditions.checkStringNotEmpty(setting, "String setting is null or empty");
+ final CallerIdentity caller = getCallerIdentity(who);
+ Preconditions.checkCallAuthorization(isProfileOwner(caller) || isDeviceOwner(caller));
synchronized (getLockObject()) {
- getActiveAdminForCallerLocked(who, DeviceAdminInfo.USES_POLICY_PROFILE_OWNER);
-
if (!SYSTEM_SETTINGS_ALLOWLIST.contains(setting)) {
throw new SecurityException(String.format(
"Permission denial: device owners cannot update %1$s", setting));
}
- final int callingUserId = mInjector.userHandleGetCallingUserId();
-
mInjector.binderWithCleanCallingIdentity(() ->
- mInjector.settingsSystemPutStringForUser(setting, value, callingUserId));
+ mInjector.settingsSystemPutStringForUser(setting, value, caller.getUserId()));
}
}
@@ -10643,8 +10695,10 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
Slog.wtf(LOG_TAG, "Failed to resolve intent for location settings");
}
+ // Simple notification clicks are immutable
PendingIntent locationSettingsIntent = mInjector.pendingIntentGetActivityAsUser(mContext, 0,
- intent, PendingIntent.FLAG_UPDATE_CURRENT, null, user);
+ intent, PendingIntent.FLAG_UPDATE_CURRENT | PendingIntent.FLAG_IMMUTABLE, null,
+ user);
Notification notification = new Notification.Builder(mContext,
SystemNotificationChannels.DEVICE_ADMIN)
.setSmallIcon(R.drawable.ic_info_outline)
@@ -10704,11 +10758,11 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
@Override
public void setSecureSetting(ComponentName who, String setting, String value) {
Objects.requireNonNull(who, "ComponentName is null");
- int callingUserId = mInjector.userHandleGetCallingUserId();
+ final CallerIdentity caller = getCallerIdentity(who);
+ Preconditions.checkCallAuthorization(isProfileOwner(caller) || isDeviceOwner(caller));
+ int callingUserId = caller.getUserId();
synchronized (getLockObject()) {
- getActiveAdminForCallerLocked(who, DeviceAdminInfo.USES_POLICY_PROFILE_OWNER);
-
if (isDeviceOwner(who, callingUserId)) {
if (!SECURE_SETTINGS_DEVICEOWNER_ALLOWLIST.contains(setting)
&& !isCurrentUserDemo()) {
@@ -10800,8 +10854,10 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
@Override
public void setMasterVolumeMuted(ComponentName who, boolean on) {
Objects.requireNonNull(who, "ComponentName is null");
+ final CallerIdentity caller = getCallerIdentity(who);
+ Preconditions.checkCallAuthorization(isProfileOwner(caller) || isDeviceOwner(caller));
+
synchronized (getLockObject()) {
- getActiveAdminForCallerLocked(who, DeviceAdminInfo.USES_POLICY_PROFILE_OWNER);
setUserRestriction(who, UserManager.DISALLOW_UNMUTE_DEVICE, on, /* parent */ false);
DevicePolicyEventLogger
.createEvent(DevicePolicyEnums.SET_MASTER_VOLUME_MUTED)
@@ -10814,9 +10870,10 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
@Override
public boolean isMasterVolumeMuted(ComponentName who) {
Objects.requireNonNull(who, "ComponentName is null");
- synchronized (getLockObject()) {
- getActiveAdminForCallerLocked(who, DeviceAdminInfo.USES_POLICY_PROFILE_OWNER);
+ final CallerIdentity caller = getCallerIdentity(who);
+ Preconditions.checkCallAuthorization(isProfileOwner(caller) || isDeviceOwner(caller));
+ synchronized (getLockObject()) {
AudioManager audioManager =
(AudioManager) mContext.getSystemService(Context.AUDIO_SERVICE);
return audioManager.isMasterMute();
@@ -10825,13 +10882,13 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
@Override
public void setUserIcon(ComponentName who, Bitmap icon) {
- synchronized (getLockObject()) {
- Objects.requireNonNull(who, "ComponentName is null");
- getActiveAdminForCallerLocked(who, DeviceAdminInfo.USES_POLICY_PROFILE_OWNER);
+ Objects.requireNonNull(who, "ComponentName is null");
+ final CallerIdentity caller = getCallerIdentity(who);
+ Preconditions.checkCallAuthorization(isProfileOwner(caller) || isDeviceOwner(caller));
- int userId = UserHandle.getCallingUserId();
+ synchronized (getLockObject()) {
mInjector.binderWithCleanCallingIdentity(
- () -> mUserManagerInternal.setUserIcon(userId, icon));
+ () -> mUserManagerInternal.setUserIcon(caller.getUserId(), icon));
}
DevicePolicyEventLogger
.createEvent(DevicePolicyEnums.SET_USER_ICON)
@@ -10842,13 +10899,15 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
@Override
public boolean setKeyguardDisabled(ComponentName who, boolean disabled) {
Objects.requireNonNull(who, "ComponentName is null");
- final int userId = mInjector.userHandleGetCallingUserId();
+ final CallerIdentity caller = getCallerIdentity(who);
+ Preconditions.checkCallAuthorization(isProfileOwner(caller) || isDeviceOwner(caller));
+
+ final int userId = caller.getUserId();
synchronized (getLockObject()) {
- getActiveAdminForCallerLocked(who, DeviceAdminInfo.USES_POLICY_PROFILE_OWNER);
- if (!isUserAffiliatedWithDeviceLocked(userId)) {
- throw new SecurityException("Admin " + who +
- " is neither the device owner or affiliated user's profile owner.");
- }
+ Preconditions.checkCallAuthorization(isUserAffiliatedWithDeviceLocked(userId),
+ String.format(
+ "Admin %s is neither the device owner or affiliated user's profile "
+ + "owner.", who));
}
if (isManagedProfile(userId)) {
throw new SecurityException("Managed profile cannot disable keyguard");
@@ -10881,13 +10940,14 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
@Override
public boolean setStatusBarDisabled(ComponentName who, boolean disabled) {
- int userId = UserHandle.getCallingUserId();
+ final CallerIdentity caller = getAdminCallerIdentity(who);
+ Preconditions.checkCallAuthorization(isProfileOwner(caller) || isDeviceOwner(caller));
+
+ int userId = caller.getUserId();
synchronized (getLockObject()) {
- getActiveAdminForCallerLocked(who, DeviceAdminInfo.USES_POLICY_PROFILE_OWNER);
- if (!isUserAffiliatedWithDeviceLocked(userId)) {
- throw new SecurityException("Admin " + who +
- " is neither the device owner or affiliated user's profile owner.");
- }
+ Preconditions.checkCallAuthorization(isUserAffiliatedWithDeviceLocked(userId),
+ "Admin " + who
+ + " is neither the device owner or affiliated user's profile owner.");
if (isManagedProfile(userId)) {
throw new SecurityException("Managed profile cannot disable status bar");
}
@@ -11628,32 +11688,24 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
}
/**
- * Checks if the caller of the method is the device owner app.
- *
- * @param callerUid UID of the caller.
- * @return true if the caller is the device owner app
+ * Checks if any of the packages associated with the UID of the app provided is that
+ * of the device owner.
+ * @param appUid UID of the app to check.
+ * @return {@code true} if any of the packages are the device owner, {@code false} otherwise.
*/
- @VisibleForTesting
- boolean isCallerDeviceOwner(int callerUid) {
- synchronized (getLockObject()) {
- if (!mOwners.hasDeviceOwner()) {
- return false;
- }
- if (UserHandle.getUserId(callerUid) != mOwners.getDeviceOwnerUserId()) {
- return false;
- }
- final String deviceOwnerPackageName = mOwners.getDeviceOwnerComponent()
- .getPackageName();
- try {
- String[] pkgs = mInjector.getIPackageManager().getPackagesForUid(callerUid);
- for (String pkg : pkgs) {
- if (deviceOwnerPackageName.equals(pkg)) {
- return true;
- }
- }
- } catch (RemoteException e) {
- return false;
+ private boolean isUidDeviceOwnerLocked(int appUid) {
+ ensureLocked();
+ final String deviceOwnerPackageName = mOwners.getDeviceOwnerComponent()
+ .getPackageName();
+ try {
+ String[] pkgs = mInjector.getIPackageManager().getPackagesForUid(appUid);
+ for (String pkg : pkgs) {
+ if (deviceOwnerPackageName.equals(pkg)) {
+ return true;
}
+ }
+ } catch (RemoteException e) {
+ return false;
}
return false;
}
@@ -12330,8 +12382,8 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
final CallerIdentity caller = getCallerIdentity();
Preconditions.checkCallAuthorization(hasFullCrossUsersPermission(caller, userId));
Preconditions.checkCallAuthorization(canManageUsers(caller));
- Preconditions.checkCallAuthorization(isManagedProfile(userId), String.format("You can not "
- + "set organization color outside a managed profile, userId = %d", userId));
+ Preconditions.checkCallAuthorization(isManagedProfile(userId), "You can not "
+ + "set organization color outside a managed profile, userId = %d", userId);
synchronized (getLockObject()) {
ActiveAdmin admin = getProfileOwnerAdminLocked(userId);
@@ -12365,8 +12417,8 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
final CallerIdentity caller = getCallerIdentity();
Preconditions.checkCallAuthorization(hasFullCrossUsersPermission(caller, userHandle));
- Preconditions.checkCallAuthorization(isManagedProfile(userHandle), String.format("You can "
- + "not get organization color outside a managed profile, userId = %d", userHandle));
+ Preconditions.checkCallAuthorization(isManagedProfile(userHandle), "You can "
+ + "not get organization color outside a managed profile, userId = %d", userHandle);
synchronized (getLockObject()) {
ActiveAdmin profileOwner = getProfileOwnerAdminLocked(userHandle);
@@ -12431,9 +12483,9 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
final CallerIdentity caller = getCallerIdentity();
Preconditions.checkCallAuthorization(hasFullCrossUsersPermission(caller, userHandle));
- Preconditions.checkCallAuthorization(isManagedProfile(userHandle), String.format(
+ Preconditions.checkCallAuthorization(isManagedProfile(userHandle),
"You can not get organization name outside a managed profile, userId = %d",
- userHandle));
+ userHandle);
synchronized (getLockObject()) {
ActiveAdmin profileOwner = getProfileOwnerAdminLocked(userHandle);
@@ -12449,7 +12501,7 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
Objects.requireNonNull(packageNames);
final CallerIdentity caller = getCallerIdentity(who);
Preconditions.checkCallAuthorization(isDeviceOwner(caller) || isProfileOwner(caller),
- String.format("Admin %s does not own the profile", caller.getComponentName()));
+ "Admin %s does not own the profile", caller.getComponentName());
if (!mHasFeature) {
return packageNames;
@@ -12500,7 +12552,7 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
}
final CallerIdentity caller = getCallerIdentity(who);
Preconditions.checkCallAuthorization(isDeviceOwner(caller) || isProfileOwner(caller),
- String.format("Admin %s does not own the profile", caller.getComponentName()));
+ "Admin %s does not own the profile", caller.getComponentName());
synchronized (getLockObject()) {
final ActiveAdmin admin = getProfileOwnerOrDeviceOwnerLocked(caller);
@@ -12633,9 +12685,11 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
}
final Set<String> affiliationIds = new ArraySet<>(ids);
- final int callingUserId = mInjector.userHandleGetCallingUserId();
+ final CallerIdentity caller = getAdminCallerIdentity(admin);
+ Preconditions.checkCallAuthorization(isProfileOwner(caller) || isDeviceOwner(caller));
+ final int callingUserId = caller.getUserId();
+
synchronized (getLockObject()) {
- getActiveAdminForCallerLocked(admin, DeviceAdminInfo.USES_POLICY_PROFILE_OWNER);
getUserData(callingUserId).mAffiliationIds = affiliationIds;
saveSettingsLocked(callingUserId);
if (callingUserId != UserHandle.USER_SYSTEM && isDeviceOwner(admin, callingUserId)) {
@@ -12661,10 +12715,11 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
}
Objects.requireNonNull(admin);
+ final CallerIdentity caller = getCallerIdentity(admin);
+ Preconditions.checkCallAuthorization(isProfileOwner(caller) || isDeviceOwner(caller));
+
synchronized (getLockObject()) {
- getActiveAdminForCallerLocked(admin, DeviceAdminInfo.USES_POLICY_PROFILE_OWNER);
- return new ArrayList<String>(
- getUserData(mInjector.userHandleGetCallingUserId()).mAffiliationIds);
+ return new ArrayList<String>(getUserData(caller.getUserId()).mAffiliationIds);
}
}
@@ -13174,11 +13229,11 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
return Collections.emptyList();
}
Objects.requireNonNull(admin);
+ final CallerIdentity caller = getCallerIdentity(admin);
+ Preconditions.checkCallAuthorization(isProfileOwner(caller) || isDeviceOwner(caller));
synchronized (getLockObject()) {
- getActiveAdminForCallerLocked(admin, DeviceAdminInfo.USES_POLICY_PROFILE_OWNER);
-
- final int callingUserId = mInjector.userHandleGetCallingUserId();
+ final int callingUserId = caller.getUserId();
return mInjector.binderWithCleanCallingIdentity(() -> {
ArrayList<UserHandle> targetUsers = new ArrayList<>();
if (!isDeviceOwner(admin, callingUserId)) {
@@ -13494,8 +13549,9 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
final PackageManagerInternal pm = mInjector.getPackageManagerInternal();
final Intent intent = new Intent(DevicePolicyManager.ACTION_SHOW_DEVICE_MONITORING_DIALOG);
intent.setPackage(pm.getSystemUiServiceComponent().getPackageName());
- final PendingIntent pendingIntent = PendingIntent.getBroadcastAsUser(mContext, 0, intent, 0,
- UserHandle.CURRENT);
+ // Simple notification clicks are immutable
+ final PendingIntent pendingIntent = PendingIntent.getBroadcastAsUser(mContext, 0, intent,
+ PendingIntent.FLAG_IMMUTABLE, UserHandle.CURRENT);
Notification notification =
new Notification.Builder(mContext, SystemNotificationChannels.DEVICE_ADMIN)
.setSmallIcon(R.drawable.ic_info_outline)
@@ -13581,9 +13637,11 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
if (token == null || token.length < 32) {
throw new IllegalArgumentException("token must be at least 32-byte long");
}
+ final CallerIdentity caller = getAdminCallerIdentity(admin);
+ Preconditions.checkCallAuthorization(isProfileOwner(caller) || isDeviceOwner(caller));
+
synchronized (getLockObject()) {
- final int userHandle = mInjector.userHandleGetCallingUserId();
- getActiveAdminForCallerLocked(admin, DeviceAdminInfo.USES_POLICY_PROFILE_OWNER);
+ final int userHandle = caller.getUserId();
DevicePolicyData policy = getUserData(userHandle);
return mInjector.binderWithCleanCallingIdentity(() -> {
@@ -13603,9 +13661,11 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
if (!mHasFeature || !mLockPatternUtils.hasSecureLockScreen()) {
return false;
}
+ final CallerIdentity caller = getAdminCallerIdentity(admin);
+ Preconditions.checkCallAuthorization(isProfileOwner(caller) || isDeviceOwner(caller));
+
synchronized (getLockObject()) {
- final int userHandle = mInjector.userHandleGetCallingUserId();
- getActiveAdminForCallerLocked(admin, DeviceAdminInfo.USES_POLICY_PROFILE_OWNER);
+ final int userHandle = caller.getUserId();
DevicePolicyData policy = getUserData(userHandle);
if (policy.mPasswordTokenHandle != 0) {
@@ -13626,11 +13686,11 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
if (!mHasFeature || !mLockPatternUtils.hasSecureLockScreen()) {
return false;
}
- synchronized (getLockObject()) {
- final int userHandle = mInjector.userHandleGetCallingUserId();
- getActiveAdminForCallerLocked(admin, DeviceAdminInfo.USES_POLICY_PROFILE_OWNER);
+ final CallerIdentity caller = getAdminCallerIdentity(admin);
+ Preconditions.checkCallAuthorization(isProfileOwner(caller) || isDeviceOwner(caller));
- return isResetPasswordTokenActiveForUserLocked(userHandle);
+ synchronized (getLockObject()) {
+ return isResetPasswordTokenActiveForUserLocked(caller.getUserId());
}
}
@@ -13650,15 +13710,16 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
return false;
}
Objects.requireNonNull(token);
- synchronized (getLockObject()) {
- final int userHandle = mInjector.userHandleGetCallingUserId();
- getActiveAdminForCallerLocked(admin, DeviceAdminInfo.USES_POLICY_PROFILE_OWNER);
- DevicePolicyData policy = getUserData(userHandle);
+ final CallerIdentity caller = getAdminCallerIdentity(admin);
+ Preconditions.checkCallAuthorization(isProfileOwner(caller) || isDeviceOwner(caller));
+
+ synchronized (getLockObject()) {
+ DevicePolicyData policy = getUserData(caller.getUserId());
if (policy.mPasswordTokenHandle != 0) {
final String password = passwordOrNull != null ? passwordOrNull : "";
return resetPasswordInternal(password, policy.mPasswordTokenHandle, token,
- flags, mInjector.binderGetCallingUid());
+ flags, caller);
} else {
Slog.w(LOG_TAG, "No saved token handle");
}
@@ -13973,9 +14034,11 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
@Override
@Nullable
public PersistableBundle getTransferOwnershipBundle() {
+ final CallerIdentity caller = getCallerIdentity();
+ Preconditions.checkCallAuthorization(isProfileOwner(caller) || isDeviceOwner(caller));
+
synchronized (getLockObject()) {
- final int callingUserId = mInjector.userHandleGetCallingUserId();
- getActiveAdminForCallerLocked(null, DeviceAdminInfo.USES_POLICY_PROFILE_OWNER);
+ final int callingUserId = caller.getUserId();
final File bundleFile = new File(
mInjector.environmentGetUserSystemDirectory(callingUserId),
TRANSFER_OWNERSHIP_PARAMETERS_XML);
@@ -14159,8 +14222,8 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
parametersFile.delete();
}
- private void maybeLogPasswordComplexitySet(ComponentName who, int userId, boolean parent,
- PasswordPolicy passwordPolicy) {
+ private void logPasswordQualitySetIfSecurityLogEnabled(ComponentName who, int userId,
+ boolean parent, PasswordPolicy passwordPolicy) {
if (SecurityLog.isLoggingEnabled()) {
final int affectedUserId = parent ? getProfileParentId(userId) : userId;
SecurityLog.writeEvent(SecurityLog.TAG_PASSWORD_COMPLEXITY_SET, who.getPackageName(),
@@ -14708,7 +14771,7 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
Preconditions.checkCallAuthorization(isProfileOwnerOfOrganizationOwnedDevice(caller));
synchronized (getLockObject()) {
- final ActiveAdmin admin = getProfileOwnerOfCallerLocked(caller);
+ final ActiveAdmin admin = getProfileOwnerLocked(caller);
final long deadline = admin.mProfileOffDeadline;
final int result = makeSuspensionReasons(admin.mSuspendPersonalApps,
deadline != 0 && mInjector.systemCurrentTimeMillis() > deadline);
@@ -14741,7 +14804,7 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
final int callingUserId = caller.getUserId();
synchronized (getLockObject()) {
- final ActiveAdmin admin = getProfileOwnerOfCallerLocked(caller);
+ final ActiveAdmin admin = getProfileOwnerLocked(caller);
boolean shouldSaveSettings = false;
if (admin.mSuspendPersonalApps != suspended) {
admin.mSuspendPersonalApps = suspended;
@@ -14879,9 +14942,11 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
final AlarmManager am = mInjector.getAlarmManager();
final Intent intent = new Intent(ACTION_PROFILE_OFF_DEADLINE);
intent.setPackage(mContext.getPackageName());
+ // Broadcast alarms sent by system are immutable
final PendingIntent pi = mInjector.pendingIntentGetBroadcast(
mContext, REQUEST_PROFILE_OFF_DEADLINE, intent,
- PendingIntent.FLAG_ONE_SHOT | PendingIntent.FLAG_UPDATE_CURRENT);
+ PendingIntent.FLAG_ONE_SHOT | PendingIntent.FLAG_UPDATE_CURRENT
+ | PendingIntent.FLAG_IMMUTABLE);
if (alarmTime == 0) {
Slog.i(LOG_TAG, "Profile off deadline alarm is removed.");
@@ -14942,8 +15007,10 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
intent.setPackage(mContext.getPackageName());
intent.putExtra(Intent.EXTRA_USER_HANDLE, profileUserId);
+ // Simple notification action button clicks are immutable
final PendingIntent pendingIntent = mInjector.pendingIntentGetBroadcast(mContext,
- 0 /* requestCode */, intent, PendingIntent.FLAG_UPDATE_CURRENT);
+ 0 /* requestCode */, intent,
+ PendingIntent.FLAG_UPDATE_CURRENT | PendingIntent.FLAG_IMMUTABLE);
final String buttonText =
mContext.getString(R.string.personal_apps_suspended_turn_profile_on);
@@ -15002,7 +15069,7 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
final int userId = caller.getUserId();
synchronized (getLockObject()) {
- final ActiveAdmin admin = getProfileOwnerOfCallerLocked(caller);
+ final ActiveAdmin admin = getProfileOwnerLocked(caller);
// Ensure the timeout is long enough to avoid having bad user experience.
if (timeoutMillis > 0 && timeoutMillis < MANAGED_PROFILE_MAXIMUM_TIME_OFF_THRESHOLD
@@ -15047,7 +15114,7 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
Preconditions.checkCallAuthorization(isProfileOwnerOfOrganizationOwnedDevice(caller));
synchronized (getLockObject()) {
- final ActiveAdmin admin = getProfileOwnerOfCallerLocked(caller);
+ final ActiveAdmin admin = getProfileOwnerLocked(caller);
return admin.mProfileMaximumTimeOffMillis;
}
}
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/RemoteBugreportManager.java b/services/devicepolicy/java/com/android/server/devicepolicy/RemoteBugreportManager.java
index 46c9aab5bb97..543f3815454e 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/RemoteBugreportManager.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/RemoteBugreportManager.java
@@ -137,8 +137,9 @@ public class RemoteBugreportManager {
Slog.wtf(LOG_TAG, "Failed to resolve intent for remote bugreport dialog");
}
+ // Simple notification clicks are immutable
final PendingIntent pendingDialogIntent = PendingIntent.getActivityAsUser(mContext, type,
- dialogIntent, 0, null, UserHandle.CURRENT);
+ dialogIntent, PendingIntent.FLAG_IMMUTABLE, null, UserHandle.CURRENT);
final Notification.Builder builder =
new Notification.Builder(mContext, SystemNotificationChannels.DEVICE_ADMIN)
@@ -158,12 +159,14 @@ public class RemoteBugreportManager {
R.string.taking_remote_bugreport_notification_title))
.setProgress(0, 0, true);
} else if (type == NOTIFICATION_BUGREPORT_FINISHED_NOT_ACCEPTED) {
+ // Simple notification action button clicks are immutable
final PendingIntent pendingIntentAccept = PendingIntent.getBroadcast(mContext,
NOTIFICATION_ID, new Intent(ACTION_BUGREPORT_SHARING_ACCEPTED),
- PendingIntent.FLAG_CANCEL_CURRENT);
+ PendingIntent.FLAG_CANCEL_CURRENT | PendingIntent.FLAG_IMMUTABLE);
+ // Simple notification action button clicks are immutable
final PendingIntent pendingIntentDecline = PendingIntent.getBroadcast(mContext,
NOTIFICATION_ID, new Intent(ACTION_BUGREPORT_SHARING_DECLINED),
- PendingIntent.FLAG_CANCEL_CURRENT);
+ PendingIntent.FLAG_CANCEL_CURRENT | PendingIntent.FLAG_IMMUTABLE);
builder.addAction(new Notification.Action.Builder(null /* icon */, mContext.getString(
R.string.decline_remote_bugreport_action), pendingIntentDecline).build())
.addAction(new Notification.Action.Builder(null /* icon */, mContext.getString(
diff --git a/services/incremental/BinderIncrementalService.cpp b/services/incremental/BinderIncrementalService.cpp
index 2f8825b064ce..a31aac96eb48 100644
--- a/services/incremental/BinderIncrementalService.cpp
+++ b/services/incremental/BinderIncrementalService.cpp
@@ -323,6 +323,22 @@ binder::Status BinderIncrementalService::unregisterLoadingProgressListener(int32
return ok();
}
+binder::Status BinderIncrementalService::registerStorageHealthListener(
+ int32_t storageId,
+ const ::android::os::incremental::StorageHealthCheckParams& healthCheckParams,
+ const ::android::sp<IStorageHealthListener>& healthListener, bool* _aidl_return) {
+ *_aidl_return = mImpl.registerStorageHealthListener(storageId,
+ const_cast<StorageHealthCheckParams&&>(
+ healthCheckParams),
+ healthListener);
+ return ok();
+}
+
+binder::Status BinderIncrementalService::unregisterStorageHealthListener(int32_t storageId) {
+ mImpl.unregisterStorageHealthListener(storageId);
+ return ok();
+}
+
} // namespace android::os::incremental
jlong Incremental_IncrementalService_Start(JNIEnv* env) {
diff --git a/services/incremental/BinderIncrementalService.h b/services/incremental/BinderIncrementalService.h
index 0a89166f4868..8afa0f7bb117 100644
--- a/services/incremental/BinderIncrementalService.h
+++ b/services/incremental/BinderIncrementalService.h
@@ -89,6 +89,11 @@ public:
progressListener,
bool* _aidl_return) final;
binder::Status unregisterLoadingProgressListener(int32_t storageId, bool* _aidl_return) final;
+ binder::Status registerStorageHealthListener(
+ int32_t storageId,
+ const ::android::os::incremental::StorageHealthCheckParams& healthCheckParams,
+ const ::android::sp<IStorageHealthListener>& healthListener, bool* _aidl_return) final;
+ binder::Status unregisterStorageHealthListener(int32_t storageId) final;
private:
android::incremental::IncrementalService mImpl;
diff --git a/services/incremental/IncrementalService.cpp b/services/incremental/IncrementalService.cpp
index 5f145f33f628..599ac9344e73 100644
--- a/services/incremental/IncrementalService.cpp
+++ b/services/incremental/IncrementalService.cpp
@@ -1801,6 +1801,31 @@ bool IncrementalService::unregisterLoadingProgressListener(StorageId storage) {
return removeTimedJobs(*mProgressUpdateJobQueue, storage);
}
+bool IncrementalService::registerStorageHealthListener(
+ StorageId storage, StorageHealthCheckParams&& healthCheckParams,
+ const StorageHealthListener& healthListener) {
+ DataLoaderStubPtr dataLoaderStub;
+ {
+ std::unique_lock l(mLock);
+ const auto& ifs = getIfsLocked(storage);
+ if (!ifs) {
+ return false;
+ }
+ dataLoaderStub = ifs->dataLoaderStub;
+ if (!dataLoaderStub) {
+ return false;
+ }
+ }
+ dataLoaderStub->setHealthListener(std::move(healthCheckParams), &healthListener);
+ return true;
+}
+
+void IncrementalService::unregisterStorageHealthListener(StorageId storage) {
+ StorageHealthCheckParams invalidCheckParams;
+ invalidCheckParams.blockedTimeoutMs = -1;
+ registerStorageHealthListener(storage, std::move(invalidCheckParams), {});
+}
+
bool IncrementalService::perfLoggingEnabled() {
static const bool enabled = base::GetBoolProperty("incremental.perflogging", false);
return enabled;
@@ -2137,6 +2162,19 @@ binder::Status IncrementalService::DataLoaderStub::onStatusChanged(MountId mount
binder::Status IncrementalService::DataLoaderStub::reportStreamHealth(MountId mountId,
int newStatus) {
+ if (!isValid()) {
+ return binder::Status::
+ fromServiceSpecificError(-EINVAL,
+ "reportStreamHealth came to invalid DataLoaderStub");
+ }
+ if (id() != mountId) {
+ LOG(ERROR) << "Mount ID mismatch: expected " << id() << ", but got: " << mountId;
+ return binder::Status::fromServiceSpecificError(-EPERM, "Mount ID mismatch.");
+ }
+ {
+ std::lock_guard lock(mMutex);
+ mStreamStatus = newStatus;
+ }
return binder::Status::ok();
}
@@ -2153,6 +2191,33 @@ void IncrementalService::DataLoaderStub::onHealthStatus(StorageHealthListener he
}
}
+static int adjustHealthStatus(int healthStatus, int streamStatus) {
+ if (healthStatus == IStorageHealthListener::HEALTH_STATUS_OK) {
+ // everything is good; no need to change status
+ return healthStatus;
+ }
+ int newHeathStatus = healthStatus;
+ switch (streamStatus) {
+ case IDataLoaderStatusListener::STREAM_STORAGE_ERROR:
+ // storage is limited and storage not healthy
+ newHeathStatus = IStorageHealthListener::HEALTH_STATUS_UNHEALTHY_STORAGE;
+ break;
+ case IDataLoaderStatusListener::STREAM_INTEGRITY_ERROR:
+ // fall through
+ case IDataLoaderStatusListener::STREAM_SOURCE_ERROR:
+ // fall through
+ case IDataLoaderStatusListener::STREAM_TRANSPORT_ERROR:
+ if (healthStatus == IStorageHealthListener::HEALTH_STATUS_UNHEALTHY) {
+ newHeathStatus = IStorageHealthListener::HEALTH_STATUS_UNHEALTHY_TRANSPORT;
+ }
+ // pending/blocked status due to transportation issues is not regarded as unhealthy
+ break;
+ default:
+ break;
+ }
+ return newHeathStatus;
+}
+
void IncrementalService::DataLoaderStub::updateHealthStatus(bool baseline) {
LOG(DEBUG) << id() << ": updateHealthStatus" << (baseline ? " (baseline)" : "");
@@ -2232,6 +2297,8 @@ void IncrementalService::DataLoaderStub::updateHealthStatus(bool baseline) {
checkBackAfter = unhealthyMonitoring;
healthStatusToReport = IStorageHealthListener::HEALTH_STATUS_UNHEALTHY;
}
+ // Adjust health status based on stream status
+ healthStatusToReport = adjustHealthStatus(healthStatusToReport, mStreamStatus);
LOG(DEBUG) << id() << ": updateHealthStatus in " << double(checkBackAfter.count()) / 1000.0
<< "secs";
mService.addTimedJob(*mService.mTimedQueue, id(), checkBackAfter,
@@ -2321,6 +2388,18 @@ void IncrementalService::DataLoaderStub::unregisterFromPendingReads() {
mService.mLooper->wake();
}
+void IncrementalService::DataLoaderStub::setHealthListener(
+ StorageHealthCheckParams&& healthCheckParams, const StorageHealthListener* healthListener) {
+ std::lock_guard lock(mMutex);
+ mHealthCheckParams = std::move(healthCheckParams);
+ if (healthListener == nullptr) {
+ // reset listener and params
+ mHealthListener = {};
+ } else {
+ mHealthListener = *healthListener;
+ }
+}
+
void IncrementalService::DataLoaderStub::onDump(int fd) {
dprintf(fd, " dataLoader: {\n");
dprintf(fd, " currentStatus: %d\n", mCurrentStatus);
diff --git a/services/incremental/IncrementalService.h b/services/incremental/IncrementalService.h
index 504c02a57b86..4c4b8bd1ba50 100644
--- a/services/incremental/IncrementalService.h
+++ b/services/incremental/IncrementalService.h
@@ -140,7 +140,10 @@ public:
bool registerLoadingProgressListener(StorageId storage,
const StorageLoadingProgressListener& progressListener);
bool unregisterLoadingProgressListener(StorageId storage);
-
+ bool registerStorageHealthListener(StorageId storage,
+ StorageHealthCheckParams&& healthCheckParams,
+ const StorageHealthListener& healthListener);
+ void unregisterStorageHealthListener(StorageId storage);
RawMetadata getMetadata(StorageId storage, std::string_view path) const;
RawMetadata getMetadata(StorageId storage, FileId node) const;
@@ -197,6 +200,8 @@ private:
MountId id() const { return mId.load(std::memory_order_relaxed); }
const content::pm::DataLoaderParamsParcel& params() const { return mParams; }
+ void setHealthListener(StorageHealthCheckParams&& healthCheckParams,
+ const StorageHealthListener* healthListener);
private:
binder::Status onStatusChanged(MountId mount, int newStatus) final;
@@ -251,6 +256,7 @@ private:
BootClockTsUs kernelTsUs;
} mHealthBase = {TimePoint::max(), kMaxBootClockTsUs};
StorageHealthCheckParams mHealthCheckParams;
+ int mStreamStatus = content::pm::IDataLoaderStatusListener::STREAM_HEALTHY;
};
using DataLoaderStubPtr = sp<DataLoaderStub>;
diff --git a/services/incremental/test/IncrementalServiceTest.cpp b/services/incremental/test/IncrementalServiceTest.cpp
index aec9fa1c3277..867312e0eb2f 100644
--- a/services/incremental/test/IncrementalServiceTest.cpp
+++ b/services/incremental/test/IncrementalServiceTest.cpp
@@ -177,6 +177,18 @@ public:
}
return binder::Status::ok();
}
+ binder::Status storageError(int32_t id) {
+ if (mListener) {
+ mListener->reportStreamHealth(id, IDataLoaderStatusListener::STREAM_STORAGE_ERROR);
+ }
+ return binder::Status::ok();
+ }
+ binder::Status transportError(int32_t id) {
+ if (mListener) {
+ mListener->reportStreamHealth(id, IDataLoaderStatusListener::STREAM_INTEGRITY_ERROR);
+ }
+ return binder::Status::ok();
+ }
int32_t setStorageParams(bool enableReadLogs) {
int32_t result = -1;
EXPECT_NE(mServiceConnector.get(), nullptr);
@@ -1221,4 +1233,83 @@ TEST_F(IncrementalServiceTest, testRegisterLoadingProgressListenerFailsToGetProg
EXPECT_CALL(*listenerMock, onStorageLoadingProgressChanged(_, _)).Times(0);
mIncrementalService->registerLoadingProgressListener(storageId, listener);
}
+
+TEST_F(IncrementalServiceTest, testRegisterStorageHealthListenerSuccess) {
+ mIncFs->openMountSuccess();
+ sp<NiceMock<MockStorageHealthListener>> listener{new NiceMock<MockStorageHealthListener>};
+ sp<NiceMock<MockStorageHealthListener>> newListener{new NiceMock<MockStorageHealthListener>};
+ NiceMock<MockStorageHealthListener>* newListenerMock = newListener.get();
+
+ TemporaryDir tempDir;
+ int storageId = mIncrementalService->createStorage(tempDir.path, std::move(mDataLoaderParcel),
+ IncrementalService::CreateOptions::CreateNew,
+ {}, StorageHealthCheckParams{}, listener);
+ ASSERT_GE(storageId, 0);
+ StorageHealthCheckParams newParams;
+ newParams.blockedTimeoutMs = 10000;
+ newParams.unhealthyTimeoutMs = 20000;
+ newParams.unhealthyMonitoringMs = 30000;
+ ASSERT_TRUE(mIncrementalService->registerStorageHealthListener(storageId, std::move(newParams),
+ newListener));
+
+ using MS = std::chrono::milliseconds;
+ using MCS = std::chrono::microseconds;
+
+ const auto blockedTimeout = MS(newParams.blockedTimeoutMs);
+ const auto unhealthyTimeout = MS(newParams.unhealthyTimeoutMs);
+
+ const uint64_t kFirstTimestampUs = 1000000000ll;
+ const uint64_t kBlockedTimestampUs =
+ kFirstTimestampUs - std::chrono::duration_cast<MCS>(blockedTimeout).count();
+ const uint64_t kUnhealthyTimestampUs =
+ kFirstTimestampUs - std::chrono::duration_cast<MCS>(unhealthyTimeout).count();
+
+ // test that old listener was not called
+ EXPECT_CALL(*listener.get(),
+ onHealthStatus(_, IStorageHealthListener::HEALTH_STATUS_READS_PENDING))
+ .Times(0);
+ EXPECT_CALL(*newListenerMock,
+ onHealthStatus(_, IStorageHealthListener::HEALTH_STATUS_READS_PENDING))
+ .Times(1);
+ EXPECT_CALL(*newListenerMock, onHealthStatus(_, IStorageHealthListener::HEALTH_STATUS_BLOCKED))
+ .Times(1);
+ EXPECT_CALL(*newListenerMock,
+ onHealthStatus(_, IStorageHealthListener::HEALTH_STATUS_UNHEALTHY_STORAGE))
+ .Times(1);
+ EXPECT_CALL(*newListenerMock,
+ onHealthStatus(_, IStorageHealthListener::HEALTH_STATUS_UNHEALTHY_TRANSPORT))
+ .Times(1);
+ mIncFs->waitForPendingReadsSuccess(kFirstTimestampUs);
+ mLooper->mCallback(-1, -1, mLooper->mCallbackData);
+
+ ASSERT_EQ(IStorageHealthListener::HEALTH_STATUS_READS_PENDING, newListener->mStatus);
+ ASSERT_EQ(storageId, newListener->mStorageId);
+
+ auto timedCallback = mTimedQueue->mWhat;
+ mTimedQueue->clearJob(storageId);
+
+ // test when health status is blocked with transport error
+ mDataLoader->transportError(storageId);
+ mIncFs->waitForPendingReadsSuccess(kBlockedTimestampUs);
+ timedCallback();
+ ASSERT_EQ(IStorageHealthListener::HEALTH_STATUS_BLOCKED, newListener->mStatus);
+ timedCallback = mTimedQueue->mWhat;
+ mTimedQueue->clearJob(storageId);
+
+ // test when health status is blocked with storage error
+ mDataLoader->storageError(storageId);
+ mIncFs->waitForPendingReadsSuccess(kBlockedTimestampUs);
+ timedCallback();
+ ASSERT_EQ(IStorageHealthListener::HEALTH_STATUS_UNHEALTHY_STORAGE, newListener->mStatus);
+ timedCallback = mTimedQueue->mWhat;
+ mTimedQueue->clearJob(storageId);
+
+ // test when health status is unhealthy with transport error
+ mDataLoader->transportError(storageId);
+ mIncFs->waitForPendingReadsSuccess(kUnhealthyTimestampUs);
+ timedCallback();
+ ASSERT_EQ(IStorageHealthListener::HEALTH_STATUS_UNHEALTHY_TRANSPORT, newListener->mStatus);
+ mTimedQueue->clearJob(storageId);
+}
+
} // namespace android::os::incremental
diff --git a/services/people/java/com/android/server/people/PeopleService.java b/services/people/java/com/android/server/people/PeopleService.java
index 91cb481a3b23..7c3b7a67178e 100644
--- a/services/people/java/com/android/server/people/PeopleService.java
+++ b/services/people/java/com/android/server/people/PeopleService.java
@@ -122,7 +122,7 @@ public class PeopleService extends SystemService {
@Override
public ParceledListSlice<ConversationChannel> getRecentConversations() {
- enforceSystemOrRoot("get recent conversations");
+ enforceSystemRootOrSystemUI(getContext(), "get recent conversations");
return new ParceledListSlice<>(
mDataManager.getRecentConversations(
Binder.getCallingUserHandle().getIdentifier()));
diff --git a/services/profcollect/src/com/android/server/profcollect/ProfcollectForwardingService.java b/services/profcollect/src/com/android/server/profcollect/ProfcollectForwardingService.java
index ddd1f7568224..d14ed5a15cf9 100644
--- a/services/profcollect/src/com/android/server/profcollect/ProfcollectForwardingService.java
+++ b/services/profcollect/src/com/android/server/profcollect/ProfcollectForwardingService.java
@@ -29,6 +29,8 @@ import android.os.Looper;
import android.os.RemoteException;
import android.os.ServiceManager;
import android.os.SystemProperties;
+import android.os.UpdateEngine;
+import android.os.UpdateEngineCallback;
import android.util.Log;
import com.android.server.IoThread;
@@ -198,6 +200,7 @@ public final class ProfcollectForwardingService extends SystemService {
// Event observers
private void registerObservers() {
registerAppLaunchObserver();
+ registerOTAObserver();
}
private final AppLaunchObserver mAppLaunchObserver = new AppLaunchObserver();
@@ -261,4 +264,33 @@ public final class ProfcollectForwardingService extends SystemService {
// Ignored
}
}
+
+ private void registerOTAObserver() {
+ UpdateEngine updateEngine = new UpdateEngine();
+ updateEngine.bind(new UpdateEngineCallback() {
+ @Override
+ public void onStatusUpdate(int status, float percent) {
+ if (status == UpdateEngine.UpdateStatusConstants.UPDATED_NEED_REBOOT) {
+ packProfileReport();
+ }
+ }
+
+ @Override
+ public void onPayloadApplicationComplete(int errorCode) {
+ // Ignored
+ }
+ });
+ }
+
+ private void packProfileReport() {
+ if (mIProfcollect == null) {
+ return;
+ }
+
+ try {
+ mIProfcollect.CreateProfileReport();
+ } catch (RemoteException e) {
+ Log.e(LOG_TAG, e.getMessage());
+ }
+ }
}
diff --git a/services/tests/PackageManagerComponentOverrideTests/src/com/android/server/pm/test/override/PackageManagerComponentLabelIconOverrideTest.kt b/services/tests/PackageManagerComponentOverrideTests/src/com/android/server/pm/test/override/PackageManagerComponentLabelIconOverrideTest.kt
index 09552082e4af..27b07c76fb0d 100644
--- a/services/tests/PackageManagerComponentOverrideTests/src/com/android/server/pm/test/override/PackageManagerComponentLabelIconOverrideTest.kt
+++ b/services/tests/PackageManagerComponentOverrideTests/src/com/android/server/pm/test/override/PackageManagerComponentLabelIconOverrideTest.kt
@@ -45,6 +45,7 @@ import org.junit.Before
import org.junit.Test
import org.junit.runner.RunWith
import org.junit.runners.Parameterized
+import org.mockito.Mockito
import org.mockito.Mockito.any
import org.mockito.Mockito.anyBoolean
import org.mockito.Mockito.anyInt
@@ -341,7 +342,8 @@ class PackageManagerComponentLabelIconOverrideTest {
whenever(this.userManagerService) { mockUserManagerService }
whenever(this.permissionManagerServiceInternal) { mockPermissionManagerService }
whenever(this.settings) { mockSettings }
- whenever(this.activityTaskManagerInternal) { mockActivityTaskManager }
+ whenever(this.getLocalService(ActivityTaskManagerInternal::class.java)) {
+ mockActivityTaskManager}
whenever(this.appsFilter) { mockAppsFilter }
whenever(this.context) { mockContext }
}
diff --git a/services/tests/servicestests/src/com/android/server/am/UserControllerTest.java b/services/tests/servicestests/src/com/android/server/am/UserControllerTest.java
index 6f4ff35ba0df..04de6ca192ef 100644
--- a/services/tests/servicestests/src/com/android/server/am/UserControllerTest.java
+++ b/services/tests/servicestests/src/com/android/server/am/UserControllerTest.java
@@ -153,7 +153,7 @@ public class UserControllerTest {
doNothing().when(mInjector).startHomeActivity(anyInt(), anyString());
doReturn(false).when(mInjector).stackSupervisorSwitchUser(anyInt(), any());
doNothing().when(mInjector).stackSupervisorResumeFocusedStackTopActivity();
- doNothing().when(mInjector).systemServiceManagerCleanupUser(anyInt());
+ doNothing().when(mInjector).systemServiceManagerOnUserStopped(anyInt());
doNothing().when(mInjector).activityManagerForceStopPackage(anyInt(), anyString());
doNothing().when(mInjector).activityManagerOnUserStopped(anyInt());
doNothing().when(mInjector).clearBroadcastQueueForUser(anyInt());
diff --git a/services/tests/servicestests/src/com/android/server/compat/CompatConfigBuilder.java b/services/tests/servicestests/src/com/android/server/compat/CompatConfigBuilder.java
index 2cbe7be8ac33..870fe4a0837e 100644
--- a/services/tests/servicestests/src/com/android/server/compat/CompatConfigBuilder.java
+++ b/services/tests/servicestests/src/com/android/server/compat/CompatConfigBuilder.java
@@ -39,58 +39,79 @@ class CompatConfigBuilder {
return new CompatConfigBuilder(buildClassifier, context);
}
- CompatConfigBuilder addTargetSdkChangeWithId(int sdk, long id) {
- mChanges.add(new CompatChange(id, "", sdk, false, false, ""));
+ CompatConfigBuilder addEnableAfterSdkChangeWithId(int sdk, long id) {
+ mChanges.add(new CompatChange(id, "", sdk, -1, false, false, ""));
return this;
}
- CompatConfigBuilder addTargetSdkDisabledChangeWithId(int sdk, long id) {
- mChanges.add(new CompatChange(id, "", sdk, true, false, ""));
+ CompatConfigBuilder addEnableAfterSdkChangeWithIdAndName(int sdk, long id, String name) {
+ mChanges.add(new CompatChange(id, name, sdk, -1, false, false, ""));
return this;
}
- CompatConfigBuilder addTargetSdkChangeWithIdAndName(int sdk, long id, String name) {
- mChanges.add(new CompatChange(id, name, sdk, false, false, ""));
+ CompatConfigBuilder addEnableAfterSdkChangeWithIdDefaultDisabled(int sdk, long id) {
+ mChanges.add(new CompatChange(id, "", sdk, -1, true, false, ""));
return this;
}
- CompatConfigBuilder addTargetSdkChangeWithIdAndDescription(int sdk, long id,
+ CompatConfigBuilder addEnableAfterSdkChangeWithIdAndDescription(int sdk, long id,
String description) {
- mChanges.add(new CompatChange(id, "", sdk, false, false, description));
+ mChanges.add(new CompatChange(id, "", sdk, -1, false, false, description));
+ return this;
+ }
+
+ CompatConfigBuilder addEnableSinceSdkChangeWithId(int sdk, long id) {
+ mChanges.add(new CompatChange(id, "", -1, sdk, false, false, ""));
+ return this;
+ }
+
+ CompatConfigBuilder addEnableSinceSdkChangeWithIdAndName(int sdk, long id, String name) {
+ mChanges.add(new CompatChange(id, name, -1, sdk, false, false, ""));
+ return this;
+ }
+
+ CompatConfigBuilder addEnableSinceSdkChangeWithIdDefaultDisabled(int sdk, long id) {
+ mChanges.add(new CompatChange(id, "", -1, sdk, true, false, ""));
+ return this;
+ }
+
+ CompatConfigBuilder addEnableSinceSdkChangeWithIdAndDescription(int sdk, long id,
+ String description) {
+ mChanges.add(new CompatChange(id, "", -1, sdk, false, false, description));
return this;
}
CompatConfigBuilder addEnabledChangeWithId(long id) {
- mChanges.add(new CompatChange(id, "", -1, false, false, ""));
+ mChanges.add(new CompatChange(id, "", -1, -1, false, false, ""));
return this;
}
CompatConfigBuilder addEnabledChangeWithIdAndName(long id, String name) {
- mChanges.add(new CompatChange(id, name, -1, false, false, ""));
+ mChanges.add(new CompatChange(id, name, -1, -1, false, false, ""));
return this;
}
CompatConfigBuilder addEnabledChangeWithIdAndDescription(long id, String description) {
- mChanges.add(new CompatChange(id, "", -1, false, false, description));
+ mChanges.add(new CompatChange(id, "", -1, -1, false, false, description));
return this;
}
CompatConfigBuilder addDisabledChangeWithId(long id) {
- mChanges.add(new CompatChange(id, "", -1, true, false, ""));
+ mChanges.add(new CompatChange(id, "", -1, -1, true, false, ""));
return this;
}
CompatConfigBuilder addDisabledChangeWithIdAndName(long id, String name) {
- mChanges.add(new CompatChange(id, name, -1, true, false, ""));
+ mChanges.add(new CompatChange(id, name, -1, -1, true, false, ""));
return this;
}
CompatConfigBuilder addDisabledChangeWithIdAndDescription(long id, String description) {
- mChanges.add(new CompatChange(id, "", -1, true, false, description));
+ mChanges.add(new CompatChange(id, "", -1, -1, true, false, description));
return this;
}
CompatConfigBuilder addLoggingOnlyChangeWithId(long id) {
- mChanges.add(new CompatChange(id, "", -1, false, true, ""));
+ mChanges.add(new CompatChange(id, "", -1, -1, false, true, ""));
return this;
}
diff --git a/services/tests/servicestests/src/com/android/server/compat/CompatConfigTest.java b/services/tests/servicestests/src/com/android/server/compat/CompatConfigTest.java
index 8be9213fd925..e5883708e921 100644
--- a/services/tests/servicestests/src/com/android/server/compat/CompatConfigTest.java
+++ b/services/tests/servicestests/src/com/android/server/compat/CompatConfigTest.java
@@ -98,7 +98,7 @@ public class CompatConfigTest {
@Test
public void testTargetSdkChangeDisabled() throws Exception {
CompatConfig compatConfig = CompatConfigBuilder.create(mBuildClassifier, mContext)
- .addTargetSdkChangeWithId(2, 1234L)
+ .addEnableAfterSdkChangeWithId(2, 1234L)
.build();
assertThat(compatConfig.isChangeEnabled(1234L,
@@ -109,7 +109,7 @@ public class CompatConfigTest {
@Test
public void testTargetSdkChangeEnabled() throws Exception {
CompatConfig compatConfig = CompatConfigBuilder.create(mBuildClassifier, mContext)
- .addTargetSdkChangeWithId(2, 1234L)
+ .addEnableAfterSdkChangeWithId(2, 1234L)
.build();
assertThat(compatConfig.isChangeEnabled(1234L,
@@ -119,7 +119,7 @@ public class CompatConfigTest {
@Test
public void testDisabledOverrideTargetSdkChange() throws Exception {
CompatConfig compatConfig = CompatConfigBuilder.create(mBuildClassifier, mContext)
- .addTargetSdkDisabledChangeWithId(2, 1234L)
+ .addEnableAfterSdkChangeWithIdDefaultDisabled(2, 1234L)
.build();
assertThat(compatConfig.isChangeEnabled(1234L,
@@ -293,8 +293,8 @@ public class CompatConfigTest {
CompatConfig compatConfig = CompatConfigBuilder.create(mBuildClassifier, mContext)
.addEnabledChangeWithId(1L)
.addDisabledChangeWithId(2L)
- .addTargetSdkChangeWithId(3, 3L)
- .addTargetSdkChangeWithId(4, 4L)
+ .addEnableSinceSdkChangeWithId(3, 3L)
+ .addEnableSinceSdkChangeWithId(4, 4L)
.build();
ApplicationInfo applicationInfo = ApplicationInfoBuilder.create()
.withPackageName("foo.bar")
@@ -314,8 +314,8 @@ public class CompatConfigTest {
CompatConfig compatConfig = CompatConfigBuilder.create(mBuildClassifier, mContext)
.addEnabledChangeWithId(1L)
.addDisabledChangeWithId(2L)
- .addTargetSdkChangeWithId(3, 3L)
- .addTargetSdkChangeWithId(4, 4L)
+ .addEnableSinceSdkChangeWithId(3, 3L)
+ .addEnableSinceSdkChangeWithId(4, 4L)
.build();
ApplicationInfo applicationInfo = ApplicationInfoBuilder.create()
.withPackageName("foo.bar")
diff --git a/services/tests/servicestests/src/com/android/server/compat/OverrideValidatorImplTest.java b/services/tests/servicestests/src/com/android/server/compat/OverrideValidatorImplTest.java
index d45589d90ce3..c53b29a08a4a 100644
--- a/services/tests/servicestests/src/com/android/server/compat/OverrideValidatorImplTest.java
+++ b/services/tests/servicestests/src/com/android/server/compat/OverrideValidatorImplTest.java
@@ -87,9 +87,9 @@ public class OverrideValidatorImplTest {
public void getOverrideAllowedState_debugBuildAnyChangeDebugApp_allowOverride()
throws Exception {
CompatConfig config = CompatConfigBuilder.create(debuggableBuild(), mContext)
- .addTargetSdkChangeWithId(TARGET_SDK_BEFORE, 1)
- .addTargetSdkChangeWithId(TARGET_SDK, 2)
- .addTargetSdkChangeWithId(TARGET_SDK_AFTER, 3)
+ .addEnableAfterSdkChangeWithId(TARGET_SDK_BEFORE, 1)
+ .addEnableAfterSdkChangeWithId(TARGET_SDK, 2)
+ .addEnableAfterSdkChangeWithId(TARGET_SDK_AFTER, 3)
.addEnabledChangeWithId(4)
.addDisabledChangeWithId(5)
.addLoggingOnlyChangeWithId(6).build();
@@ -131,9 +131,9 @@ public class OverrideValidatorImplTest {
public void getOverrideAllowedState_debugBuildAnyChangeReleaseApp_allowOverride()
throws Exception {
CompatConfig config = CompatConfigBuilder.create(debuggableBuild(), mContext)
- .addTargetSdkChangeWithId(TARGET_SDK_BEFORE, 1)
- .addTargetSdkChangeWithId(TARGET_SDK, 2)
- .addTargetSdkChangeWithId(TARGET_SDK_AFTER, 3)
+ .addEnableAfterSdkChangeWithId(TARGET_SDK_BEFORE, 1)
+ .addEnableAfterSdkChangeWithId(TARGET_SDK, 2)
+ .addEnableAfterSdkChangeWithId(TARGET_SDK_AFTER, 3)
.addEnabledChangeWithId(4)
.addDisabledChangeWithId(5)
.addLoggingOnlyChangeWithId(6).build();
@@ -174,9 +174,9 @@ public class OverrideValidatorImplTest {
public void getOverrideAllowedState_betaBuildTargetSdkChangeDebugApp_allowOverride()
throws Exception {
CompatConfig config = CompatConfigBuilder.create(betaBuild(), mContext)
- .addTargetSdkChangeWithId(TARGET_SDK_BEFORE, 1)
- .addTargetSdkChangeWithId(TARGET_SDK, 2)
- .addTargetSdkChangeWithId(TARGET_SDK_AFTER, 3)
+ .addEnableAfterSdkChangeWithId(TARGET_SDK_BEFORE, 1)
+ .addEnableAfterSdkChangeWithId(TARGET_SDK, 2)
+ .addEnableAfterSdkChangeWithId(TARGET_SDK_AFTER, 3)
.addDisabledChangeWithId(4).build();
IOverrideValidator overrideValidator = config.getOverrideValidator();
when(mPackageManager.getApplicationInfo(eq(PACKAGE_NAME), anyInt()))
@@ -245,9 +245,9 @@ public class OverrideValidatorImplTest {
public void getOverrideAllowedState_betaBuildAnyChangeReleaseApp_rejectOverride()
throws Exception {
CompatConfig config = CompatConfigBuilder.create(betaBuild(), mContext)
- .addTargetSdkChangeWithId(TARGET_SDK_BEFORE, 1)
- .addTargetSdkChangeWithId(TARGET_SDK, 2)
- .addTargetSdkChangeWithId(TARGET_SDK_AFTER, 3)
+ .addEnableAfterSdkChangeWithId(TARGET_SDK_BEFORE, 1)
+ .addEnableAfterSdkChangeWithId(TARGET_SDK, 2)
+ .addEnableAfterSdkChangeWithId(TARGET_SDK_AFTER, 3)
.addEnabledChangeWithId(4)
.addDisabledChangeWithId(5)
.addLoggingOnlyChangeWithId(6).build();
@@ -288,8 +288,8 @@ public class OverrideValidatorImplTest {
public void getOverrideAllowedState_finalBuildTargetSdkChangeDebugAppOptin_allowOverride()
throws Exception {
CompatConfig config = CompatConfigBuilder.create(finalBuild(), mContext)
- .addTargetSdkChangeWithId(TARGET_SDK_AFTER, 1)
- .addTargetSdkChangeWithId(TARGET_SDK, 2).build();
+ .addEnableAfterSdkChangeWithId(TARGET_SDK_AFTER, 1)
+ .addEnableAfterSdkChangeWithId(TARGET_SDK, 2).build();
IOverrideValidator overrideValidator = config.getOverrideValidator();
when(mPackageManager.getApplicationInfo(eq(PACKAGE_NAME), anyInt()))
.thenReturn(ApplicationInfoBuilder.create()
@@ -313,7 +313,7 @@ public class OverrideValidatorImplTest {
public void getOverrideAllowedState_finalBuildTargetSdkChangeDebugAppOptout_rejectOverride()
throws Exception {
CompatConfig config = CompatConfigBuilder.create(finalBuild(), mContext)
- .addTargetSdkChangeWithId(TARGET_SDK_BEFORE, 1).build();
+ .addEnableAfterSdkChangeWithId(TARGET_SDK_BEFORE, 1).build();
IOverrideValidator overrideValidator = config.getOverrideValidator();
when(mPackageManager.getApplicationInfo(eq(PACKAGE_NAME), anyInt()))
.thenReturn(ApplicationInfoBuilder.create()
@@ -371,9 +371,9 @@ public class OverrideValidatorImplTest {
public void getOverrideAllowedState_finalBuildAnyChangeReleaseApp_rejectOverride()
throws Exception {
CompatConfig config = CompatConfigBuilder.create(finalBuild(), mContext)
- .addTargetSdkChangeWithId(TARGET_SDK_BEFORE, 1)
- .addTargetSdkChangeWithId(TARGET_SDK, 2)
- .addTargetSdkChangeWithId(TARGET_SDK_AFTER, 3)
+ .addEnableAfterSdkChangeWithId(TARGET_SDK_BEFORE, 1)
+ .addEnableAfterSdkChangeWithId(TARGET_SDK, 2)
+ .addEnableAfterSdkChangeWithId(TARGET_SDK_AFTER, 3)
.addEnabledChangeWithId(4)
.addDisabledChangeWithId(5)
.addLoggingOnlyChangeWithId(6).build();
diff --git a/services/tests/servicestests/src/com/android/server/compat/PlatformCompatTest.java b/services/tests/servicestests/src/com/android/server/compat/PlatformCompatTest.java
index cef02ffc3831..64014ba182d2 100644
--- a/services/tests/servicestests/src/com/android/server/compat/PlatformCompatTest.java
+++ b/services/tests/servicestests/src/com/android/server/compat/PlatformCompatTest.java
@@ -84,22 +84,22 @@ public class PlatformCompatTest {
mCompatConfig = CompatConfigBuilder.create(mBuildClassifier, mContext)
.addEnabledChangeWithId(1L)
.addDisabledChangeWithIdAndName(2L, "change2")
- .addTargetSdkChangeWithIdAndDescription(Build.VERSION_CODES.O, 3L, "description")
- .addTargetSdkChangeWithId(Build.VERSION_CODES.P, 4L)
- .addTargetSdkChangeWithId(Build.VERSION_CODES.Q, 5L)
- .addTargetSdkChangeWithId(Build.VERSION_CODES.R, 6L)
+ .addEnableAfterSdkChangeWithIdAndDescription(Build.VERSION_CODES.O, 3L, "desc")
+ .addEnableAfterSdkChangeWithId(Build.VERSION_CODES.P, 4L)
+ .addEnableAfterSdkChangeWithId(Build.VERSION_CODES.Q, 5L)
+ .addEnableAfterSdkChangeWithId(Build.VERSION_CODES.R, 6L)
.addLoggingOnlyChangeWithId(7L)
.build();
mPlatformCompat = new PlatformCompat(mContext, mCompatConfig);
assertThat(mPlatformCompat.listAllChanges()).asList().containsExactly(
- new CompatibilityChangeInfo(1L, "", -1, false, false, ""),
- new CompatibilityChangeInfo(2L, "change2", -1, true, false, ""),
- new CompatibilityChangeInfo(3L, "", Build.VERSION_CODES.O, false, false,
- "description"),
- new CompatibilityChangeInfo(4L, "", Build.VERSION_CODES.P, false, false, ""),
- new CompatibilityChangeInfo(5L, "", Build.VERSION_CODES.Q, false, false, ""),
- new CompatibilityChangeInfo(6L, "", Build.VERSION_CODES.R, false, false, ""),
- new CompatibilityChangeInfo(7L, "", -1, false, true, ""));
+ new CompatibilityChangeInfo(1L, "", -1, -1, false, false, ""),
+ new CompatibilityChangeInfo(2L, "change2", -1, -1, true, false, ""),
+ new CompatibilityChangeInfo(3L, "", Build.VERSION_CODES.O, -1, false, false,
+ "desc"),
+ new CompatibilityChangeInfo(4L, "", Build.VERSION_CODES.P, -1, false, false, ""),
+ new CompatibilityChangeInfo(5L, "", Build.VERSION_CODES.Q, -1, false, false, ""),
+ new CompatibilityChangeInfo(6L, "", Build.VERSION_CODES.R, -1, false, false, ""),
+ new CompatibilityChangeInfo(7L, "", -1, -1, false, true, ""));
}
@Test
@@ -107,18 +107,18 @@ public class PlatformCompatTest {
mCompatConfig = CompatConfigBuilder.create(mBuildClassifier, mContext)
.addEnabledChangeWithId(1L)
.addDisabledChangeWithIdAndName(2L, "change2")
- .addTargetSdkChangeWithIdAndDescription(Build.VERSION_CODES.O, 3L, "description")
- .addTargetSdkChangeWithId(Build.VERSION_CODES.P, 4L)
- .addTargetSdkChangeWithId(Build.VERSION_CODES.Q, 5L)
- .addTargetSdkChangeWithId(Build.VERSION_CODES.R, 6L)
+ .addEnableAfterSdkChangeWithIdAndDescription(Build.VERSION_CODES.O, 3L, "desc")
+ .addEnableAfterSdkChangeWithId(Build.VERSION_CODES.P, 4L)
+ .addEnableAfterSdkChangeWithId(Build.VERSION_CODES.Q, 5L)
+ .addEnableAfterSdkChangeWithId(Build.VERSION_CODES.R, 6L)
.addLoggingOnlyChangeWithId(7L)
.build();
mPlatformCompat = new PlatformCompat(mContext, mCompatConfig);
assertThat(mPlatformCompat.listUIChanges()).asList().containsExactly(
- new CompatibilityChangeInfo(1L, "", -1, false, false, ""),
- new CompatibilityChangeInfo(2L, "change2", -1, true, false, ""),
- new CompatibilityChangeInfo(4L, "", Build.VERSION_CODES.P, false, false, ""),
- new CompatibilityChangeInfo(5L, "", Build.VERSION_CODES.Q, false, false, ""));
+ new CompatibilityChangeInfo(1L, "", -1, -1, false, false, ""),
+ new CompatibilityChangeInfo(2L, "change2", -1, -1, true, false, ""),
+ new CompatibilityChangeInfo(4L, "", Build.VERSION_CODES.P, -1, false, false, ""),
+ new CompatibilityChangeInfo(5L, "", Build.VERSION_CODES.Q, -1, false, false, ""));
}
@Test
diff --git a/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java b/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java
index 631b4d48e9f2..c4f7b9547277 100644
--- a/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java
+++ b/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java
@@ -2814,7 +2814,7 @@ public class DevicePolicyManagerTest extends DpmTestBase {
exerciseUserProvisioningTransitions(CALLER_USER_HANDLE,
DevicePolicyManager.STATE_USER_PROFILE_COMPLETE,
- DevicePolicyManager.STATE_USER_UNMANAGED);
+ DevicePolicyManager.STATE_USER_PROFILE_FINALIZED);
}
public void testSetUserProvisioningState_managedProfileFromSetupWizard_managedProfile()
@@ -5728,6 +5728,7 @@ public class DevicePolicyManagerTest extends DpmTestBase {
// Device owner should be allowed to request Device ID attestation.
dpms.enforceCallerCanRequestDeviceIdAttestation(dpms.getCallerIdentity(admin1));
+ mContext.binder.callingUid = DpmMockContext.ANOTHER_UID;
// Another package must not be allowed to request Device ID attestation.
assertExpectException(SecurityException.class, null,
() -> dpms.enforceCallerCanRequestDeviceIdAttestation(
@@ -5757,6 +5758,7 @@ public class DevicePolicyManagerTest extends DpmTestBase {
dpms.enforceCallerCanRequestDeviceIdAttestation(dpms.getCallerIdentity(admin1));
// But not another package.
+ mContext.binder.callingUid = DpmMockContext.ANOTHER_UID;
assertExpectException(SecurityException.class, null,
() -> dpms.enforceCallerCanRequestDeviceIdAttestation(
dpms.getCallerIdentity(null, admin2.getPackageName())));
diff --git a/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecMessageValidatorTest.java b/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecMessageValidatorTest.java
new file mode 100644
index 000000000000..5a05fc6eda4c
--- /dev/null
+++ b/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecMessageValidatorTest.java
@@ -0,0 +1,94 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.hdmi;
+
+import static com.android.server.hdmi.HdmiCecMessageValidator.ERROR_DESTINATION;
+import static com.android.server.hdmi.HdmiCecMessageValidator.ERROR_PARAMETER_SHORT;
+import static com.android.server.hdmi.HdmiCecMessageValidator.ERROR_SOURCE;
+import static com.android.server.hdmi.HdmiCecMessageValidator.OK;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import android.os.test.TestLooper;
+import android.platform.test.annotations.Presubmit;
+
+import androidx.test.InstrumentationRegistry;
+import androidx.test.filters.SmallTest;
+
+import com.google.common.truth.IntegerSubject;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+
+/** Tests for {@link com.android.server.hdmi.HdmiCecMessageValidator} class. */
+@SmallTest
+@Presubmit
+@RunWith(JUnit4.class)
+public class HdmiCecMessageValidatorTest {
+
+ private HdmiCecMessageValidator mHdmiCecMessageValidator;
+ private TestLooper mTestLooper = new TestLooper();
+
+ @Before
+ public void setUp() throws Exception {
+ HdmiControlService mHdmiControlService = new HdmiControlService(
+ InstrumentationRegistry.getTargetContext());
+
+ mHdmiControlService.setIoLooper(mTestLooper.getLooper());
+ mHdmiCecMessageValidator = new HdmiCecMessageValidator(mHdmiControlService);
+ }
+
+ @Test
+ public void isValid_giveDevicePowerStatus() {
+ assertMessageValidity("04:8F").isEqualTo(OK);
+
+ assertMessageValidity("0F:8F").isEqualTo(ERROR_DESTINATION);
+ assertMessageValidity("F4:8F").isEqualTo(ERROR_SOURCE);
+ }
+
+ @Test
+ public void isValid_reportPowerStatus() {
+ assertMessageValidity("04:90:00").isEqualTo(OK);
+
+ assertMessageValidity("0F:90:00").isEqualTo(ERROR_DESTINATION);
+ assertMessageValidity("F0:90").isEqualTo(ERROR_SOURCE);
+ assertMessageValidity("04:90").isEqualTo(ERROR_PARAMETER_SHORT);
+ }
+
+ private IntegerSubject assertMessageValidity(String message) {
+ return assertThat(mHdmiCecMessageValidator.isValid(buildMessage(message)));
+ }
+
+ /**
+ * Build a CEC message from a hex byte string with bytes separated by {@code :}.
+ *
+ * <p>This format is used by both cec-client and www.cec-o-matic.com
+ */
+ private static HdmiCecMessage buildMessage(String message) {
+ String[] parts = message.split(":");
+ int src = Integer.parseInt(parts[0].substring(0, 1), 16);
+ int dest = Integer.parseInt(parts[0].substring(1, 2), 16);
+ int opcode = Integer.parseInt(parts[1], 16);
+ byte[] params = new byte[parts.length - 2];
+ for (int i = 0; i < params.length; i++) {
+ params[i] = (byte) Integer.parseInt(parts[i + 2], 16);
+ }
+ return new HdmiCecMessage(src, dest, opcode, params);
+ }
+}
diff --git a/services/tests/servicestests/src/com/android/server/om/OverlayManagerServiceImplRebootTests.java b/services/tests/servicestests/src/com/android/server/om/OverlayManagerServiceImplRebootTests.java
index e281f2b206f5..391611b72dab 100644
--- a/services/tests/servicestests/src/com/android/server/om/OverlayManagerServiceImplRebootTests.java
+++ b/services/tests/servicestests/src/com/android/server/om/OverlayManagerServiceImplRebootTests.java
@@ -35,8 +35,8 @@ import java.util.function.BiConsumer;
@RunWith(AndroidJUnit4.class)
public class OverlayManagerServiceImplRebootTests extends OverlayManagerServiceImplTestsBase {
- private static final String OVERLAY = "com.dummy.overlay";
- private static final String TARGET = "com.dummy.target";
+ private static final String OVERLAY = "com.test.overlay";
+ private static final String TARGET = "com.test.target";
private static final int USER = 0;
private static final String OVERLAY2 = OVERLAY + "2";
diff --git a/services/tests/servicestests/src/com/android/server/om/OverlayManagerServiceImplTests.java b/services/tests/servicestests/src/com/android/server/om/OverlayManagerServiceImplTests.java
index c1d862ab2ad4..4f882ce13dd4 100644
--- a/services/tests/servicestests/src/com/android/server/om/OverlayManagerServiceImplTests.java
+++ b/services/tests/servicestests/src/com/android/server/om/OverlayManagerServiceImplTests.java
@@ -39,8 +39,8 @@ import java.util.Map;
@RunWith(AndroidJUnit4.class)
public class OverlayManagerServiceImplTests extends OverlayManagerServiceImplTestsBase {
- private static final String OVERLAY = "com.dummy.overlay";
- private static final String TARGET = "com.dummy.target";
+ private static final String OVERLAY = "com.test.overlay";
+ private static final String TARGET = "com.test.target";
private static final int USER = 0;
private static final String OVERLAY2 = OVERLAY + "2";
@@ -50,7 +50,7 @@ public class OverlayManagerServiceImplTests extends OverlayManagerServiceImplTes
private static final String OVERLAY3 = OVERLAY + "3";
private static final int USER3 = USER2 + 1;
- private static final String CONFIG_SIGNATURE_REFERENCE_PKG = "com.dummy.ref";
+ private static final String CONFIG_SIGNATURE_REFERENCE_PKG = "com.test.ref";
private static final String CERT_CONFIG_OK = "config_certificate_ok";
private static final String CERT_CONFIG_NOK = "config_certificate_nok";
@@ -149,7 +149,7 @@ public class OverlayManagerServiceImplTests extends OverlayManagerServiceImplTes
installNewPackage(overlay(OVERLAY, TARGET), USER);
assertState(STATE_MISSING_TARGET, OVERLAY, USER);
- final DummyDeviceState.PackageBuilder target = target(TARGET);
+ final FakeDeviceState.PackageBuilder target = target(TARGET);
installNewPackage(target, USER);
assertState(STATE_DISABLED, OVERLAY, USER);
@@ -169,9 +169,9 @@ public class OverlayManagerServiceImplTests extends OverlayManagerServiceImplTes
@Test
public void testOnOverlayPackageUpgraded() {
- final DummyListener listener = getListener();
- final DummyDeviceState.PackageBuilder target = target(TARGET);
- final DummyDeviceState.PackageBuilder overlay = overlay(OVERLAY, TARGET);
+ final FakeListener listener = getListener();
+ final FakeDeviceState.PackageBuilder target = target(TARGET);
+ final FakeDeviceState.PackageBuilder overlay = overlay(OVERLAY, TARGET);
installNewPackage(target, USER);
installNewPackage(overlay, USER);
listener.count = 0;
@@ -181,7 +181,7 @@ public class OverlayManagerServiceImplTests extends OverlayManagerServiceImplTes
// upgrade to a version where the overlay has changed its target
// expect once for the old target package, once for the new target package
listener.count = 0;
- final DummyDeviceState.PackageBuilder overlay2 = overlay(OVERLAY, "some.other.target");
+ final FakeDeviceState.PackageBuilder overlay2 = overlay(OVERLAY, "some.other.target");
upgradePackage(overlay2, USER);
assertEquals(3, listener.count);
@@ -193,7 +193,7 @@ public class OverlayManagerServiceImplTests extends OverlayManagerServiceImplTes
@Test
public void testListener() {
final OverlayManagerServiceImpl impl = getImpl();
- final DummyListener listener = getListener();
+ final FakeListener listener = getListener();
installNewPackage(overlay(OVERLAY, TARGET), USER);
assertEquals(1, listener.count);
listener.count = 0;
@@ -219,12 +219,12 @@ public class OverlayManagerServiceImplTests extends OverlayManagerServiceImplTes
installNewPackage(target(TARGET), USER);
installNewPackage(overlay(OVERLAY, TARGET).setCertificate(CERT_CONFIG_OK), USER);
- final DummyIdmapDaemon idmapd = getIdmapd();
- final DummyDeviceState state = getState();
+ final FakeIdmapDaemon idmapd = getIdmapd();
+ final FakeDeviceState state = getState();
String overlayPath = state.select(OVERLAY, USER).apkPath;
assertTrue(idmapd.idmapExists(overlayPath, USER));
- DummyIdmapDaemon.IdmapHeader idmap = idmapd.getIdmap(overlayPath);
+ FakeIdmapDaemon.IdmapHeader idmap = idmapd.getIdmap(overlayPath);
assertTrue((CONFIG_SIGNATURE & idmap.policies) == CONFIG_SIGNATURE);
}
@@ -237,12 +237,12 @@ public class OverlayManagerServiceImplTests extends OverlayManagerServiceImplTes
installNewPackage(target(TARGET), USER);
installNewPackage(overlay(OVERLAY, TARGET).setCertificate(CERT_CONFIG_NOK), USER);
- final DummyIdmapDaemon idmapd = getIdmapd();
- final DummyDeviceState state = getState();
+ final FakeIdmapDaemon idmapd = getIdmapd();
+ final FakeDeviceState state = getState();
String overlayPath = state.select(OVERLAY, USER).apkPath;
assertTrue(idmapd.idmapExists(overlayPath, USER));
- DummyIdmapDaemon.IdmapHeader idmap = idmapd.getIdmap(overlayPath);
+ FakeIdmapDaemon.IdmapHeader idmap = idmapd.getIdmap(overlayPath);
assertTrue((CONFIG_SIGNATURE & idmap.policies) == 0);
}
@@ -252,12 +252,12 @@ public class OverlayManagerServiceImplTests extends OverlayManagerServiceImplTes
installNewPackage(target(TARGET), USER);
installNewPackage(overlay(OVERLAY, TARGET).setCertificate(CERT_CONFIG_NOK), USER);
- final DummyIdmapDaemon idmapd = getIdmapd();
- final DummyDeviceState state = getState();
+ final FakeIdmapDaemon idmapd = getIdmapd();
+ final FakeDeviceState state = getState();
String overlayPath = state.select(OVERLAY, USER).apkPath;
assertTrue(idmapd.idmapExists(overlayPath, USER));
- DummyIdmapDaemon.IdmapHeader idmap = idmapd.getIdmap(overlayPath);
+ FakeIdmapDaemon.IdmapHeader idmap = idmapd.getIdmap(overlayPath);
assertTrue((CONFIG_SIGNATURE & idmap.policies) == 0);
}
@@ -266,12 +266,12 @@ public class OverlayManagerServiceImplTests extends OverlayManagerServiceImplTes
installNewPackage(target(TARGET), USER);
installNewPackage(overlay(OVERLAY, TARGET).setCertificate(CERT_CONFIG_NOK), USER);
- final DummyIdmapDaemon idmapd = getIdmapd();
- final DummyDeviceState state = getState();
+ final FakeIdmapDaemon idmapd = getIdmapd();
+ final FakeDeviceState state = getState();
String overlayPath = state.select(OVERLAY, USER).apkPath;
assertTrue(idmapd.idmapExists(overlayPath, USER));
- DummyIdmapDaemon.IdmapHeader idmap = idmapd.getIdmap(overlayPath);
+ FakeIdmapDaemon.IdmapHeader idmap = idmapd.getIdmap(overlayPath);
assertTrue((CONFIG_SIGNATURE & idmap.policies) == 0);
}
@@ -284,12 +284,12 @@ public class OverlayManagerServiceImplTests extends OverlayManagerServiceImplTes
installNewPackage(target(TARGET), USER);
installNewPackage(overlay(OVERLAY, TARGET).setCertificate(CERT_CONFIG_NOK), USER);
- final DummyIdmapDaemon idmapd = getIdmapd();
- final DummyDeviceState state = getState();
+ final FakeIdmapDaemon idmapd = getIdmapd();
+ final FakeDeviceState state = getState();
String overlayPath = state.select(OVERLAY, USER).apkPath;
assertTrue(idmapd.idmapExists(overlayPath, USER));
- DummyIdmapDaemon.IdmapHeader idmap = idmapd.getIdmap(overlayPath);
+ FakeIdmapDaemon.IdmapHeader idmap = idmapd.getIdmap(overlayPath);
assertTrue((CONFIG_SIGNATURE & idmap.policies) == 0);
}
}
diff --git a/services/tests/servicestests/src/com/android/server/om/OverlayManagerServiceImplTestsBase.java b/services/tests/servicestests/src/com/android/server/om/OverlayManagerServiceImplTestsBase.java
index 2faf29f45375..006dda0f80e3 100644
--- a/services/tests/servicestests/src/com/android/server/om/OverlayManagerServiceImplTestsBase.java
+++ b/services/tests/servicestests/src/com/android/server/om/OverlayManagerServiceImplTestsBase.java
@@ -48,19 +48,19 @@ import java.util.stream.Collectors;
/** Base class for creating {@link OverlayManagerServiceImplTests} tests. */
class OverlayManagerServiceImplTestsBase {
private OverlayManagerServiceImpl mImpl;
- private DummyDeviceState mState;
- private DummyListener mListener;
- private DummyPackageManagerHelper mPackageManager;
- private DummyIdmapDaemon mIdmapDaemon;
+ private FakeDeviceState mState;
+ private FakeListener mListener;
+ private FakePackageManagerHelper mPackageManager;
+ private FakeIdmapDaemon mIdmapDaemon;
private OverlayConfig mOverlayConfig;
private String mConfigSignaturePackageName;
@Before
public void setUp() {
- mState = new DummyDeviceState();
- mListener = new DummyListener();
- mPackageManager = new DummyPackageManagerHelper(mState);
- mIdmapDaemon = new DummyIdmapDaemon(mState);
+ mState = new FakeDeviceState();
+ mListener = new FakeListener();
+ mPackageManager = new FakePackageManagerHelper(mState);
+ mIdmapDaemon = new FakeIdmapDaemon(mState);
mOverlayConfig = mock(OverlayConfig.class);
when(mOverlayConfig.getPriority(any())).thenReturn(OverlayConfig.DEFAULT_PRIORITY);
when(mOverlayConfig.isEnabled(any())).thenReturn(false);
@@ -81,15 +81,15 @@ class OverlayManagerServiceImplTestsBase {
return mImpl;
}
- DummyListener getListener() {
+ FakeListener getListener() {
return mListener;
}
- DummyIdmapDaemon getIdmapd() {
+ FakeIdmapDaemon getIdmapd() {
return mIdmapDaemon;
}
- DummyDeviceState getState() {
+ FakeDeviceState getState() {
return mState;
}
@@ -116,27 +116,27 @@ class OverlayManagerServiceImplTestsBase {
assertEquals(expected, actual);
}
- DummyDeviceState.PackageBuilder app(String packageName) {
- return new DummyDeviceState.PackageBuilder(packageName, null /* targetPackageName */,
+ FakeDeviceState.PackageBuilder app(String packageName) {
+ return new FakeDeviceState.PackageBuilder(packageName, null /* targetPackageName */,
null /* targetOverlayableName */, "data");
}
- DummyDeviceState.PackageBuilder target(String packageName) {
- return new DummyDeviceState.PackageBuilder(packageName, null /* targetPackageName */,
+ FakeDeviceState.PackageBuilder target(String packageName) {
+ return new FakeDeviceState.PackageBuilder(packageName, null /* targetPackageName */,
null /* targetOverlayableName */, "");
}
- DummyDeviceState.PackageBuilder overlay(String packageName, String targetPackageName) {
+ FakeDeviceState.PackageBuilder overlay(String packageName, String targetPackageName) {
return overlay(packageName, targetPackageName, null /* targetOverlayableName */);
}
- DummyDeviceState.PackageBuilder overlay(String packageName, String targetPackageName,
+ FakeDeviceState.PackageBuilder overlay(String packageName, String targetPackageName,
String targetOverlayableName) {
- return new DummyDeviceState.PackageBuilder(packageName, targetPackageName,
+ return new FakeDeviceState.PackageBuilder(packageName, targetPackageName,
targetOverlayableName, "");
}
- void addPackage(DummyDeviceState.PackageBuilder pkg, int userId) {
+ void addPackage(FakeDeviceState.PackageBuilder pkg, int userId) {
mState.add(pkg, userId);
}
@@ -155,7 +155,7 @@ class OverlayManagerServiceImplTestsBase {
*
* @throws IllegalStateException if the package is currently installed
*/
- void installNewPackage(DummyDeviceState.PackageBuilder pkg, int userId) {
+ void installNewPackage(FakeDeviceState.PackageBuilder pkg, int userId) {
if (mState.select(pkg.packageName, userId) != null) {
throw new IllegalStateException("package " + pkg.packageName + " already installed");
}
@@ -178,8 +178,8 @@ class OverlayManagerServiceImplTestsBase {
*
* @throws IllegalStateException if the package is not currently installed
*/
- void upgradePackage(DummyDeviceState.PackageBuilder pkg, int userId) {
- final DummyDeviceState.Package replacedPackage = mState.select(pkg.packageName, userId);
+ void upgradePackage(FakeDeviceState.PackageBuilder pkg, int userId) {
+ final FakeDeviceState.Package replacedPackage = mState.select(pkg.packageName, userId);
if (replacedPackage == null) {
throw new IllegalStateException("package " + pkg.packageName + " not installed");
}
@@ -204,7 +204,7 @@ class OverlayManagerServiceImplTestsBase {
* @throws IllegalStateException if the package is not currently installed
*/
void uninstallPackage(String packageName, int userId) {
- final DummyDeviceState.Package pkg = mState.select(packageName, userId);
+ final FakeDeviceState.Package pkg = mState.select(packageName, userId);
if (pkg == null) {
throw new IllegalStateException("package " + packageName+ " not installed");
}
@@ -217,7 +217,7 @@ class OverlayManagerServiceImplTestsBase {
}
/** Represents the state of packages installed on a fake device. */
- static class DummyDeviceState {
+ static class FakeDeviceState {
private ArrayMap<String, Package> mPackages = new ArrayMap<>();
void add(PackageBuilder pkgBuilder, int userId) {
@@ -333,16 +333,16 @@ class OverlayManagerServiceImplTestsBase {
}
}
- final class DummyPackageManagerHelper implements PackageManagerHelper {
- private final DummyDeviceState mState;
+ final class FakePackageManagerHelper implements PackageManagerHelper {
+ private final FakeDeviceState mState;
- private DummyPackageManagerHelper(DummyDeviceState state) {
+ private FakePackageManagerHelper(FakeDeviceState state) {
mState = state;
}
@Override
public PackageInfo getPackageInfo(@NonNull String packageName, int userId) {
- final DummyDeviceState.Package pkg = mState.select(packageName, userId);
+ final FakeDeviceState.Package pkg = mState.select(packageName, userId);
if (pkg == null) {
return null;
}
@@ -353,15 +353,15 @@ class OverlayManagerServiceImplTestsBase {
pi.packageName = pkg.packageName;
pi.overlayTarget = pkg.targetPackageName;
pi.targetOverlayableName = pkg.targetOverlayableName;
- pi.overlayCategory = "dummy-category-" + pkg.targetPackageName;
+ pi.overlayCategory = "Fake-category-" + pkg.targetPackageName;
return pi;
}
@Override
public boolean signaturesMatching(@NonNull String packageName1,
@NonNull String packageName2, int userId) {
- final DummyDeviceState.Package pkg1 = mState.select(packageName1, userId);
- final DummyDeviceState.Package pkg2 = mState.select(packageName2, userId);
+ final FakeDeviceState.Package pkg1 = mState.select(packageName1, userId);
+ final FakeDeviceState.Package pkg2 = mState.select(packageName2, userId);
return pkg1 != null && pkg2 != null && pkg1.certificate.equals(pkg2.certificate);
}
@@ -382,7 +382,7 @@ class OverlayManagerServiceImplTestsBase {
@Override
public OverlayableInfo getOverlayableForTarget(@NonNull String packageName,
@NonNull String targetOverlayableName, int userId) {
- final DummyDeviceState.Package pkg = mState.select(packageName, userId);
+ final FakeDeviceState.Package pkg = mState.select(packageName, userId);
if (pkg == null || !pkg.overlayableNames.contains(targetOverlayableName)) {
return null;
}
@@ -403,7 +403,7 @@ class OverlayManagerServiceImplTestsBase {
@Override
public boolean doesTargetDefineOverlayable(String targetPackageName, int userId) {
- final DummyDeviceState.Package pkg = mState.select(targetPackageName, userId);
+ final FakeDeviceState.Package pkg = mState.select(targetPackageName, userId);
return pkg != null && pkg.overlayableNames.contains(targetPackageName);
}
@@ -413,16 +413,16 @@ class OverlayManagerServiceImplTestsBase {
}
}
- static class DummyIdmapDaemon extends IdmapDaemon {
- private final DummyDeviceState mState;
+ static class FakeIdmapDaemon extends IdmapDaemon {
+ private final FakeDeviceState mState;
private final ArrayMap<String, IdmapHeader> mIdmapFiles = new ArrayMap<>();
- DummyIdmapDaemon(DummyDeviceState state) {
+ FakeIdmapDaemon(FakeDeviceState state) {
this.mState = state;
}
private int getCrc(@NonNull final String path) {
- final DummyDeviceState.Package pkg = mState.selectFromPath(path);
+ final FakeDeviceState.Package pkg = mState.selectFromPath(path);
Assert.assertNotNull(pkg);
return pkg.versionCode;
}
@@ -486,7 +486,7 @@ class OverlayManagerServiceImplTestsBase {
}
}
- static class DummyListener implements OverlayManagerServiceImpl.OverlayChangeListener {
+ static class FakeListener implements OverlayManagerServiceImpl.OverlayChangeListener {
public int count;
public void onOverlaysChanged(@NonNull String targetPackage, int userId) {
diff --git a/services/tests/servicestests/src/com/android/server/om/OverlayManagerSettingsTests.java b/services/tests/servicestests/src/com/android/server/om/OverlayManagerSettingsTests.java
index 146f60aff724..9ef755791c80 100644
--- a/services/tests/servicestests/src/com/android/server/om/OverlayManagerSettingsTests.java
+++ b/services/tests/servicestests/src/com/android/server/om/OverlayManagerSettingsTests.java
@@ -50,55 +50,55 @@ public class OverlayManagerSettingsTests {
private OverlayManagerSettings mSettings;
private static final OverlayInfo OVERLAY_A0 = new OverlayInfo(
- "com.dummy.overlay_a",
- "com.dummy.target",
+ "com.test.overlay_a",
+ "com.test.target",
null,
"some-category",
- "/data/app/com.dummy.overlay_a-1/base.apk",
+ "/data/app/com.test.overlay_a-1/base.apk",
STATE_DISABLED,
0,
0,
true);
private static final OverlayInfo OVERLAY_B0 = new OverlayInfo(
- "com.dummy.overlay_b",
- "com.dummy.target",
+ "com.test.overlay_b",
+ "com.test.target",
null,
"some-category",
- "/data/app/com.dummy.overlay_b-1/base.apk",
+ "/data/app/com.test.overlay_b-1/base.apk",
STATE_DISABLED,
0,
0,
true);
private static final OverlayInfo OVERLAY_C0 = new OverlayInfo(
- "com.dummy.overlay_c",
- "com.dummy.target",
+ "com.test.overlay_c",
+ "com.test.target",
null,
"some-category",
- "/data/app/com.dummy.overlay_c-1/base.apk",
+ "/data/app/com.test.overlay_c-1/base.apk",
STATE_DISABLED,
0,
0,
true);
private static final OverlayInfo OVERLAY_A1 = new OverlayInfo(
- "com.dummy.overlay_a",
- "com.dummy.target",
+ "com.test.overlay_a",
+ "com.test.target",
null,
"some-category",
- "/data/app/com.dummy.overlay_a-1/base.apk",
+ "/data/app/com.test.overlay_a-1/base.apk",
STATE_DISABLED,
1,
0,
true);
private static final OverlayInfo OVERLAY_B1 = new OverlayInfo(
- "com.dummy.overlay_b",
- "com.dummy.target",
+ "com.test.overlay_b",
+ "com.test.target",
null,
"some-category",
- "/data/app/com.dummy.overlay_b-1/base.apk",
+ "/data/app/com.test.overlay_b-1/base.apk",
STATE_DISABLED,
1,
0,
@@ -230,11 +230,11 @@ public class OverlayManagerSettingsTests {
assertListsAreEqual(list, OVERLAY_A0, OVERLAY_C0, OVERLAY_B0);
OverlayInfo otherTarget = new OverlayInfo(
- "com.dummy.overlay_other",
- "com.dummy.some.other.target",
+ "com.test.overlay_other",
+ "com.test.some.other.target",
null,
"some-category",
- "/data/app/com.dummy.overlay_other-1/base.apk",
+ "/data/app/com.test.overlay_other-1/base.apk",
STATE_DISABLED,
0,
0,
@@ -350,7 +350,7 @@ public class OverlayManagerSettingsTests {
ByteArrayInputStream is = new ByteArrayInputStream(xml.getBytes("utf-8"));
mSettings.restore(is);
- assertDoesNotContain(mSettings, "com.dummy.overlay", 0);
+ assertDoesNotContain(mSettings, "com.test.overlay", 0);
}
@Test
@@ -359,27 +359,27 @@ public class OverlayManagerSettingsTests {
final String xml =
"<?xml version='1.0' encoding='utf-8' standalone='yes'?>\n"
+ "<overlays version='" + version + "'>\n"
- + "<item packageName='com.dummy.overlay'\n"
+ + "<item packageName='com.test.overlay'\n"
+ " userId='1234'\n"
- + " targetPackageName='com.dummy.target'\n"
- + " baseCodePath='/data/app/com.dummy.overlay-1/base.apk'\n"
+ + " targetPackageName='com.test.target'\n"
+ + " baseCodePath='/data/app/com.test.overlay-1/base.apk'\n"
+ " state='" + STATE_DISABLED + "'\n"
+ " isEnabled='false'\n"
- + " category='dummy-category'\n"
+ + " category='test-category'\n"
+ " isStatic='false'\n"
+ " priority='0' />\n"
+ "</overlays>\n";
ByteArrayInputStream is = new ByteArrayInputStream(xml.getBytes("utf-8"));
mSettings.restore(is);
- OverlayInfo oi = mSettings.getOverlayInfo("com.dummy.overlay", 1234);
+ OverlayInfo oi = mSettings.getOverlayInfo("com.test.overlay", 1234);
assertNotNull(oi);
- assertEquals("com.dummy.overlay", oi.packageName);
- assertEquals("com.dummy.target", oi.targetPackageName);
- assertEquals("/data/app/com.dummy.overlay-1/base.apk", oi.baseCodePath);
+ assertEquals("com.test.overlay", oi.packageName);
+ assertEquals("com.test.target", oi.targetPackageName);
+ assertEquals("/data/app/com.test.overlay-1/base.apk", oi.baseCodePath);
assertEquals(1234, oi.userId);
assertEquals(STATE_DISABLED, oi.state);
- assertFalse(mSettings.getEnabled("com.dummy.overlay", 1234));
+ assertFalse(mSettings.getEnabled("com.test.overlay", 1234));
}
@Test
diff --git a/services/tests/servicestests/src/com/android/server/pm/IncrementalStatesTest.java b/services/tests/servicestests/src/com/android/server/pm/IncrementalStatesTest.java
index 62e135b09593..86758f18a407 100644
--- a/services/tests/servicestests/src/com/android/server/pm/IncrementalStatesTest.java
+++ b/services/tests/servicestests/src/com/android/server/pm/IncrementalStatesTest.java
@@ -20,7 +20,6 @@ import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
-import android.content.pm.IDataLoaderStatusListener;
import android.content.pm.PackageManager;
import android.os.ConditionVariable;
import android.os.incremental.IStorageHealthListener;
@@ -113,96 +112,30 @@ public class IncrementalStatesTest {
}
/**
- * Test that the package is still startable when Incremental Storage is at blocked status.
+ * Test that the package becomes unstartable when health status indicate storage issues.
*/
@Test
public void testStartableTransition_IncrementalStorageBlocked() {
mIncrementalStates.onStorageHealthStatusChanged(
- IStorageHealthListener.HEALTH_STATUS_BLOCKED);
- // Test that package is still startable
- assertFalse(mUnstartableCalled.block(WAIT_TIMEOUT_MILLIS));
- assertTrue(mIncrementalStates.isStartable());
- }
-
- /**
- * Test that the package is still startable when Data Loader has unknown transportation issues.
- */
- @Test
- public void testStartableTransition_DataLoaderTransportError() {
- mIncrementalStates.onStreamStatusChanged(
- IDataLoaderStatusListener.STREAM_TRANSPORT_ERROR);
- // Test that package is still startable
- assertFalse(mUnstartableCalled.block(WAIT_TIMEOUT_MILLIS));
- assertTrue(mIncrementalStates.isStartable());
- }
-
- /**
- * Test that the package becomes unstartable when Data Loader has data integrity issues.
- */
- @Test
- public void testStartableTransition_DataLoaderIntegrityError() {
- mIncrementalStates.onStreamStatusChanged(
- IDataLoaderStatusListener.STREAM_INTEGRITY_ERROR);
- // Test that package is now unstartable
- assertTrue(mUnstartableCalled.block(WAIT_TIMEOUT_MILLIS));
- assertFalse(mIncrementalStates.isStartable());
- assertEquals(PackageManager.UNSTARTABLE_REASON_DATALOADER_TRANSPORT,
- mUnstartableReason.get());
- }
-
- /**
- * Test that the package becomes unstartable when Data Loader has data source issues.
- */
- @Test
- public void testStartableTransition_DataLoaderSourceError() {
- mIncrementalStates.onStreamStatusChanged(
- IDataLoaderStatusListener.STREAM_SOURCE_ERROR);
+ IStorageHealthListener.HEALTH_STATUS_UNHEALTHY_STORAGE);
// Test that package is now unstartable
assertTrue(mUnstartableCalled.block(WAIT_TIMEOUT_MILLIS));
assertFalse(mIncrementalStates.isStartable());
- assertEquals(PackageManager.UNSTARTABLE_REASON_DATALOADER_TRANSPORT,
+ assertEquals(PackageManager.UNSTARTABLE_REASON_INSUFFICIENT_STORAGE,
mUnstartableReason.get());
}
/**
- * Test that the package becomes unstartable when Data Loader hits limited storage while
- * Incremental storage has a pending reads.
+ * Test that the package becomes unstartable when health status indicates transport issues.
*/
@Test
- public void testStartableTransition_DataLoaderStorageErrorWhenIncrementalStoragePending()
- throws InterruptedException {
- mIncrementalStates.onStreamStatusChanged(
- IDataLoaderStatusListener.STREAM_STORAGE_ERROR);
- // Test that package is still startable
- assertFalse(mUnstartableCalled.block(WAIT_TIMEOUT_MILLIS));
- assertTrue(mIncrementalStates.isStartable());
- mIncrementalStates.onStorageHealthStatusChanged(
- IStorageHealthListener.HEALTH_STATUS_READS_PENDING);
- // Test that package is now unstartable
- assertTrue(mUnstartableCalled.block(WAIT_TIMEOUT_MILLIS));
- assertFalse(mIncrementalStates.isStartable());
- assertEquals(PackageManager.UNSTARTABLE_REASON_DATALOADER_STORAGE,
- mUnstartableReason.get());
- }
-
- /**
- * Test that the package becomes unstartable when Data Loader hits limited storage while
- * Incremental storage is at blocked status.
- */
- @Test
- public void testStartableTransition_DataLoaderStorageErrorWhenIncrementalStorageBlocked()
- throws InterruptedException {
- mIncrementalStates.onStreamStatusChanged(
- IDataLoaderStatusListener.STREAM_STORAGE_ERROR);
- // Test that package is still startable
- assertFalse(mUnstartableCalled.block(WAIT_TIMEOUT_MILLIS));
- assertTrue(mIncrementalStates.isStartable());
+ public void testStartableTransition_DataLoaderIntegrityError() {
mIncrementalStates.onStorageHealthStatusChanged(
- IStorageHealthListener.HEALTH_STATUS_BLOCKED);
+ IStorageHealthListener.HEALTH_STATUS_UNHEALTHY_TRANSPORT);
// Test that package is now unstartable
assertTrue(mUnstartableCalled.block(WAIT_TIMEOUT_MILLIS));
assertFalse(mIncrementalStates.isStartable());
- assertEquals(PackageManager.UNSTARTABLE_REASON_DATALOADER_STORAGE,
+ assertEquals(PackageManager.UNSTARTABLE_REASON_CONNECTION_ERROR,
mUnstartableReason.get());
}
@@ -227,42 +160,18 @@ public class IncrementalStatesTest {
}
/**
- * Test that the package becomes unstartable when Data Loader has data integrity issue, and it
- * becomes startable again when Data Loader is healthy again.
+ * Test that the package becomes unstartable when health status indicates transportation issue,
+ * and it becomes startable again when health status is ok again.
*/
@Test
public void testStartableTransition_DataLoaderUnhealthyBackToHealthy()
throws InterruptedException {
- mIncrementalStates.onStreamStatusChanged(IDataLoaderStatusListener.STREAM_INTEGRITY_ERROR);
- // Test that package is unstartable
- assertTrue(mUnstartableCalled.block(WAIT_TIMEOUT_MILLIS));
- assertFalse(mIncrementalStates.isStartable());
-
- mIncrementalStates.onStreamStatusChanged(IDataLoaderStatusListener.STREAM_HEALTHY);
- // Test that package is now startable
- assertTrue(mStartableCalled.block(WAIT_TIMEOUT_MILLIS));
- assertTrue(mIncrementalStates.isStartable());
- }
-
- /**
- * Test that the package becomes unstartable when both Incremental Storage and Data Loader
- * are unhealthy, and it becomes startable again when both Incremental Storage and Data Loader
- * are healthy again.
- */
- @Test
- public void testStartableTransition_DataLoaderAndIncrementalStorageUnhealthyBackToHealthy()
- throws InterruptedException {
mIncrementalStates.onStorageHealthStatusChanged(
- IStorageHealthListener.HEALTH_STATUS_UNHEALTHY);
- mIncrementalStates.onStreamStatusChanged(IDataLoaderStatusListener.STREAM_INTEGRITY_ERROR);
+ IStorageHealthListener.HEALTH_STATUS_UNHEALTHY_TRANSPORT);
// Test that package is unstartable
assertTrue(mUnstartableCalled.block(WAIT_TIMEOUT_MILLIS));
assertFalse(mIncrementalStates.isStartable());
- mIncrementalStates.onStreamStatusChanged(IDataLoaderStatusListener.STREAM_HEALTHY);
- // Test that package is still unstartable
- assertFalse(mStartableCalled.block(WAIT_TIMEOUT_MILLIS));
- assertFalse(mIncrementalStates.isStartable());
mIncrementalStates.onStorageHealthStatusChanged(IStorageHealthListener.HEALTH_STATUS_OK);
// Test that package is now startable
assertTrue(mStartableCalled.block(WAIT_TIMEOUT_MILLIS));
diff --git a/services/tests/servicestests/src/com/android/server/pm/PackageManagerServiceTest.java b/services/tests/servicestests/src/com/android/server/pm/PackageManagerServiceTest.java
index 35d6f470a504..d54a40e58af1 100644
--- a/services/tests/servicestests/src/com/android/server/pm/PackageManagerServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/pm/PackageManagerServiceTest.java
@@ -16,12 +16,21 @@
package com.android.server.pm;
+import static com.google.common.truth.Truth.assertWithMessage;
+
+import static java.lang.reflect.Modifier.isFinal;
+import static java.lang.reflect.Modifier.isPublic;
+import static java.lang.reflect.Modifier.isStatic;
+
import android.content.IIntentReceiver;
+import android.content.pm.PackageManagerInternal;
import android.os.Bundle;
import android.util.SparseArray;
import androidx.test.runner.AndroidJUnit4;
+import com.google.android.collect.Lists;
+
import org.junit.After;
import org.junit.Assert;
import org.junit.Before;
@@ -29,6 +38,12 @@ import org.junit.Test;
import org.junit.runner.RunWith;
import java.io.File;
+import java.lang.reflect.Field;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
+import java.util.regex.Pattern;
// runtest -c com.android.server.pm.PackageManagerServiceTest frameworks-services
// bit FrameworksServicesTests:com.android.server.pm.PackageManagerServiceTest
@@ -133,4 +148,51 @@ public class PackageManagerServiceTest {
}
}
}
+
+ @Test
+ public void testKnownPackageToString_shouldNotGetUnknown() {
+ final List<String> packageNames = new ArrayList<>();
+ for (int i = 0; i <= PackageManagerInternal.LAST_KNOWN_PACKAGE; i++) {
+ packageNames.add(PackageManagerInternal.knownPackageToString(i));
+ }
+ assertWithMessage(
+ "The Ids of KnownPackage should be continuous and the string representation "
+ + "should not be unknown.").that(
+ packageNames).containsNoneIn(Lists.newArrayList("Unknown"));
+ }
+
+ @Test
+ public void testKnownPackage_lastKnownPackageIsTheLast() throws Exception {
+ final List<Integer> knownPackageIds = getKnownPackageIdsList();
+ assertWithMessage(
+ "The last KnownPackage Id should be assigned to PackageManagerInternal"
+ + ".LAST_KNOWN_PACKAGE.").that(
+ knownPackageIds.get(knownPackageIds.size() - 1)).isEqualTo(
+ PackageManagerInternal.LAST_KNOWN_PACKAGE);
+ }
+
+ @Test
+ public void testKnownPackage_IdsShouldBeUniqueAndContinuous() throws Exception {
+ final List<Integer> knownPackageIds = getKnownPackageIdsList();
+ for (int i = 0, size = knownPackageIds.size(); i < size - 1; i++) {
+ assertWithMessage(
+ "The KnownPackage Ids should be unique and continuous. KnownPackageIds = "
+ + Arrays.toString(knownPackageIds.toArray())).that(
+ knownPackageIds.get(i) + 1).isEqualTo(knownPackageIds.get(i + 1));
+ }
+ }
+
+ private List<Integer> getKnownPackageIdsList() throws IllegalAccessException {
+ final ArrayList<Integer> knownPackageIds = new ArrayList<>();
+ final Field[] allFields = PackageManagerInternal.class.getDeclaredFields();
+ for (Field field : allFields) {
+ final int modifier = field.getModifiers();
+ if (isPublic(modifier) && isStatic(modifier) && isFinal(modifier)
+ && Pattern.matches("PACKAGE(_[A-Z]+)+", field.getName())) {
+ knownPackageIds.add(field.getInt(null));
+ }
+ }
+ Collections.sort(knownPackageIds);
+ return knownPackageIds;
+ }
}
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 75799562abfa..b190339b129b 100644
--- a/services/tests/servicestests/src/com/android/server/pm/UserManagerTest.java
+++ b/services/tests/servicestests/src/com/android/server/pm/UserManagerTest.java
@@ -220,7 +220,7 @@ public final class UserManagerTest {
asHandle(currentUser));
try {
assertThat(mUserManager.removeUserOrSetEphemeral(user1.id)).isEqualTo(
- UserManagerService.REMOVE_RESULT_ERROR);
+ UserManager.REMOVE_RESULT_ERROR);
} finally {
mUserManager.setUserRestriction(UserManager.DISALLOW_REMOVE_USER, /* value= */ false,
asHandle(currentUser));
@@ -234,7 +234,7 @@ public final class UserManagerTest {
@Test
public void testRemoveUserOrSetEphemeral_systemUserReturnsError() throws Exception {
assertThat(mUserManager.removeUserOrSetEphemeral(UserHandle.USER_SYSTEM)).isEqualTo(
- UserManagerService.REMOVE_RESULT_ERROR);
+ UserManager.REMOVE_RESULT_ERROR);
assertThat(hasUser(UserHandle.USER_SYSTEM)).isTrue();
}
@@ -244,7 +244,7 @@ public final class UserManagerTest {
public void testRemoveUserOrSetEphemeral_invalidUserReturnsError() throws Exception {
assertThat(hasUser(Integer.MAX_VALUE)).isFalse();
assertThat(mUserManager.removeUserOrSetEphemeral(Integer.MAX_VALUE)).isEqualTo(
- UserManagerService.REMOVE_RESULT_ERROR);
+ UserManager.REMOVE_RESULT_ERROR);
}
@MediumTest
@@ -256,7 +256,7 @@ public final class UserManagerTest {
switchUser(user1.id, null, /* ignoreHandle= */ true);
assertThat(mUserManager.removeUserOrSetEphemeral(user1.id)).isEqualTo(
- UserManagerService.REMOVE_RESULT_SET_EPHEMERAL);
+ UserManager.REMOVE_RESULT_SET_EPHEMERAL);
assertThat(hasUser(user1.id)).isTrue();
assertThat(getUser(user1.id).isEphemeral()).isTrue();
@@ -277,7 +277,7 @@ public final class UserManagerTest {
final UserInfo user1 = createUser("User 1", /* flags= */ 0);
synchronized (mUserRemoveLock) {
assertThat(mUserManager.removeUserOrSetEphemeral(user1.id)).isEqualTo(
- UserManagerService.REMOVE_RESULT_REMOVED);
+ UserManager.REMOVE_RESULT_REMOVED);
waitForUserRemovalLocked(user1.id);
}
diff --git a/services/tests/servicestests/src/com/android/server/webkit/TestSystemImpl.java b/services/tests/servicestests/src/com/android/server/webkit/TestSystemImpl.java
index 8cba69f6ddcb..3530e38ef67c 100644
--- a/services/tests/servicestests/src/com/android/server/webkit/TestSystemImpl.java
+++ b/services/tests/servicestests/src/com/android/server/webkit/TestSystemImpl.java
@@ -34,7 +34,6 @@ public class TestSystemImpl implements SystemInterface {
List<Integer> mUsers = new ArrayList<>();
// Package -> [user, package]
Map<String, Map<Integer, PackageInfo>> mPackages = new HashMap();
- private boolean mFallbackLogicEnabled;
private final int mNumRelros;
private final boolean mIsDebuggable;
private int mMultiProcessSetting;
@@ -42,10 +41,9 @@ public class TestSystemImpl implements SystemInterface {
public static final int PRIMARY_USER_ID = 0;
- public TestSystemImpl(WebViewProviderInfo[] packageConfigs, boolean fallbackLogicEnabled,
- int numRelros, boolean isDebuggable, boolean multiProcessDefault) {
+ public TestSystemImpl(WebViewProviderInfo[] packageConfigs, int numRelros, boolean isDebuggable,
+ boolean multiProcessDefault) {
mPackageConfigs = packageConfigs;
- mFallbackLogicEnabled = fallbackLogicEnabled;
mNumRelros = numRelros;
mIsDebuggable = isDebuggable;
mUsers.add(PRIMARY_USER_ID);
@@ -78,16 +76,6 @@ public class TestSystemImpl implements SystemInterface {
public void killPackageDependents(String packageName) {}
@Override
- public boolean isFallbackLogicEnabled() {
- return mFallbackLogicEnabled;
- }
-
- @Override
- public void enableFallbackLogic(boolean enable) {
- mFallbackLogicEnabled = enable;
- }
-
- @Override
public void enablePackageForAllUsers(Context context, String packageName, boolean enable) {
for(int userId : mUsers) {
enablePackageForUser(packageName, enable, userId);
diff --git a/services/tests/servicestests/src/com/android/server/webkit/WebViewUpdateServiceTest.java b/services/tests/servicestests/src/com/android/server/webkit/WebViewUpdateServiceTest.java
index bbfc5ab42d61..ebe45a6fa1e8 100644
--- a/services/tests/servicestests/src/com/android/server/webkit/WebViewUpdateServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/webkit/WebViewUpdateServiceTest.java
@@ -67,36 +67,30 @@ public class WebViewUpdateServiceTest {
}
private void setupWithPackages(WebViewProviderInfo[] packages) {
- setupWithAllParameters(packages, false /* fallbackLogicEnabled */, 1 /* numRelros */,
- true /* isDebuggable */, false /* multiProcessDefault */);
- }
-
- private void setupWithPackagesAndFallbackLogic(WebViewProviderInfo[] packages) {
- setupWithAllParameters(packages, true /* fallbackLogicEnabled */, 1 /* numRelros */,
- true /* isDebuggable */, false /* multiProcessDefault */);
+ setupWithAllParameters(packages, 1 /* numRelros */, true /* isDebuggable */,
+ false /* multiProcessDefault */);
}
private void setupWithPackagesAndRelroCount(WebViewProviderInfo[] packages, int numRelros) {
- setupWithAllParameters(packages, false /* fallbackLogicEnabled */, numRelros,
- true /* isDebuggable */, false /* multiProcessDefault */);
+ setupWithAllParameters(packages, numRelros, true /* isDebuggable */,
+ false /* multiProcessDefault */);
}
private void setupWithPackagesNonDebuggable(WebViewProviderInfo[] packages) {
- setupWithAllParameters(packages, false /* fallbackLogicEnabled */, 1 /* numRelros */,
- false /* isDebuggable */, false /* multiProcessDefault */);
+ setupWithAllParameters(packages, 1 /* numRelros */, false /* isDebuggable */,
+ false /* multiProcessDefault */);
}
private void setupWithPackagesAndMultiProcess(WebViewProviderInfo[] packages,
boolean multiProcessDefault) {
- setupWithAllParameters(packages, false /* fallbackLogicEnabled */, 1 /* numRelros */,
- true /* isDebuggable */, multiProcessDefault);
+ setupWithAllParameters(packages, 1 /* numRelros */, true /* isDebuggable */,
+ multiProcessDefault);
}
- private void setupWithAllParameters(WebViewProviderInfo[] packages,
- boolean fallbackLogicEnabled, int numRelros, boolean isDebuggable,
- boolean multiProcessDefault) {
- TestSystemImpl testing = new TestSystemImpl(packages, fallbackLogicEnabled, numRelros,
- isDebuggable, multiProcessDefault);
+ private void setupWithAllParameters(WebViewProviderInfo[] packages, int numRelros,
+ boolean isDebuggable, boolean multiProcessDefault) {
+ TestSystemImpl testing = new TestSystemImpl(packages, numRelros, isDebuggable,
+ multiProcessDefault);
mTestSystemImpl = Mockito.spy(testing);
mWebViewUpdateServiceImpl =
new WebViewUpdateServiceImpl(null /*Context*/, mTestSystemImpl);
@@ -514,49 +508,29 @@ public class WebViewUpdateServiceTest {
}
/**
- * Scenario for testing migrating away from the fallback logic.
- * We start with a primary package that's a disabled fallback, and an enabled secondary,
- * so that the fallback being re-enabled will cause a provider switch, as that covers
- * the most complex case.
+ * Scenario for testing re-enabling a fallback package.
*/
@Test
- public void testFallbackLogicMigration() {
- String primaryPackage = "primary";
- String secondaryPackage = "secondary";
+ public void testFallbackPackageEnabling() {
+ String testPackage = "testFallback";
WebViewProviderInfo[] packages = new WebViewProviderInfo[] {
new WebViewProviderInfo(
- primaryPackage, "", true /* default available */, true /* fallback */, null),
- new WebViewProviderInfo(
- secondaryPackage, "", true /* default available */, false /* fallback */,
- null)};
- setupWithPackagesAndFallbackLogic(packages);
- mTestSystemImpl.setPackageInfo(
- createPackageInfo(primaryPackage, false /* enabled */ , true /* valid */,
- true /* installed */));
+ testPackage, "", true /* default available */, true /* fallback */, null)};
+ setupWithPackages(packages);
mTestSystemImpl.setPackageInfo(
- createPackageInfo(secondaryPackage, true /* enabled */ , true /* valid */,
+ createPackageInfo(testPackage, false /* enabled */ , true /* valid */,
true /* installed */));
- // Check that the boot time logic re-enables and chooses the primary, and disables the
- // fallback logic.
+ // Check that the boot time logic re-enables the fallback package.
runWebViewBootPreparationOnMainSync();
Mockito.verify(mTestSystemImpl).enablePackageForAllUsers(
- Matchers.anyObject(), Mockito.eq(primaryPackage), Mockito.eq(true));
- checkPreparationPhasesForPackage(primaryPackage, 1);
- assertFalse(mTestSystemImpl.isFallbackLogicEnabled());
+ Matchers.anyObject(), Mockito.eq(testPackage), Mockito.eq(true));
- // Disable primary again
- mTestSystemImpl.setPackageInfo(createPackageInfo(primaryPackage, false /* enabled */,
- true /* valid */, true /* installed */));
- mWebViewUpdateServiceImpl.packageStateChanged(primaryPackage,
- WebViewUpdateService.PACKAGE_CHANGED, TestSystemImpl.PRIMARY_USER_ID);
- checkPreparationPhasesForPackage(secondaryPackage, 1);
-
- // Run boot logic again and check that we didn't re-enable the primary a second time.
- runWebViewBootPreparationOnMainSync();
- Mockito.verify(mTestSystemImpl, Mockito.times(1)).enablePackageForAllUsers(
- Matchers.anyObject(), Mockito.eq(primaryPackage), Mockito.eq(true));
- checkPreparationPhasesForPackage(secondaryPackage, 2);
+ // Fake the message about the enabling having changed the package state,
+ // and check we now use that package.
+ mWebViewUpdateServiceImpl.packageStateChanged(
+ testPackage, WebViewUpdateService.PACKAGE_CHANGED, TestSystemImpl.PRIMARY_USER_ID);
+ checkPreparationPhasesForPackage(testPackage, 1);
}
/**
diff --git a/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java b/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java
index ad9692f404e9..dd4d718084ab 100644
--- a/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java
@@ -1525,7 +1525,6 @@ public class ActivityRecordTests extends WindowTestsBase {
any() /* window */, any() /* attrs */,
anyInt() /* viewVisibility */, anyInt() /* displayId */,
any() /* requestedVisibility */, any() /* outFrame */,
- any() /* outContentInsets */, any() /* outStableInsets */,
any() /* outDisplayCutout */, any() /* outInputChannel */,
any() /* outInsetsState */, any() /* outActiveControls */);
TaskSnapshotSurface.create(mAtm.mWindowManager, mActivity, snapshot);
diff --git a/services/tests/wmtests/src/com/android/server/wm/ActivityStackTests.java b/services/tests/wmtests/src/com/android/server/wm/ActivityStackTests.java
index caf8a720e26c..3dc258c51954 100644
--- a/services/tests/wmtests/src/com/android/server/wm/ActivityStackTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/ActivityStackTests.java
@@ -70,6 +70,8 @@ import android.content.pm.ActivityInfo;
import android.os.Binder;
import android.os.UserHandle;
import android.platform.test.annotations.Presubmit;
+import android.view.SurfaceControl;
+import android.window.ITaskOrganizer;
import androidx.test.filters.SmallTest;
@@ -240,6 +242,24 @@ public class ActivityStackTests extends WindowTestsBase {
@Test
public void testRemoveOrganizedTask_UpdateStackReference() {
+ ITaskOrganizer listener = new ITaskOrganizer.Stub() {
+ @Override
+ public void onTaskAppeared(
+ ActivityManager.RunningTaskInfo taskInfo, SurfaceControl leash) { }
+
+ @Override
+ public void onTaskVanished(ActivityManager.RunningTaskInfo container) { }
+
+ @Override
+ public void onTaskInfoChanged(ActivityManager.RunningTaskInfo info) {
+ }
+
+ @Override
+ public void onBackPressedOnTaskRoot(ActivityManager.RunningTaskInfo taskInfo) {
+ }
+ };
+ mWm.mAtmService.mTaskOrganizerController.registerTaskOrganizer(listener);
+
final Task rootHomeTask = mDefaultTaskDisplayArea.getRootHomeTask();
final ActivityRecord homeActivity = new ActivityBuilder(mAtm)
.setStack(rootHomeTask)
@@ -247,7 +267,7 @@ public class ActivityStackTests extends WindowTestsBase {
.build();
final Task secondaryStack = (Task) WindowContainer.fromBinder(
mAtm.mTaskOrganizerController.createRootTask(rootHomeTask.getDisplayId(),
- WINDOWING_MODE_SPLIT_SCREEN_SECONDARY).token.asBinder());
+ WINDOWING_MODE_SPLIT_SCREEN_SECONDARY).getTaskInfo().token.asBinder());
rootHomeTask.reparent(secondaryStack, POSITION_TOP);
assertEquals(secondaryStack, rootHomeTask.getParent());
diff --git a/services/tests/wmtests/src/com/android/server/wm/ActivityTaskManagerServiceTests.java b/services/tests/wmtests/src/com/android/server/wm/ActivityTaskManagerServiceTests.java
index 3349c6dda87f..8292420c9e0a 100644
--- a/services/tests/wmtests/src/com/android/server/wm/ActivityTaskManagerServiceTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/ActivityTaskManagerServiceTests.java
@@ -23,20 +23,24 @@ import static com.android.dx.mockito.inline.extended.ExtendedMockito.mockitoSess
import static com.android.dx.mockito.inline.extended.ExtendedMockito.verify;
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.mockito.ArgumentMatchers.anyBoolean;
import static org.mockito.ArgumentMatchers.anyString;
+import static org.mockito.Mockito.doCallRealMethod;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.when;
import android.app.Activity;
+import android.app.ActivityManager;
import android.app.PictureInPictureParams;
import android.app.servertransaction.ClientTransaction;
import android.app.servertransaction.EnterPipRequestedItem;
import android.content.res.Configuration;
import android.graphics.Rect;
import android.os.IBinder;
+import android.os.PowerManager;
import android.os.RemoteException;
import android.platform.test.annotations.Presubmit;
import android.view.IDisplayWindowListener;
@@ -252,5 +256,36 @@ public class ActivityTaskManagerServiceTests extends WindowTestsBase {
assertEquals(Task.ActivityState.RESUMED, homeActivity.getState());
assertEquals(homeActivity.app, mAtm.mInternal.getTopApp());
}
+
+ @Test
+ public void testUpdateSleep() {
+ doCallRealMethod().when(mWm.mRoot).hasAwakeDisplay();
+ mSupervisor.mGoingToSleepWakeLock = mock(PowerManager.WakeLock.class);
+ final ActivityRecord topActivity = new ActivityBuilder(mAtm).setCreateTask(true).build();
+ topActivity.setState(Task.ActivityState.RESUMED, "test");
+
+ final Runnable assertTopNonSleeping = () -> {
+ assertFalse(mAtm.mInternal.isSleeping());
+ assertEquals(ActivityManager.PROCESS_STATE_TOP, mAtm.mInternal.getTopProcessState());
+ assertEquals(topActivity.app, mAtm.mInternal.getTopApp());
+ };
+ assertTopNonSleeping.run();
+
+ // Sleep all displays.
+ mWm.mRoot.forAllDisplays(display -> doReturn(true).when(display).shouldSleep());
+ mAtm.updateSleepIfNeededLocked();
+
+ assertEquals(Task.ActivityState.PAUSING, topActivity.getState());
+ assertTrue(mAtm.mInternal.isSleeping());
+ assertEquals(ActivityManager.PROCESS_STATE_TOP_SLEEPING,
+ mAtm.mInternal.getTopProcessState());
+ assertNull(mAtm.mInternal.getTopApp());
+
+ // Wake all displays.
+ mWm.mRoot.forAllDisplays(display -> doReturn(false).when(display).shouldSleep());
+ mAtm.updateSleepIfNeededLocked();
+
+ assertTopNonSleeping.run();
+ }
}
diff --git a/services/tests/wmtests/src/com/android/server/wm/DisplayPolicyLayoutTests.java b/services/tests/wmtests/src/com/android/server/wm/DisplayPolicyLayoutTests.java
index 5a14a249e78f..3598cd8d841d 100644
--- a/services/tests/wmtests/src/com/android/server/wm/DisplayPolicyLayoutTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/DisplayPolicyLayoutTests.java
@@ -157,6 +157,8 @@ public class DisplayPolicyLayoutTests extends DisplayPolicyTestsBase {
mDisplayBounds.set(0, 0, mFrames.mDisplayWidth, mFrames.mDisplayHeight);
mDisplayContent.mDisplayFrames = mFrames;
mDisplayContent.setBounds(mDisplayBounds);
+ mDisplayContent.getInsetsStateController().getRawInsetsState().setDisplayFrame(
+ mDisplayBounds);
}
private DisplayFrames createDisplayFrames() {
@@ -339,7 +341,7 @@ public class DisplayPolicyLayoutTests extends DisplayPolicyTestsBase {
@Test
public void layoutWindowLw_fitInsetsIgnoringVisibility() {
final InsetsState state =
- mDisplayContent.getInsetsPolicy().getInsetsForDispatch(mWindow);
+ mDisplayContent.getInsetsPolicy().getInsetsForWindow(mWindow);
state.getSource(InsetsState.ITYPE_STATUS_BAR).setVisible(false);
state.getSource(InsetsState.ITYPE_NAVIGATION_BAR).setVisible(false);
mWindow.mAttrs.setFitInsetsIgnoringVisibility(true);
@@ -359,7 +361,7 @@ public class DisplayPolicyLayoutTests extends DisplayPolicyTestsBase {
@Test
public void layoutWindowLw_fitInsetsNotIgnoringVisibility() {
final InsetsState state =
- mDisplayContent.getInsetsPolicy().getInsetsForDispatch(mWindow);
+ mDisplayContent.getInsetsPolicy().getInsetsForWindow(mWindow);
state.getSource(InsetsState.ITYPE_STATUS_BAR).setVisible(false);
state.getSource(InsetsState.ITYPE_NAVIGATION_BAR).setVisible(false);
mWindow.mAttrs.setFitInsetsIgnoringVisibility(false);
@@ -520,7 +522,7 @@ public class DisplayPolicyLayoutTests extends DisplayPolicyTestsBase {
mWindow.mAttrs.flags =
FLAG_LAYOUT_IN_SCREEN | FLAG_LAYOUT_INSET_DECOR | FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS;
mWindow.mAttrs.setFitInsetsTypes(0 /* types */);
- mDisplayContent.getInsetsPolicy().getInsetsForDispatch(mWindow)
+ mDisplayContent.getInsetsPolicy().getInsetsForWindow(mWindow)
.getSource(InsetsState.ITYPE_STATUS_BAR).setVisible(false);
final InsetsState requestedState = new InsetsState();
requestedState.getSource(ITYPE_STATUS_BAR).setVisible(false);
@@ -544,7 +546,7 @@ public class DisplayPolicyLayoutTests extends DisplayPolicyTestsBase {
mWindow.mAttrs.flags =
FLAG_LAYOUT_IN_SCREEN | FLAG_LAYOUT_INSET_DECOR | FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS;
mWindow.mAttrs.setFitInsetsTypes(0 /* types */);
- mDisplayContent.getInsetsPolicy().getInsetsForDispatch(mWindow)
+ mDisplayContent.getInsetsPolicy().getInsetsForWindow(mWindow)
.getSource(InsetsState.ITYPE_STATUS_BAR).setVisible(false);
final InsetsState requestedState = new InsetsState();
requestedState.getSource(ITYPE_STATUS_BAR).setVisible(false);
@@ -774,31 +776,30 @@ public class DisplayPolicyLayoutTests extends DisplayPolicyTestsBase {
@Test
public void layoutHint_appWindow() {
- mWindow.mAttrs.flags =
- FLAG_LAYOUT_IN_SCREEN | FLAG_LAYOUT_INSET_DECOR | FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS;
+ mWindow.mAttrs.setFitInsetsTypes(0);
// Initialize DisplayFrames
mDisplayPolicy.beginLayoutLw(mFrames, 0 /* UI mode */);
final Rect outFrame = new Rect();
- final Rect outContentInsets = new Rect();
- final Rect outStableInsets = new Rect();
final DisplayCutout.ParcelableWrapper outDisplayCutout =
new DisplayCutout.ParcelableWrapper();
+ final InsetsState outState = new InsetsState();
mDisplayPolicy.getLayoutHint(mWindow.mAttrs, null /* windowToken */, outFrame,
- outContentInsets, outStableInsets, outDisplayCutout);
+ outDisplayCutout, outState, true /* localClient */);
- assertThat(outFrame, is(mFrames.mUnrestricted));
- assertThat(outContentInsets, is(new Rect(0, STATUS_BAR_HEIGHT, 0, NAV_BAR_HEIGHT)));
- assertThat(outStableInsets, is(new Rect(0, STATUS_BAR_HEIGHT, 0, NAV_BAR_HEIGHT)));
+ assertThat(outFrame, is(outState.getDisplayFrame()));
assertThat(outDisplayCutout, is(new DisplayCutout.ParcelableWrapper()));
+ assertThat(outState.getSource(ITYPE_STATUS_BAR).getFrame(),
+ is(new Rect(0, 0, DISPLAY_WIDTH, STATUS_BAR_HEIGHT)));
+ assertThat(outState.getSource(ITYPE_NAVIGATION_BAR).getFrame(),
+ is(new Rect(0, DISPLAY_HEIGHT - NAV_BAR_HEIGHT, DISPLAY_WIDTH, DISPLAY_HEIGHT)));
}
@Test
public void layoutHint_appWindowInTask() {
- mWindow.mAttrs.flags =
- FLAG_LAYOUT_IN_SCREEN | FLAG_LAYOUT_INSET_DECOR | FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS;
+ mWindow.mAttrs.setFitInsetsTypes(0);
// Initialize DisplayFrames
mDisplayPolicy.beginLayoutLw(mFrames, 0 /* UI mode */);
@@ -809,24 +810,24 @@ public class DisplayPolicyLayoutTests extends DisplayPolicyTestsBase {
task.getWindowConfiguration().setBounds(taskBounds);
final Rect outFrame = new Rect();
- final Rect outContentInsets = new Rect();
- final Rect outStableInsets = new Rect();
final DisplayCutout.ParcelableWrapper outDisplayCutout =
new DisplayCutout.ParcelableWrapper();
+ final InsetsState outState = new InsetsState();
- mDisplayPolicy.getLayoutHint(mWindow.mAttrs, mWindow.mToken, outFrame,
- outContentInsets, outStableInsets, outDisplayCutout);
+ mDisplayPolicy.getLayoutHint(mWindow.mAttrs, mWindow.mToken, outFrame, outDisplayCutout,
+ outState, true /* localClient */);
assertThat(outFrame, is(taskBounds));
- assertThat(outContentInsets, is(new Rect()));
- assertThat(outStableInsets, is(new Rect()));
assertThat(outDisplayCutout, is(new DisplayCutout.ParcelableWrapper()));
+ assertThat(outState.getSource(ITYPE_STATUS_BAR).getFrame(),
+ is(new Rect(0, 0, DISPLAY_WIDTH, STATUS_BAR_HEIGHT)));
+ assertThat(outState.getSource(ITYPE_NAVIGATION_BAR).getFrame(),
+ is(new Rect(0, DISPLAY_HEIGHT - NAV_BAR_HEIGHT, DISPLAY_WIDTH, DISPLAY_HEIGHT)));
}
@Test
public void layoutHint_appWindowInTask_outsideContentFrame() {
- mWindow.mAttrs.flags =
- FLAG_LAYOUT_IN_SCREEN | FLAG_LAYOUT_INSET_DECOR | FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS;
+ mWindow.mAttrs.setFitInsetsTypes(0);
// Initialize DisplayFrames
mDisplayPolicy.beginLayoutLw(mFrames, 0 /* UI mode */);
@@ -843,18 +844,19 @@ public class DisplayPolicyLayoutTests extends DisplayPolicyTestsBase {
task.getWindowConfiguration().setBounds(taskBounds);
final Rect outFrame = new Rect();
- final Rect outContentInsets = new Rect();
- final Rect outStableInsets = new Rect();
final DisplayCutout.ParcelableWrapper outDisplayCutout =
new DisplayCutout.ParcelableWrapper();
+ final InsetsState outState = new InsetsState();
- mDisplayPolicy.getLayoutHint(mWindow.mAttrs, mWindow.mToken, outFrame, outContentInsets,
- outStableInsets, outDisplayCutout);
+ mDisplayPolicy.getLayoutHint(mWindow.mAttrs, mWindow.mToken, outFrame, outDisplayCutout,
+ outState, true /* localClient */);
assertThat(outFrame, is(taskBounds));
- assertThat(outContentInsets, is(new Rect()));
- assertThat(outStableInsets, is(new Rect()));
assertThat(outDisplayCutout, is(new DisplayCutout.ParcelableWrapper()));
+ assertThat(outState.getSource(ITYPE_STATUS_BAR).getFrame(),
+ is(new Rect(0, 0, DISPLAY_WIDTH, STATUS_BAR_HEIGHT)));
+ assertThat(outState.getSource(ITYPE_NAVIGATION_BAR).getFrame(),
+ is(new Rect(0, DISPLAY_HEIGHT - NAV_BAR_HEIGHT, DISPLAY_WIDTH, DISPLAY_HEIGHT)));
}
/**
diff --git a/services/tests/wmtests/src/com/android/server/wm/InsetsPolicyTest.java b/services/tests/wmtests/src/com/android/server/wm/InsetsPolicyTest.java
index d67120f53917..a1606d3502ad 100644
--- a/services/tests/wmtests/src/com/android/server/wm/InsetsPolicyTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/InsetsPolicyTest.java
@@ -321,7 +321,7 @@ public class InsetsPolicyTest extends WindowTestsBase {
assertNull(controls[i].getLeash());
}
- final InsetsState state = policy.getInsetsForDispatch(mAppWindow);
+ final InsetsState state = policy.getInsetsForWindow(mAppWindow);
state.setSourceVisible(ITYPE_STATUS_BAR, true);
state.setSourceVisible(ITYPE_NAVIGATION_BAR, true);
diff --git a/services/tests/wmtests/src/com/android/server/wm/InsetsStateControllerTest.java b/services/tests/wmtests/src/com/android/server/wm/InsetsStateControllerTest.java
index c14df676f525..90caf35e2936 100644
--- a/services/tests/wmtests/src/com/android/server/wm/InsetsStateControllerTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/InsetsStateControllerTest.java
@@ -63,7 +63,7 @@ public class InsetsStateControllerTest extends WindowTestsBase {
final WindowState app = createWindow(null, TYPE_APPLICATION, "app");
getController().getSourceProvider(ITYPE_STATUS_BAR).setWindow(statusBar, null, null);
statusBar.setControllableInsetProvider(getController().getSourceProvider(ITYPE_STATUS_BAR));
- assertNotNull(getController().getInsetsForDispatch(app).peekSource(ITYPE_STATUS_BAR));
+ assertNotNull(getController().getInsetsForWindow(app).peekSource(ITYPE_STATUS_BAR));
}
@Test
@@ -72,7 +72,7 @@ public class InsetsStateControllerTest extends WindowTestsBase {
mDisplayContent.getInsetsStateController().getSourceProvider(ITYPE_STATUS_BAR)
.setWindow(statusBar, null, null);
statusBar.setControllableInsetProvider(getController().getSourceProvider(ITYPE_STATUS_BAR));
- final InsetsState state = getController().getInsetsForDispatch(statusBar);
+ final InsetsState state = getController().getInsetsForWindow(statusBar);
assertNull(state.peekSource(ITYPE_STATUS_BAR));
}
@@ -88,8 +88,8 @@ public class InsetsStateControllerTest extends WindowTestsBase {
getController().getSourceProvider(ITYPE_STATUS_BAR).setWindow(statusBar, null, null);
getController().getSourceProvider(ITYPE_NAVIGATION_BAR).setWindow(navBar, null, null);
getController().getSourceProvider(ITYPE_IME).setWindow(ime, null, null);
- assertNull(getController().getInsetsForDispatch(navBar).peekSource(ITYPE_IME));
- assertNull(getController().getInsetsForDispatch(navBar).peekSource(ITYPE_STATUS_BAR));
+ assertNull(getController().getInsetsForWindow(navBar).peekSource(ITYPE_IME));
+ assertNull(getController().getInsetsForWindow(navBar).peekSource(ITYPE_STATUS_BAR));
}
@Test
@@ -102,8 +102,8 @@ public class InsetsStateControllerTest extends WindowTestsBase {
getController().getSourceProvider(ITYPE_NAVIGATION_BAR).setWindow(navBar, null, null);
app.setWindowingMode(WINDOWING_MODE_PINNED);
- assertNull(getController().getInsetsForDispatch(app).peekSource(ITYPE_STATUS_BAR));
- assertNull(getController().getInsetsForDispatch(app).peekSource(ITYPE_NAVIGATION_BAR));
+ assertNull(getController().getInsetsForWindow(app).peekSource(ITYPE_STATUS_BAR));
+ assertNull(getController().getInsetsForWindow(app).peekSource(ITYPE_NAVIGATION_BAR));
}
@Test
@@ -116,8 +116,8 @@ public class InsetsStateControllerTest extends WindowTestsBase {
getController().getSourceProvider(ITYPE_NAVIGATION_BAR).setWindow(navBar, null, null);
app.setWindowingMode(WINDOWING_MODE_FREEFORM);
- assertNull(getController().getInsetsForDispatch(app).peekSource(ITYPE_STATUS_BAR));
- assertNull(getController().getInsetsForDispatch(app).peekSource(ITYPE_NAVIGATION_BAR));
+ assertNull(getController().getInsetsForWindow(app).peekSource(ITYPE_STATUS_BAR));
+ assertNull(getController().getInsetsForWindow(app).peekSource(ITYPE_NAVIGATION_BAR));
}
@Test
@@ -131,8 +131,8 @@ public class InsetsStateControllerTest extends WindowTestsBase {
app.setWindowingMode(WINDOWING_MODE_MULTI_WINDOW);
app.setAlwaysOnTop(true);
- assertNull(getController().getInsetsForDispatch(app).peekSource(ITYPE_STATUS_BAR));
- assertNull(getController().getInsetsForDispatch(app).peekSource(ITYPE_NAVIGATION_BAR));
+ assertNull(getController().getInsetsForWindow(app).peekSource(ITYPE_STATUS_BAR));
+ assertNull(getController().getInsetsForWindow(app).peekSource(ITYPE_NAVIGATION_BAR));
}
@UseTestDisplay(addWindows = W_INPUT_METHOD)
@@ -147,8 +147,8 @@ public class InsetsStateControllerTest extends WindowTestsBase {
app2.mBehindIme = false;
getController().getRawInsetsState().setSourceVisible(ITYPE_IME, true);
- assertFalse(getController().getInsetsForDispatch(app2).getSource(ITYPE_IME).isVisible());
- assertTrue(getController().getInsetsForDispatch(app1).getSource(ITYPE_IME).isVisible());
+ assertFalse(getController().getInsetsForWindow(app2).getSource(ITYPE_IME).isVisible());
+ assertTrue(getController().getInsetsForWindow(app1).getSource(ITYPE_IME).isVisible());
}
@UseTestDisplay(addWindows = W_INPUT_METHOD)
@@ -160,7 +160,7 @@ public class InsetsStateControllerTest extends WindowTestsBase {
app.mBehindIme = true;
getController().getRawInsetsState().setSourceVisible(ITYPE_IME, true);
- assertTrue(getController().getInsetsForDispatch(app).getSource(ITYPE_IME).isVisible());
+ assertTrue(getController().getInsetsForWindow(app).getSource(ITYPE_IME).isVisible());
}
@UseTestDisplay(addWindows = W_INPUT_METHOD)
@@ -172,7 +172,7 @@ public class InsetsStateControllerTest extends WindowTestsBase {
app.mBehindIme = false;
getController().getRawInsetsState().setSourceVisible(ITYPE_IME, true);
- assertFalse(getController().getInsetsForDispatch(app).getSource(ITYPE_IME).isVisible());
+ assertFalse(getController().getInsetsForWindow(app).getSource(ITYPE_IME).isVisible());
}
@UseTestDisplay(addWindows = W_INPUT_METHOD)
@@ -207,7 +207,7 @@ public class InsetsStateControllerTest extends WindowTestsBase {
// app won't get visible IME insets while above IME even when IME is visible.
assertTrue(getController().getRawInsetsState().getSourceOrDefaultVisibility(ITYPE_IME));
- assertFalse(getController().getInsetsForDispatch(app).getSource(ITYPE_IME).isVisible());
+ assertFalse(getController().getInsetsForWindow(app).getSource(ITYPE_IME).isVisible());
// Reset invocation counter.
clearInvocations(app);
@@ -221,7 +221,7 @@ public class InsetsStateControllerTest extends WindowTestsBase {
verify(app, atLeast(1)).notifyInsetsChanged();
// app will get visible IME insets while below IME.
- assertTrue(getController().getInsetsForDispatch(app).getSource(ITYPE_IME).isVisible());
+ assertTrue(getController().getInsetsForWindow(app).getSource(ITYPE_IME).isVisible());
}
@UseTestDisplay(addWindows = W_INPUT_METHOD)
@@ -238,8 +238,8 @@ public class InsetsStateControllerTest extends WindowTestsBase {
mDisplayContent.applySurfaceChangesTransaction();
getController().getRawInsetsState().setSourceVisible(ITYPE_IME, true);
- assertTrue(getController().getInsetsForDispatch(app).getSource(ITYPE_IME).isVisible());
- assertFalse(getController().getInsetsForDispatch(child).getSource(ITYPE_IME).isVisible());
+ assertTrue(getController().getInsetsForWindow(app).getSource(ITYPE_IME).isVisible());
+ assertFalse(getController().getInsetsForWindow(child).getSource(ITYPE_IME).isVisible());
}
@UseTestDisplay(addWindows = W_INPUT_METHOD)
@@ -257,8 +257,8 @@ public class InsetsStateControllerTest extends WindowTestsBase {
mDisplayContent.applySurfaceChangesTransaction();
getController().getRawInsetsState().setSourceVisible(ITYPE_IME, true);
- assertTrue(getController().getInsetsForDispatch(app).getSource(ITYPE_IME).isVisible());
- assertFalse(getController().getInsetsForDispatch(child).getSource(ITYPE_IME).isVisible());
+ assertTrue(getController().getInsetsForWindow(app).getSource(ITYPE_IME).isVisible());
+ assertFalse(getController().getInsetsForWindow(child).getSource(ITYPE_IME).isVisible());
}
@Test
@@ -278,7 +278,7 @@ public class InsetsStateControllerTest extends WindowTestsBase {
statusBarProvider.onPostLayout();
- final InsetsState state = getController().getInsetsForDispatch(ime);
+ final InsetsState state = getController().getInsetsForWindow(ime);
assertEquals(new Rect(0, 1, 2, 3), state.getSource(ITYPE_STATUS_BAR).getFrame());
}
diff --git a/services/tests/wmtests/src/com/android/server/wm/RecentTasksTest.java b/services/tests/wmtests/src/com/android/server/wm/RecentTasksTest.java
index 1bf83aced590..bea0d8e60c40 100644
--- a/services/tests/wmtests/src/com/android/server/wm/RecentTasksTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/RecentTasksTest.java
@@ -736,7 +736,7 @@ public class RecentTasksTest extends WindowTestsBase {
}
/**
- * Tests that tasks on singleTaskDisplay are not visible and not trimmed/removed.
+ * Tests that tasks on always on top multi-window tasks are not visible and not trimmed/removed.
*/
@Test
public void testVisibleTasks_alwaysOnTop() {
diff --git a/services/tests/wmtests/src/com/android/server/wm/SyncEngineTests.java b/services/tests/wmtests/src/com/android/server/wm/SyncEngineTests.java
new file mode 100644
index 000000000000..7bac3e7b8679
--- /dev/null
+++ b/services/tests/wmtests/src/com/android/server/wm/SyncEngineTests.java
@@ -0,0 +1,390 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.wm;
+
+import static com.android.dx.mockito.inline.extended.ExtendedMockito.mock;
+import static com.android.dx.mockito.inline.extended.ExtendedMockito.spyOn;
+import static com.android.dx.mockito.inline.extended.ExtendedMockito.times;
+import static com.android.dx.mockito.inline.extended.ExtendedMockito.verify;
+import static com.android.server.wm.WindowContainer.POSITION_BOTTOM;
+import static com.android.server.wm.WindowContainer.POSITION_TOP;
+import static com.android.server.wm.WindowContainer.SYNC_STATE_NONE;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyInt;
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.ArgumentMatchers.notNull;
+import static org.mockito.Mockito.spy;
+
+import android.platform.test.annotations.Presubmit;
+import android.view.SurfaceControl;
+
+import androidx.test.filters.SmallTest;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.ArgumentCaptor;
+
+/**
+ * Test class for {@link BLASTSyncEngine}.
+ *
+ * Build/Install/Run:
+ * atest WmTests:SyncEngineTests
+ */
+@SmallTest
+@Presubmit
+@RunWith(WindowTestRunner.class)
+public class SyncEngineTests extends WindowTestsBase {
+
+ @Before
+ public void setUp() {
+ spyOn(mWm.mWindowPlacerLocked);
+ }
+
+ @Test
+ public void testTrivialSyncCallback() {
+ TestWindowContainer mockWC = new TestWindowContainer(mWm, false /* waiter */);
+
+ BLASTSyncEngine bse = new BLASTSyncEngine(mWm);
+
+ BLASTSyncEngine.TransactionReadyListener listener = mock(
+ BLASTSyncEngine.TransactionReadyListener.class);
+
+ int id = bse.startSyncSet(listener);
+ bse.addToSyncSet(id, mockWC);
+ // Make sure a traversal is requested
+ verify(mWm.mWindowPlacerLocked, times(1)).requestTraversal();
+
+ bse.onSurfacePlacement();
+ verify(listener, times(0)).onTransactionReady(anyInt(), any());
+
+ bse.setReady(id);
+ // Make sure a traversal is requested
+ verify(mWm.mWindowPlacerLocked, times(2)).requestTraversal();
+ bse.onSurfacePlacement();
+ verify(listener, times(1)).onTransactionReady(eq(id), notNull());
+
+ // make sure it was cleaned-up (no second callback)
+ bse.onSurfacePlacement();
+ verify(listener, times(1)).onTransactionReady(anyInt(), any());
+ }
+
+ @Test
+ public void testWaitingSyncCallback() {
+ TestWindowContainer mockWC = new TestWindowContainer(mWm, true /* waiter */);
+
+ BLASTSyncEngine bse = new BLASTSyncEngine(mWm);
+
+ BLASTSyncEngine.TransactionReadyListener listener = mock(
+ BLASTSyncEngine.TransactionReadyListener.class);
+
+ int id = bse.startSyncSet(listener);
+ bse.addToSyncSet(id, mockWC);
+ bse.setReady(id);
+ // Make sure traversals requested (one for add and another for setReady)
+ verify(mWm.mWindowPlacerLocked, times(2)).requestTraversal();
+ bse.onSurfacePlacement();
+ verify(listener, times(0)).onTransactionReady(anyInt(), any());
+
+ mockWC.onSyncFinishedDrawing();
+ // Make sure a (third) traversal is requested.
+ verify(mWm.mWindowPlacerLocked, times(3)).requestTraversal();
+ bse.onSurfacePlacement();
+ verify(listener, times(1)).onTransactionReady(eq(id), notNull());
+ }
+
+ @Test
+ public void testInvisibleSyncCallback() {
+ TestWindowContainer mockWC = new TestWindowContainer(mWm, true /* waiter */);
+
+ BLASTSyncEngine bse = new BLASTSyncEngine(mWm);
+
+ BLASTSyncEngine.TransactionReadyListener listener = mock(
+ BLASTSyncEngine.TransactionReadyListener.class);
+
+ int id = bse.startSyncSet(listener);
+ bse.addToSyncSet(id, mockWC);
+ bse.setReady(id);
+ // Make sure traversals requested (one for add and another for setReady)
+ verify(mWm.mWindowPlacerLocked, times(2)).requestTraversal();
+ bse.onSurfacePlacement();
+ verify(listener, times(0)).onTransactionReady(anyInt(), any());
+
+ // Finish sync if invisible.
+ mockWC.mVisibleRequested = false;
+ bse.onSurfacePlacement();
+ verify(listener, times(1)).onTransactionReady(eq(id), notNull());
+ assertEquals(SYNC_STATE_NONE, mockWC.mSyncState);
+ }
+
+ @Test
+ public void testWaitForChildrenCallback() {
+ TestWindowContainer parentWC = new TestWindowContainer(mWm, true /* waiter */);
+ TestWindowContainer childWC = new TestWindowContainer(mWm, true /* waiter */);
+ TestWindowContainer childWC2 = new TestWindowContainer(mWm, true /* waiter */);
+ parentWC.addChild(childWC, POSITION_TOP);
+ parentWC.addChild(childWC2, POSITION_TOP);
+
+ BLASTSyncEngine bse = new BLASTSyncEngine(mWm);
+
+ BLASTSyncEngine.TransactionReadyListener listener = mock(
+ BLASTSyncEngine.TransactionReadyListener.class);
+
+ int id = bse.startSyncSet(listener);
+ bse.addToSyncSet(id, parentWC);
+ bse.setReady(id);
+ bse.onSurfacePlacement();
+ verify(listener, times(0)).onTransactionReady(anyInt(), any());
+
+ parentWC.onSyncFinishedDrawing();
+ bse.onSurfacePlacement();
+ verify(listener, times(0)).onTransactionReady(anyInt(), any());
+
+ childWC.onSyncFinishedDrawing();
+ bse.onSurfacePlacement();
+ verify(listener, times(0)).onTransactionReady(anyInt(), any());
+
+ childWC2.onSyncFinishedDrawing();
+ bse.onSurfacePlacement();
+ verify(listener, times(1)).onTransactionReady(eq(id), notNull());
+ assertEquals(SYNC_STATE_NONE, parentWC.mSyncState);
+ assertEquals(SYNC_STATE_NONE, childWC.mSyncState);
+ assertEquals(SYNC_STATE_NONE, childWC2.mSyncState);
+ }
+
+ @Test
+ public void testWaitForParentCallback() {
+ TestWindowContainer parentWC = new TestWindowContainer(mWm, true /* waiter */);
+ TestWindowContainer childWC = new TestWindowContainer(mWm, true /* waiter */);
+ parentWC.addChild(childWC, POSITION_TOP);
+
+ BLASTSyncEngine bse = new BLASTSyncEngine(mWm);
+
+ BLASTSyncEngine.TransactionReadyListener listener = mock(
+ BLASTSyncEngine.TransactionReadyListener.class);
+
+ int id = bse.startSyncSet(listener);
+ bse.addToSyncSet(id, parentWC);
+ bse.setReady(id);
+ bse.onSurfacePlacement();
+ verify(listener, times(0)).onTransactionReady(anyInt(), any());
+
+ childWC.onSyncFinishedDrawing();
+ bse.onSurfacePlacement();
+ verify(listener, times(0)).onTransactionReady(anyInt(), any());
+
+ parentWC.onSyncFinishedDrawing();
+ bse.onSurfacePlacement();
+ verify(listener, times(1)).onTransactionReady(eq(id), notNull());
+ assertEquals(SYNC_STATE_NONE, parentWC.mSyncState);
+ assertEquals(SYNC_STATE_NONE, childWC.mSyncState);
+ }
+
+ @Test
+ public void testFillsParent() {
+ TestWindowContainer parentWC = new TestWindowContainer(mWm, true /* waiter */);
+ TestWindowContainer topChildWC = new TestWindowContainer(mWm, true /* waiter */);
+ TestWindowContainer botChildWC = new TestWindowContainer(mWm, true /* waiter */);
+ topChildWC.mFillsParent = botChildWC.mFillsParent = true;
+ parentWC.addChild(topChildWC, POSITION_TOP);
+ parentWC.addChild(botChildWC, POSITION_BOTTOM);
+
+ BLASTSyncEngine bse = new BLASTSyncEngine(mWm);
+
+ BLASTSyncEngine.TransactionReadyListener listener = mock(
+ BLASTSyncEngine.TransactionReadyListener.class);
+
+ int id = bse.startSyncSet(listener);
+ bse.addToSyncSet(id, parentWC);
+ bse.setReady(id);
+ bse.onSurfacePlacement();
+ verify(listener, times(0)).onTransactionReady(anyInt(), any());
+
+ parentWC.onSyncFinishedDrawing();
+ topChildWC.onSyncFinishedDrawing();
+ // Even though bottom isn't finished, we should see callback because it is occluded by top.
+ assertFalse(botChildWC.isSyncFinished());
+ bse.onSurfacePlacement();
+ verify(listener, times(1)).onTransactionReady(eq(id), notNull());
+
+ assertEquals(SYNC_STATE_NONE, parentWC.mSyncState);
+ assertEquals(SYNC_STATE_NONE, botChildWC.mSyncState);
+ assertEquals(SYNC_STATE_NONE, topChildWC.mSyncState);
+ }
+
+ @Test
+ public void testReparentOut() {
+ TestWindowContainer nonMemberParentWC = new TestWindowContainer(mWm, true /* waiter */);
+ TestWindowContainer parentWC = new TestWindowContainer(mWm, true /* waiter */);
+ TestWindowContainer topChildWC = new TestWindowContainer(mWm, true /* waiter */);
+ TestWindowContainer botChildWC = new TestWindowContainer(mWm, true /* waiter */);
+ parentWC.addChild(topChildWC, POSITION_TOP);
+ parentWC.addChild(botChildWC, POSITION_BOTTOM);
+
+ BLASTSyncEngine bse = new BLASTSyncEngine(mWm);
+
+ BLASTSyncEngine.TransactionReadyListener listener = mock(
+ BLASTSyncEngine.TransactionReadyListener.class);
+
+ int id = bse.startSyncSet(listener);
+ bse.addToSyncSet(id, parentWC);
+ bse.setReady(id);
+ bse.onSurfacePlacement();
+ verify(listener, times(0)).onTransactionReady(anyInt(), any());
+
+ parentWC.onSyncFinishedDrawing();
+ topChildWC.onSyncFinishedDrawing();
+ bse.onSurfacePlacement();
+ verify(listener, times(0)).onTransactionReady(anyInt(), any());
+
+ // reparent out cancels
+ botChildWC.reparent(nonMemberParentWC, POSITION_TOP);
+ assertEquals(SYNC_STATE_NONE, botChildWC.mSyncState);
+
+ bse.onSurfacePlacement();
+ verify(listener, times(1)).onTransactionReady(eq(id), notNull());
+ assertEquals(SYNC_STATE_NONE, parentWC.mSyncState);
+ assertEquals(SYNC_STATE_NONE, topChildWC.mSyncState);
+ }
+
+ @Test
+ public void testReparentIn() {
+ TestWindowContainer nonMemberParentWC = new TestWindowContainer(mWm, true /* waiter */);
+ TestWindowContainer parentWC = new TestWindowContainer(mWm, true /* waiter */);
+ TestWindowContainer topChildWC = new TestWindowContainer(mWm, true /* waiter */);
+ TestWindowContainer botChildWC = new TestWindowContainer(mWm, true /* waiter */);
+ parentWC.addChild(topChildWC, POSITION_TOP);
+ nonMemberParentWC.addChild(botChildWC, POSITION_BOTTOM);
+
+ BLASTSyncEngine bse = new BLASTSyncEngine(mWm);
+
+ BLASTSyncEngine.TransactionReadyListener listener = mock(
+ BLASTSyncEngine.TransactionReadyListener.class);
+
+ int id = bse.startSyncSet(listener);
+ bse.addToSyncSet(id, parentWC);
+ bse.setReady(id);
+ bse.onSurfacePlacement();
+ verify(listener, times(0)).onTransactionReady(anyInt(), any());
+
+ parentWC.onSyncFinishedDrawing();
+ topChildWC.onSyncFinishedDrawing();
+
+ // No-longer finished because new child
+ botChildWC.reparent(parentWC, POSITION_BOTTOM);
+ bse.onSurfacePlacement();
+ verify(listener, times(0)).onTransactionReady(anyInt(), any());
+
+ botChildWC.onSyncFinishedDrawing();
+ bse.onSurfacePlacement();
+ verify(listener, times(1)).onTransactionReady(eq(id), notNull());
+ assertEquals(SYNC_STATE_NONE, parentWC.mSyncState);
+ assertEquals(SYNC_STATE_NONE, topChildWC.mSyncState);
+ assertEquals(SYNC_STATE_NONE, botChildWC.mSyncState);
+ }
+
+ @Test
+ public void testRemoval() {
+ // Need different transactions to verify stuff
+ mWm.mTransactionFactory = () -> spy(new StubTransaction());
+ TestWindowContainer rootWC = new TestWindowContainer(mWm, false /* waiter */);
+ TestWindowContainer parentWC = new TestWindowContainer(mWm, true /* waiter */);
+ TestWindowContainer topChildWC = new TestWindowContainer(mWm, true /* waiter */);
+ TestWindowContainer botChildWC = new TestWindowContainer(mWm, true /* waiter */);
+ rootWC.addChild(parentWC, POSITION_TOP);
+ parentWC.addChild(topChildWC, POSITION_TOP);
+ parentWC.addChild(botChildWC, POSITION_BOTTOM);
+
+ BLASTSyncEngine bse = new BLASTSyncEngine(mWm);
+
+ BLASTSyncEngine.TransactionReadyListener listener = mock(
+ BLASTSyncEngine.TransactionReadyListener.class);
+
+ int id = bse.startSyncSet(listener);
+ bse.addToSyncSet(id, parentWC);
+ final BLASTSyncEngine.SyncGroup syncGroup = parentWC.mSyncGroup;
+ bse.setReady(id);
+ bse.onSurfacePlacement();
+ verify(listener, times(0)).onTransactionReady(anyInt(), any());
+
+ parentWC.onSyncFinishedDrawing();
+ topChildWC.removeImmediately();
+ bse.onSurfacePlacement();
+ verify(listener, times(0)).onTransactionReady(anyInt(), any());
+
+ // Removal should merge transaction into parent
+ verify(parentWC.mSyncTransaction, times(1)).merge(eq(topChildWC.mSyncTransaction));
+ assertEquals(SYNC_STATE_NONE, topChildWC.mSyncState);
+
+ // Removal of a sync-root should merge transaction into orphan
+ parentWC.removeImmediately();
+ final SurfaceControl.Transaction orphan = syncGroup.getOrphanTransaction();
+ verify(orphan, times(1)).merge(eq(parentWC.mSyncTransaction));
+
+ // Then the orphan transaction should be merged into sync
+ bse.onSurfacePlacement();
+ final ArgumentCaptor<SurfaceControl.Transaction> merged =
+ ArgumentCaptor.forClass(SurfaceControl.Transaction.class);
+ verify(listener, times(1)).onTransactionReady(eq(id), merged.capture());
+ final SurfaceControl.Transaction mergedTransaction = merged.getValue();
+ verify(mergedTransaction, times(1)).merge(eq(orphan));
+
+ assertEquals(SYNC_STATE_NONE, parentWC.mSyncState);
+ assertEquals(SYNC_STATE_NONE, botChildWC.mSyncState);
+ }
+
+ static class TestWindowContainer extends WindowContainer {
+ final boolean mWaiter;
+ boolean mVisibleRequested = true;
+ boolean mFillsParent = false;
+
+ TestWindowContainer(WindowManagerService wms, boolean waiter) {
+ super(wms);
+ mWaiter = waiter;
+ mDisplayContent = wms.getDefaultDisplayContentLocked();
+ }
+
+ @Override
+ boolean prepareSync() {
+ if (!super.prepareSync()) {
+ return false;
+ }
+ if (mWaiter) {
+ mSyncState = SYNC_STATE_WAITING_FOR_DRAW;
+ }
+ return true;
+ }
+
+ @Override
+ void createSurfaceControl(boolean force) {
+ // nothing
+ }
+
+ @Override
+ boolean isVisibleRequested() {
+ return mVisibleRequested;
+ }
+
+ @Override
+ boolean fillsParent() {
+ return mFillsParent;
+ }
+ }
+}
diff --git a/services/tests/wmtests/src/com/android/server/wm/TaskStackChangedListenerTest.java b/services/tests/wmtests/src/com/android/server/wm/TaskStackChangedListenerTest.java
index a54bbaf7f6e1..788ef5ad2ec4 100644
--- a/services/tests/wmtests/src/com/android/server/wm/TaskStackChangedListenerTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/TaskStackChangedListenerTest.java
@@ -242,40 +242,6 @@ public class TaskStackChangedListenerTest {
assertTrue(activity.mOnDetachedFromWindowCalled);
}
- @Test
- public void testTaskOnSingleTaskDisplayDrawn() throws Exception {
- final Instrumentation instrumentation = getInstrumentation();
-
- final CountDownLatch activityViewReadyLatch = new CountDownLatch(1);
- final CountDownLatch singleTaskDisplayDrawnLatch = new CountDownLatch(1);
- registerTaskStackChangedListener(new TaskStackListener() {
- @Override
- public void onSingleTaskDisplayDrawn(int displayId) throws RemoteException {
- singleTaskDisplayDrawnLatch.countDown();
- }
- });
- final ActivityViewTestActivity activity =
- (ActivityViewTestActivity) startTestActivity(ActivityViewTestActivity.class);
- final ActivityView activityView = activity.getActivityView();
- activityView.setCallback(new ActivityView.StateCallback() {
- @Override
- public void onActivityViewReady(ActivityView view) {
- activityViewReadyLatch.countDown();
- }
-
- @Override
- public void onActivityViewDestroyed(ActivityView view) {
- }
- });
- waitForCallback(activityViewReadyLatch);
-
- final Context context = instrumentation.getContext();
- Intent intent = new Intent(context, ActivityInActivityView.class);
- intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_MULTIPLE_TASK);
- SystemUtil.runWithShellPermissionIdentity(() -> activityView.startActivity(intent));
- waitForCallback(singleTaskDisplayDrawnLatch);
- }
-
public static class ActivityLaunchesNewActivityInActivityView extends TestActivity {
private boolean mActivityBLaunched = false;
@@ -291,61 +257,6 @@ public class TaskStackChangedListenerTest {
}
@Test
- public void testSingleTaskDisplayEmpty() throws Exception {
- final Instrumentation instrumentation = getInstrumentation();
-
- final CountDownLatch activityViewReadyLatch = new CountDownLatch(1);
- final CountDownLatch activityViewDestroyedLatch = new CountDownLatch(1);
- final CountDownLatch singleTaskDisplayDrawnLatch = new CountDownLatch(1);
- final CountDownLatch singleTaskDisplayEmptyLatch = new CountDownLatch(1);
-
- registerTaskStackChangedListener(new TaskStackListener() {
- @Override
- public void onSingleTaskDisplayDrawn(int displayId) throws RemoteException {
- singleTaskDisplayDrawnLatch.countDown();
- }
- @Override
- public void onSingleTaskDisplayEmpty(int displayId)
- throws RemoteException {
- singleTaskDisplayEmptyLatch.countDown();
- }
- });
- final ActivityViewTestActivity activity =
- (ActivityViewTestActivity) startTestActivity(ActivityViewTestActivity.class);
- final ActivityView activityView = activity.getActivityView();
- activityView.setCallback(new ActivityView.StateCallback() {
- @Override
- public void onActivityViewReady(ActivityView view) {
- activityViewReadyLatch.countDown();
- }
-
- @Override
- public void onActivityViewDestroyed(ActivityView view) {
- activityViewDestroyedLatch.countDown();
- }
- });
- waitForCallback(activityViewReadyLatch);
-
- // 1. start ActivityLaunchesNewActivityInActivityView in an ActivityView
- // 2. ActivityLaunchesNewActivityInActivityView launches ActivityB
- // 3. ActivityB finishes self.
- // 4. Verify ITaskStackListener#onSingleTaskDisplayEmpty is not called yet.
- final Context context = instrumentation.getContext();
- Intent intent = new Intent(context, ActivityLaunchesNewActivityInActivityView.class);
- intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_MULTIPLE_TASK);
- SystemUtil.runWithShellPermissionIdentity(() -> activityView.startActivity(intent));
- waitForCallback(singleTaskDisplayDrawnLatch);
- UiDevice.getInstance(getInstrumentation()).waitForIdle();
- assertEquals(1, singleTaskDisplayEmptyLatch.getCount());
-
- // 5. Release the container, and ActivityLaunchesNewActivityInActivityView finishes.
- // 6. Verify ITaskStackListener#onSingleTaskDisplayEmpty is called.
- activityView.release();
- waitForCallback(activityViewDestroyedLatch);
- waitForCallback(singleTaskDisplayEmptyLatch);
- }
-
- @Test
public void testTaskDisplayChanged() throws Exception {
final CountDownLatch activityViewReadyLatch = new CountDownLatch(1);
final ActivityViewTestActivity activity =
@@ -603,7 +514,7 @@ public class TaskStackChangedListenerTest {
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
- mActivityView = new ActivityView.Builder(this).setSingleInstance(true).build();
+ mActivityView = new ActivityView.Builder(this).build();
setContentView(mActivityView);
ViewGroup.LayoutParams layoutParams = mActivityView.getLayoutParams();
diff --git a/services/tests/wmtests/src/com/android/server/wm/TestIWindow.java b/services/tests/wmtests/src/com/android/server/wm/TestIWindow.java
index ea1223312cb2..db1c12f525f3 100644
--- a/services/tests/wmtests/src/com/android/server/wm/TestIWindow.java
+++ b/services/tests/wmtests/src/com/android/server/wm/TestIWindow.java
@@ -22,7 +22,7 @@ import android.os.ParcelFileDescriptor;
import android.os.RemoteException;
import android.util.MergedConfiguration;
import android.view.DragEvent;
-import android.view.IScrollCaptureController;
+import android.view.IScrollCaptureCallbacks;
import android.view.IWindow;
import android.view.InsetsSourceControl;
import android.view.InsetsState;
@@ -107,7 +107,7 @@ public class TestIWindow extends IWindow.Stub {
}
@Override
- public void requestScrollCapture(IScrollCaptureController controller) throws RemoteException {
+ public void requestScrollCapture(IScrollCaptureCallbacks callbacks) throws RemoteException {
}
@Override
diff --git a/services/tests/wmtests/src/com/android/server/wm/WindowOrganizerTests.java b/services/tests/wmtests/src/com/android/server/wm/WindowOrganizerTests.java
index aac83974eb51..c790f840485f 100644
--- a/services/tests/wmtests/src/com/android/server/wm/WindowOrganizerTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/WindowOrganizerTests.java
@@ -37,13 +37,13 @@ import static com.android.dx.mockito.inline.extended.ExtendedMockito.doNothing;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.doReturn;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.mock;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.never;
-import static com.android.dx.mockito.inline.extended.ExtendedMockito.reset;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.spyOn;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.times;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.verify;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.when;
import static com.android.server.wm.DisplayArea.Type.ABOVE_TASKS;
import static com.android.server.wm.WindowContainer.POSITION_TOP;
+import static com.android.server.wm.WindowContainer.SYNC_STATE_READY;
import static com.google.common.truth.Truth.assertThat;
@@ -479,16 +479,33 @@ public class WindowOrganizerTests extends WindowTestsBase {
@Test
public void testCreateDeleteRootTasks() {
+ ITaskOrganizer listener = new ITaskOrganizer.Stub() {
+ @Override
+ public void onTaskAppeared(RunningTaskInfo taskInfo, SurfaceControl leash) { }
+
+ @Override
+ public void onTaskVanished(RunningTaskInfo container) { }
+
+ @Override
+ public void onTaskInfoChanged(RunningTaskInfo info) {
+ }
+
+ @Override
+ public void onBackPressedOnTaskRoot(RunningTaskInfo taskInfo) {
+ }
+ };
+ mWm.mAtmService.mTaskOrganizerController.registerTaskOrganizer(listener);
+
RunningTaskInfo info1 = mWm.mAtmService.mTaskOrganizerController.createRootTask(
Display.DEFAULT_DISPLAY,
- WINDOWING_MODE_SPLIT_SCREEN_PRIMARY);
+ WINDOWING_MODE_SPLIT_SCREEN_PRIMARY).getTaskInfo();
assertEquals(WINDOWING_MODE_SPLIT_SCREEN_PRIMARY,
info1.configuration.windowConfiguration.getWindowingMode());
assertEquals(ACTIVITY_TYPE_UNDEFINED, info1.topActivityType);
RunningTaskInfo info2 = mWm.mAtmService.mTaskOrganizerController.createRootTask(
Display.DEFAULT_DISPLAY,
- WINDOWING_MODE_SPLIT_SCREEN_SECONDARY);
+ WINDOWING_MODE_SPLIT_SCREEN_SECONDARY).getTaskInfo();
assertEquals(WINDOWING_MODE_SPLIT_SCREEN_SECONDARY,
info2.configuration.windowConfiguration.getWindowingMode());
assertEquals(ACTIVITY_TYPE_UNDEFINED, info2.topActivityType);
@@ -522,7 +539,7 @@ public class WindowOrganizerTests extends WindowTestsBase {
};
mWm.mAtmService.mTaskOrganizerController.registerTaskOrganizer(listener);
RunningTaskInfo info1 = mWm.mAtmService.mTaskOrganizerController.createRootTask(
- mDisplayContent.mDisplayId, WINDOWING_MODE_SPLIT_SCREEN_SECONDARY);
+ mDisplayContent.mDisplayId, WINDOWING_MODE_SPLIT_SCREEN_SECONDARY).getTaskInfo();
final Task stack = createTaskStackOnDisplay(
WINDOWING_MODE_UNDEFINED, ACTIVITY_TYPE_STANDARD, mDisplayContent);
@@ -580,7 +597,7 @@ public class WindowOrganizerTests extends WindowTestsBase {
};
mWm.mAtmService.mTaskOrganizerController.registerTaskOrganizer(listener);
RunningTaskInfo info1 = mWm.mAtmService.mTaskOrganizerController.createRootTask(
- mDisplayContent.mDisplayId, WINDOWING_MODE_SPLIT_SCREEN_SECONDARY);
+ mDisplayContent.mDisplayId, WINDOWING_MODE_SPLIT_SCREEN_SECONDARY).getTaskInfo();
lastReportedTiles.clear();
called[0] = false;
@@ -641,9 +658,9 @@ public class WindowOrganizerTests extends WindowTestsBase {
};
mWm.mAtmService.mTaskOrganizerController.registerTaskOrganizer(listener);
RunningTaskInfo info1 = mWm.mAtmService.mTaskOrganizerController.createRootTask(
- mDisplayContent.mDisplayId, WINDOWING_MODE_SPLIT_SCREEN_PRIMARY);
+ mDisplayContent.mDisplayId, WINDOWING_MODE_SPLIT_SCREEN_PRIMARY).getTaskInfo();
RunningTaskInfo info2 = mWm.mAtmService.mTaskOrganizerController.createRootTask(
- mDisplayContent.mDisplayId, WINDOWING_MODE_SPLIT_SCREEN_SECONDARY);
+ mDisplayContent.mDisplayId, WINDOWING_MODE_SPLIT_SCREEN_SECONDARY).getTaskInfo();
final int initialRootTaskCount = mWm.mAtmService.mTaskOrganizerController.getRootTasks(
mDisplayContent.mDisplayId, null /* activityTypes */).size();
@@ -724,110 +741,15 @@ public class WindowOrganizerTests extends WindowTestsBase {
}
@Test
- public void testTrivialBLASTCallback() throws RemoteException {
- final Task stackController1 = createStack();
- final Task task = createTask(stackController1);
- final ITaskOrganizer organizer = registerMockOrganizer();
-
- spyOn(task);
- doReturn(true).when(task).isVisible();
-
- BLASTSyncEngine bse = new BLASTSyncEngine();
-
- BLASTSyncEngine.TransactionReadyListener transactionListener =
- mock(BLASTSyncEngine.TransactionReadyListener.class);
-
- int id = bse.startSyncSet(transactionListener);
- bse.addToSyncSet(id, task);
- bse.setReady(id);
- // Since this task has no windows the sync is trivial and completes immediately.
- verify(transactionListener)
- .onTransactionReady(anyInt(), any());
- }
-
- @Test
- public void testOverlappingBLASTCallback() throws RemoteException {
- final Task stackController1 = createStack();
- final Task task = createTask(stackController1);
- final ITaskOrganizer organizer = registerMockOrganizer();
-
- spyOn(task);
- doReturn(true).when(task).isVisible();
- final WindowState w = createAppWindow(task, TYPE_APPLICATION, "Enlightened Window");
- makeWindowVisible(w);
-
- BLASTSyncEngine bse = new BLASTSyncEngine();
-
- BLASTSyncEngine.TransactionReadyListener transactionListener =
- mock(BLASTSyncEngine.TransactionReadyListener.class);
-
- int id = bse.startSyncSet(transactionListener);
- assertEquals(true, bse.addToSyncSet(id, task));
- bse.setReady(id);
-
- int id2 = bse.startSyncSet(transactionListener);
- // We should be rejected from the second sync since we are already
- // in one.
- assertEquals(false, bse.addToSyncSet(id2, task));
- w.immediatelyNotifyBlastSync();
- assertEquals(true, bse.addToSyncSet(id2, task));
- bse.setReady(id2);
- }
-
- @Test
- public void testBLASTCallbackWithWindow() {
+ public void testBLASTCallbackWithActivityChildren() {
final Task stackController1 = createStack();
final Task task = createTask(stackController1);
- final ITaskOrganizer organizer = registerMockOrganizer();
final WindowState w = createAppWindow(task, TYPE_APPLICATION, "Enlightened Window");
- makeWindowVisible(w);
-
- BLASTSyncEngine bse = new BLASTSyncEngine();
-
- BLASTSyncEngine.TransactionReadyListener transactionListener =
- mock(BLASTSyncEngine.TransactionReadyListener.class);
- int id = bse.startSyncSet(transactionListener);
- bse.addToSyncSet(id, task);
- bse.setReady(id);
- // Since we have a window we have to wait for it to draw to finish sync.
- verify(transactionListener, never())
- .onTransactionReady(anyInt(), any());
- w.immediatelyNotifyBlastSync();
- verify(transactionListener)
- .onTransactionReady(anyInt(), any());
- }
-
- @Test
- public void testBLASTCallbackNoDoubleAdd() {
- final Task stackController1 = createStack();
- final Task task = createTask(stackController1);
- final ITaskOrganizer organizer = registerMockOrganizer();
- final WindowState w = createAppWindow(task, TYPE_APPLICATION, "Enlightened Window");
- makeWindowVisible(w);
-
- BLASTSyncEngine bse = new BLASTSyncEngine();
-
- BLASTSyncEngine.TransactionReadyListener transactionListener =
- mock(BLASTSyncEngine.TransactionReadyListener.class);
-
- int id = bse.startSyncSet(transactionListener);
- assertTrue(bse.addToSyncSet(id, w));
- assertFalse(bse.addToSyncSet(id, w));
-
- // Clean-up
- bse.setReady(id);
- }
-
-
- @Test
- public void testBLASTCallbackWithInvisibleWindow() {
- final Task stackController1 = createStack();
- final Task task = createTask(stackController1);
- final ITaskOrganizer organizer = registerMockOrganizer();
- final WindowState w = createAppWindow(task, TYPE_APPLICATION, "Enlightened Window");
+ w.mActivityRecord.mVisibleRequested = true;
+ w.mActivityRecord.setVisible(true);
- BLASTSyncEngine bse = new BLASTSyncEngine();
+ BLASTSyncEngine bse = new BLASTSyncEngine(mWm);
BLASTSyncEngine.TransactionReadyListener transactionListener =
mock(BLASTSyncEngine.TransactionReadyListener.class);
@@ -835,43 +757,19 @@ public class WindowOrganizerTests extends WindowTestsBase {
int id = bse.startSyncSet(transactionListener);
bse.addToSyncSet(id, task);
bse.setReady(id);
+ bse.onSurfacePlacement();
- // Since the window was invisible, the Task had no visible leaves and the sync should
- // complete as soon as we call setReady.
- verify(transactionListener)
- .onTransactionReady(anyInt(), any());
- }
-
- @Test
- public void testBLASTCallbackWithChildWindow() {
- final Task stackController1 = createStack();
- final Task task = createTask(stackController1);
- final ITaskOrganizer organizer = registerMockOrganizer();
- final WindowState w = createAppWindow(task, TYPE_APPLICATION, "Enlightened Window");
- final WindowState child = createWindow(w, TYPE_APPLICATION, "Other Window");
-
- w.mActivityRecord.setVisible(true);
- makeWindowVisible(w, child);
-
- BLASTSyncEngine bse = new BLASTSyncEngine();
-
- BLASTSyncEngine.TransactionReadyListener transactionListener =
- mock(BLASTSyncEngine.TransactionReadyListener.class);
+ // Even though w is invisible (and thus activity isn't waiting on it), activity will
+ // continue to wait until it has at-least 1 visible window.
+ // Since we have a child window we still shouldn't be done.
+ verify(transactionListener, never()).onTransactionReady(anyInt(), any());
- int id = bse.startSyncSet(transactionListener);
- assertEquals(true, bse.addToSyncSet(id, task));
- bse.setReady(id);
+ makeWindowVisible(w);
+ bse.onSurfacePlacement();
w.immediatelyNotifyBlastSync();
+ bse.onSurfacePlacement();
- // Since we have a child window we still shouldn't be done.
- verify(transactionListener, never())
- .onTransactionReady(anyInt(), any());
- reset(transactionListener);
-
- child.immediatelyNotifyBlastSync();
- // Ah finally! Done
- verify(transactionListener)
- .onTransactionReady(anyInt(), any());
+ verify(transactionListener).onTransactionReady(anyInt(), any());
}
class StubOrganizer extends ITaskOrganizer.Stub {
@@ -1028,8 +926,7 @@ public class WindowOrganizerTests extends WindowTestsBase {
}
@Test
- public void testBLASTCallbackWithMultipleWindows() throws Exception {
- final ITaskOrganizer organizer = registerMockOrganizer();
+ public void testBLASTCallbackWithWindows() throws Exception {
final Task stackController = createStack();
final Task task = createTask(stackController);
final WindowState w1 = createAppWindow(task, TYPE_APPLICATION, "Enlightened Window 1");
@@ -1048,13 +945,20 @@ public class WindowOrganizerTests extends WindowTestsBase {
verify(mockCallback, never()).onTransactionReady(anyInt(), any());
assertTrue(w1.useBLASTSync());
assertTrue(w2.useBLASTSync());
- w1.immediatelyNotifyBlastSync();
+ // Make second (bottom) ready. If we started with the top, since activities fillsParent
+ // by default, the sync would be considered finished.
+ w2.immediatelyNotifyBlastSync();
+ mWm.mSyncEngine.onSurfacePlacement();
+ verify(mockCallback, never()).onTransactionReady(anyInt(), any());
+
+ assertEquals(SYNC_STATE_READY, w2.mSyncState);
// Even though one Window finished drawing, both windows should still be using blast sync
assertTrue(w1.useBLASTSync());
assertTrue(w2.useBLASTSync());
- w2.immediatelyNotifyBlastSync();
+ w1.immediatelyNotifyBlastSync();
+ mWm.mSyncEngine.onSurfacePlacement();
verify(mockCallback).onTransactionReady(anyInt(), any());
assertFalse(w1.useBLASTSync());
assertFalse(w2.useBLASTSync());
diff --git a/services/tests/wmtests/src/com/android/server/wm/WindowStateTests.java b/services/tests/wmtests/src/com/android/server/wm/WindowStateTests.java
index 19bed48a4bc5..2691ae84db28 100644
--- a/services/tests/wmtests/src/com/android/server/wm/WindowStateTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/WindowStateTests.java
@@ -46,6 +46,7 @@ import static com.android.dx.mockito.inline.extended.ExtendedMockito.reset;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.spy;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.spyOn;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.verify;
+import static com.android.server.wm.WindowContainer.SYNC_STATE_WAITING_FOR_DRAW;
import static com.google.common.truth.Truth.assertThat;
@@ -609,7 +610,8 @@ public class WindowStateTests extends WindowTestsBase {
// Check that the window is in resizing if using blast sync.
win.reportResized();
- win.prepareForSync(mock(BLASTSyncEngine.TransactionReadyListener.class), 1);
+ win.prepareSync();
+ assertEquals(SYNC_STATE_WAITING_FOR_DRAW, win.mSyncState);
win.updateResizingWindowIfNeeded();
assertThat(mWm.mResizingWindows).contains(win);
diff --git a/services/tests/wmtests/src/com/android/server/wm/WindowTestsBase.java b/services/tests/wmtests/src/com/android/server/wm/WindowTestsBase.java
index 6237be0f4b26..924b286a4f8e 100644
--- a/services/tests/wmtests/src/com/android/server/wm/WindowTestsBase.java
+++ b/services/tests/wmtests/src/com/android/server/wm/WindowTestsBase.java
@@ -1006,10 +1006,10 @@ class WindowTestsBase extends SystemServiceTestsBase {
mDisplayId = displayId;
mService.mTaskOrganizerController.registerTaskOrganizer(this);
WindowContainerToken primary = mService.mTaskOrganizerController.createRootTask(
- displayId, WINDOWING_MODE_SPLIT_SCREEN_PRIMARY).token;
+ displayId, WINDOWING_MODE_SPLIT_SCREEN_PRIMARY).getTaskInfo().token;
mPrimary = WindowContainer.fromBinder(primary.asBinder()).asTask();
WindowContainerToken secondary = mService.mTaskOrganizerController.createRootTask(
- displayId, WINDOWING_MODE_SPLIT_SCREEN_SECONDARY).token;
+ displayId, WINDOWING_MODE_SPLIT_SCREEN_SECONDARY).getTaskInfo().token;
mSecondary = WindowContainer.fromBinder(secondary.asBinder()).asTask();
}
TestSplitOrganizer(ActivityTaskManagerService service) {
diff --git a/services/usb/java/com/android/server/usb/MtpNotificationManager.java b/services/usb/java/com/android/server/usb/MtpNotificationManager.java
index 39f2f296a305..8845f118f3a8 100644
--- a/services/usb/java/com/android/server/usb/MtpNotificationManager.java
+++ b/services/usb/java/com/android/server/usb/MtpNotificationManager.java
@@ -91,11 +91,12 @@ class MtpNotificationManager {
intent.putExtra(UsbManager.EXTRA_DEVICE, device);
intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY | Intent.FLAG_RECEIVER_FOREGROUND);
+ // Simple notification clicks are immutable
final PendingIntent openIntent = PendingIntent.getBroadcastAsUser(
mContext,
device.getDeviceId(),
intent,
- PendingIntent.FLAG_UPDATE_CURRENT,
+ PendingIntent.FLAG_UPDATE_CURRENT | PendingIntent.FLAG_IMMUTABLE,
UserHandle.SYSTEM);
builder.setContentIntent(openIntent);
diff --git a/services/usb/java/com/android/server/usb/UsbDeviceManager.java b/services/usb/java/com/android/server/usb/UsbDeviceManager.java
index 2269e1d070b1..58859e095554 100644
--- a/services/usb/java/com/android/server/usb/UsbDeviceManager.java
+++ b/services/usb/java/com/android/server/usb/UsbDeviceManager.java
@@ -1206,8 +1206,9 @@ public class UsbDeviceManager implements ActivityTaskManagerInternal.ScreenObser
Intent intent = Intent.makeRestartActivityTask(
new ComponentName("com.android.settings",
"com.android.settings.Settings$UsbDetailsActivity"));
+ // Simple notification clicks are immutable
pi = PendingIntent.getActivityAsUser(mContext, 0,
- intent, 0, null, UserHandle.CURRENT);
+ intent, PendingIntent.FLAG_IMMUTABLE, null, UserHandle.CURRENT);
channel = SystemNotificationChannels.USB;
} else {
final Intent intent = new Intent();
@@ -1217,7 +1218,9 @@ public class UsbDeviceManager implements ActivityTaskManagerInternal.ScreenObser
"help_url_audio_accessory_not_supported");
if (mContext.getPackageManager().resolveActivity(intent, 0) != null) {
- pi = PendingIntent.getActivity(mContext, 0, intent, 0);
+ // Simple notification clicks are immutable
+ pi = PendingIntent.getActivity(mContext, 0, intent,
+ PendingIntent.FLAG_IMMUTABLE);
} else {
pi = null;
}
diff --git a/services/usb/java/com/android/server/usb/UsbPortManager.java b/services/usb/java/com/android/server/usb/UsbPortManager.java
index ec7d4bd0d8c0..ca18c57d6f4b 100644
--- a/services/usb/java/com/android/server/usb/UsbPortManager.java
+++ b/services/usb/java/com/android/server/usb/UsbPortManager.java
@@ -230,8 +230,9 @@ public class UsbPortManager {
com.android.internal.R.string.config_usbContaminantActivity)));
intent.putExtra(UsbManager.EXTRA_PORT, ParcelableUsbPort.of(currentPortInfo.mUsbPort));
+ // Simple notification clicks are immutable
PendingIntent pi = PendingIntent.getActivityAsUser(mContext, 0,
- intent, 0, null, UserHandle.CURRENT);
+ intent, PendingIntent.FLAG_IMMUTABLE, null, UserHandle.CURRENT);
Notification.Builder builder = new Notification.Builder(mContext, channel)
.setOngoing(true)
diff --git a/telecomm/java/android/telecom/Call.java b/telecomm/java/android/telecom/Call.java
index 9f16543c410e..a85eb53605d6 100755
--- a/telecomm/java/android/telecom/Call.java
+++ b/telecomm/java/android/telecom/Call.java
@@ -1683,7 +1683,6 @@ public final class Call {
* @hide
*/
@SystemApi
- @TestApi
public void enterBackgroundAudioProcessing() {
if (mState != STATE_ACTIVE && mState != STATE_RINGING) {
throw new IllegalStateException("Call must be active or ringing");
@@ -1704,7 +1703,6 @@ public final class Call {
* @hide
*/
@SystemApi
- @TestApi
public void exitBackgroundAudioProcessing(boolean shouldRing) {
if (mState != STATE_AUDIO_PROCESSING) {
throw new IllegalStateException("Call must in the audio processing state");
diff --git a/telecomm/java/android/telecom/CallScreeningService.java b/telecomm/java/android/telecom/CallScreeningService.java
index 49f183151e27..7988b036ccd3 100644
--- a/telecomm/java/android/telecom/CallScreeningService.java
+++ b/telecomm/java/android/telecom/CallScreeningService.java
@@ -21,7 +21,6 @@ import android.annotation.NonNull;
import android.annotation.RequiresPermission;
import android.annotation.SdkConstant;
import android.annotation.SystemApi;
-import android.annotation.TestApi;
import android.app.Service;
import android.content.ComponentName;
import android.content.Intent;
@@ -323,7 +322,6 @@ public abstract class CallScreeningService extends Service {
* @hide
*/
@SystemApi
- @TestApi
@RequiresPermission(Manifest.permission.CAPTURE_AUDIO_OUTPUT)
public @NonNull Builder setShouldScreenCallViaAudioProcessing(
boolean shouldScreenCallViaAudioProcessing) {
diff --git a/telecomm/java/android/telecom/Conference.java b/telecomm/java/android/telecom/Conference.java
index 39c3ff9e8839..dc2fb948fdbe 100644
--- a/telecomm/java/android/telecom/Conference.java
+++ b/telecomm/java/android/telecom/Conference.java
@@ -24,7 +24,6 @@ import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.RequiresPermission;
import android.annotation.SystemApi;
-import android.annotation.TestApi;
import android.net.Uri;
import android.os.Bundle;
import android.os.SystemClock;
@@ -137,7 +136,6 @@ public abstract class Conference extends Conferenceable {
* @hide
*/
@SystemApi
- @TestApi
public final @NonNull String getTelecomCallId() {
return mTelecomCallId;
}
@@ -609,7 +607,6 @@ public abstract class Conference extends Conferenceable {
* @return The primary connection.
* @hide
*/
- @TestApi
@SystemApi
public Connection getPrimaryConnection() {
if (mUnmodifiableChildConnections == null || mUnmodifiableChildConnections.isEmpty()) {
@@ -1012,7 +1009,6 @@ public abstract class Conference extends Conferenceable {
* @hide
*/
@SystemApi
- @TestApi
@RequiresPermission(MODIFY_PHONE_STATE)
public void setConferenceState(boolean isConference) {
mIsMultiparty = isConference;
@@ -1067,7 +1063,6 @@ public abstract class Conference extends Conferenceable {
* @hide
*/
@SystemApi
- @TestApi
@RequiresPermission(MODIFY_PHONE_STATE)
public final void setAddress(@NonNull Uri address,
@TelecomManager.Presentation int presentation) {
@@ -1155,7 +1150,6 @@ public abstract class Conference extends Conferenceable {
* @hide
*/
@SystemApi
- @TestApi
public final void setCallerDisplayName(@NonNull String callerDisplayName,
@TelecomManager.Presentation int presentation) {
Log.d(this, "setCallerDisplayName %s", callerDisplayName);
diff --git a/telecomm/java/android/telecom/Connection.java b/telecomm/java/android/telecom/Connection.java
index 00b711643fe6..bbf34df8fe84 100755..100644
--- a/telecomm/java/android/telecom/Connection.java
+++ b/telecomm/java/android/telecom/Connection.java
@@ -25,7 +25,6 @@ import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.RequiresPermission;
import android.annotation.SystemApi;
-import android.annotation.TestApi;
import android.app.Notification;
import android.bluetooth.BluetoothDevice;
import android.compat.annotation.UnsupportedAppUsage;
@@ -307,7 +306,6 @@ public abstract class Connection extends Conferenceable {
* @hide
*/
@SystemApi
- @TestApi
public static final int CAPABILITY_SPEED_UP_MT_AUDIO = 0x00040000;
/**
@@ -345,7 +343,6 @@ public abstract class Connection extends Conferenceable {
* @hide
*/
@SystemApi
- @TestApi
public static final int CAPABILITY_CONFERENCE_HAS_NO_CHILDREN = 0x00200000;
/**
@@ -417,7 +414,6 @@ public abstract class Connection extends Conferenceable {
* @hide
*/
@SystemApi
- @TestApi
public static final int PROPERTY_EMERGENCY_CALLBACK_MODE = 1<<0;
/**
@@ -428,7 +424,6 @@ public abstract class Connection extends Conferenceable {
* @hide
*/
@SystemApi
- @TestApi
public static final int PROPERTY_GENERIC_CONFERENCE = 1<<1;
/**
@@ -480,7 +475,6 @@ public abstract class Connection extends Conferenceable {
* @hide
*/
@SystemApi
- @TestApi
public static final int PROPERTY_IS_DOWNGRADED_CONFERENCE = 1<<6;
/**
@@ -524,7 +518,6 @@ public abstract class Connection extends Conferenceable {
* @hide
*/
@SystemApi
- @TestApi
public static final int PROPERTY_REMOTELY_HOSTED = 1 << 11;
/**
@@ -702,7 +695,6 @@ public abstract class Connection extends Conferenceable {
* @hide
*/
@SystemApi
- @TestApi
public static final String EXTRA_DISABLE_ADD_CALL =
"android.telecom.extra.DISABLE_ADD_CALL";
@@ -2054,7 +2046,6 @@ public abstract class Connection extends Conferenceable {
* @hide
*/
@SystemApi
- @TestApi
public final @Nullable String getTelecomCallId() {
return mTelecomCallId;
}
@@ -2171,7 +2162,6 @@ public abstract class Connection extends Conferenceable {
* @hide
*/
@SystemApi
- @TestApi
public final @IntRange(from = 0) long getConnectTimeMillis() {
return mConnectTimeMillis;
}
@@ -2196,7 +2186,6 @@ public abstract class Connection extends Conferenceable {
* @hide
*/
@SystemApi
- @TestApi
public final @ElapsedRealtimeLong long getConnectionStartElapsedRealtimeMillis() {
return mConnectElapsedTimeMillis;
}
@@ -2279,7 +2268,6 @@ public abstract class Connection extends Conferenceable {
* @hide
*/
@SystemApi
- @TestApi
public void setTelecomCallId(@NonNull String callId) {
mTelecomCallId = callId;
}
@@ -2628,7 +2616,6 @@ public abstract class Connection extends Conferenceable {
* @hide
*/
@SystemApi
- @TestApi
@RequiresPermission(MODIFY_PHONE_STATE)
public final void setConnectTimeMillis(@IntRange(from = 0) long connectTimeMillis) {
mConnectTimeMillis = connectTimeMillis;
@@ -2651,7 +2638,6 @@ public abstract class Connection extends Conferenceable {
* @hide
*/
@SystemApi
- @TestApi
@RequiresPermission(MODIFY_PHONE_STATE)
public final void setConnectionStartElapsedRealtimeMillis(
@ElapsedRealtimeLong long connectElapsedTimeMillis) {
@@ -2722,7 +2708,6 @@ public abstract class Connection extends Conferenceable {
* @hide
*/
@SystemApi
- @TestApi
public final void resetConnectionTime() {
for (Listener l : mListeners) {
l.onConnectionTimeReset(this);
@@ -3505,7 +3490,6 @@ public abstract class Connection extends Conferenceable {
* @hide
*/
@SystemApi
- @TestApi
public void setPhoneAccountHandle(@NonNull PhoneAccountHandle phoneAccountHandle) {
if (mPhoneAccountHandle != phoneAccountHandle) {
mPhoneAccountHandle = phoneAccountHandle;
@@ -3524,7 +3508,6 @@ public abstract class Connection extends Conferenceable {
* @hide
*/
@SystemApi
- @TestApi
public @Nullable PhoneAccountHandle getPhoneAccountHandle() {
return mPhoneAccountHandle;
}
@@ -3590,7 +3573,6 @@ public abstract class Connection extends Conferenceable {
* @hide
*/
@SystemApi
- @TestApi
public void setCallDirection(@Call.Details.CallDirection int callDirection) {
mCallDirection = callDirection;
}
diff --git a/telecomm/java/android/telecom/ConnectionRequest.java b/telecomm/java/android/telecom/ConnectionRequest.java
index 6d7ceca0a2cd..b73ef9b794e4 100644
--- a/telecomm/java/android/telecom/ConnectionRequest.java
+++ b/telecomm/java/android/telecom/ConnectionRequest.java
@@ -327,7 +327,6 @@ public final class ConnectionRequest implements Parcelable {
* @hide
*/
@SystemApi
- @TestApi
public @Nullable String getTelecomCallId() {
return mTelecomCallId;
}
diff --git a/telecomm/java/android/telecom/PhoneAccount.java b/telecomm/java/android/telecom/PhoneAccount.java
index 866e17148a1a..5024ae27ee49 100644
--- a/telecomm/java/android/telecom/PhoneAccount.java
+++ b/telecomm/java/android/telecom/PhoneAccount.java
@@ -21,7 +21,6 @@ import static android.Manifest.permission.MODIFY_PHONE_STATE;
import android.annotation.NonNull;
import android.annotation.RequiresPermission;
import android.annotation.SystemApi;
-import android.annotation.TestApi;
import android.content.Intent;
import android.graphics.drawable.Icon;
import android.net.Uri;
@@ -635,7 +634,6 @@ public final class PhoneAccount implements Parcelable {
* @hide
*/
@SystemApi
- @TestApi
@RequiresPermission(MODIFY_PHONE_STATE)
public @NonNull Builder setGroupId(@NonNull String groupId) {
if (groupId != null) {
diff --git a/telecomm/java/android/telecom/PhoneAccountSuggestionService.java b/telecomm/java/android/telecom/PhoneAccountSuggestionService.java
index ba3822cb9951..8a91b9e9ee81 100644
--- a/telecomm/java/android/telecom/PhoneAccountSuggestionService.java
+++ b/telecomm/java/android/telecom/PhoneAccountSuggestionService.java
@@ -19,7 +19,6 @@ package android.telecom;
import android.annotation.NonNull;
import android.annotation.SdkConstant;
import android.annotation.SystemApi;
-import android.annotation.TestApi;
import android.app.Service;
import android.content.Intent;
import android.os.IBinder;
@@ -57,7 +56,6 @@ import java.util.Map;
* @hide
*/
@SystemApi
-@TestApi
public class PhoneAccountSuggestionService extends Service {
/**
* The {@link Intent} that must be declared in the {@code intent-filter} element of the
diff --git a/telecomm/java/android/telecom/TelecomManager.java b/telecomm/java/android/telecom/TelecomManager.java
index f1deec60aca7..82da4475c1b9 100644
--- a/telecomm/java/android/telecom/TelecomManager.java
+++ b/telecomm/java/android/telecom/TelecomManager.java
@@ -25,7 +25,6 @@ import android.annotation.SuppressAutoDoc;
import android.annotation.SuppressLint;
import android.annotation.SystemApi;
import android.annotation.SystemService;
-import android.annotation.TestApi;
import android.compat.annotation.UnsupportedAppUsage;
import android.content.ComponentName;
import android.content.Context;
@@ -693,7 +692,6 @@ public class TelecomManager {
*
* @hide
*/
- @TestApi
@SystemApi
public static final int TTY_MODE_OFF = 0;
@@ -703,7 +701,6 @@ public class TelecomManager {
*
* @hide
*/
- @TestApi
@SystemApi
public static final int TTY_MODE_FULL = 1;
@@ -714,7 +711,6 @@ public class TelecomManager {
*
* @hide
*/
- @TestApi
@SystemApi
public static final int TTY_MODE_HCO = 2;
@@ -725,7 +721,6 @@ public class TelecomManager {
*
* @hide
*/
- @TestApi
@SystemApi
public static final int TTY_MODE_VCO = 3;
@@ -736,7 +731,6 @@ public class TelecomManager {
* TTY mode.
* @hide
*/
- @TestApi
@SystemApi
public static final String ACTION_CURRENT_TTY_MODE_CHANGED =
"android.telecom.action.CURRENT_TTY_MODE_CHANGED";
@@ -759,7 +753,6 @@ public class TelecomManager {
* plugged into the device.
* @hide
*/
- @TestApi
@SystemApi
public static final String EXTRA_CURRENT_TTY_MODE =
"android.telecom.extra.CURRENT_TTY_MODE";
@@ -771,7 +764,6 @@ public class TelecomManager {
* preferred TTY mode.
* @hide
*/
- @TestApi
@SystemApi
public static final String ACTION_TTY_PREFERRED_MODE_CHANGED =
"android.telecom.action.TTY_PREFERRED_MODE_CHANGED";
@@ -790,7 +782,6 @@ public class TelecomManager {
* </ul>
* @hide
*/
- @TestApi
@SystemApi
public static final String EXTRA_TTY_PREFERRED_MODE =
"android.telecom.extra.TTY_PREFERRED_MODE";
@@ -1045,7 +1036,6 @@ public class TelecomManager {
* @hide
*/
@RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE)
- @TestApi
@SystemApi
public void setUserSelectedOutgoingPhoneAccount(@Nullable PhoneAccountHandle accountHandle) {
try {
@@ -1219,7 +1209,6 @@ public class TelecomManager {
* @hide
*/
@SystemApi
- @TestApi
@RequiresPermission(READ_PRIVILEGED_PHONE_STATE)
public @NonNull List<PhoneAccountHandle> getCallCapablePhoneAccounts(
boolean includeDisabledAccounts) {
@@ -1453,7 +1442,6 @@ public class TelecomManager {
* @hide
*/
@SystemApi
- @TestApi
@RequiresPermission(READ_PRIVILEGED_PHONE_STATE)
public @Nullable String getDefaultDialerPackage(@NonNull UserHandle userHandle) {
try {
@@ -1677,7 +1665,6 @@ public class TelecomManager {
* @hide
*/
@SystemApi
- @TestApi
@RequiresPermission(anyOf = {
READ_PRIVILEGED_PHONE_STATE,
android.Manifest.permission.READ_PHONE_STATE
@@ -1835,7 +1822,6 @@ public class TelecomManager {
* @hide
*/
@SystemApi
- @TestApi
@RequiresPermission(READ_PRIVILEGED_PHONE_STATE)
public @TtyMode int getCurrentTtyMode() {
try {
@@ -2249,7 +2235,6 @@ public class TelecomManager {
* @hide
*/
@SystemApi
- @TestApi
@NonNull
public Intent createLaunchEmergencyDialerIntent(@Nullable String number) {
ITelecomService service = getTelecomService();
@@ -2402,7 +2387,6 @@ public class TelecomManager {
* @hide
*/
@SystemApi
- @TestApi
@RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE)
public boolean isInEmergencyCall() {
try {
diff --git a/telephony/api/system-current.txt b/telephony/api/system-current.txt
index a67273cfc908..5eaa6c87a102 100644
--- a/telephony/api/system-current.txt
+++ b/telephony/api/system-current.txt
@@ -698,6 +698,7 @@ package android.telephony {
method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public int getCarrierPrivilegeStatus(int);
method @NonNull @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public java.util.List<java.lang.String> getCarrierPrivilegedPackagesForAllActiveSubscriptions();
method @Nullable @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public android.telephony.CarrierRestrictionRules getCarrierRestrictionRules();
+ method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public int getCdmaEnhancedRoamingIndicatorIconIndex();
method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public String getCdmaMdn();
method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public String getCdmaMdn(int);
method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public String getCdmaMin();
@@ -1431,6 +1432,10 @@ package android.telephony.ims {
field @NonNull public static final android.os.Parcelable.Creator<android.telephony.ims.ImsExternalCallState> CREATOR;
}
+ public class ImsManager {
+ method @NonNull public android.telephony.ims.SipDelegateManager getSipDelegateManager(int);
+ }
+
public class ImsMmTelManager implements android.telephony.ims.RegistrationManager {
method @Deprecated @NonNull @RequiresPermission(anyOf={android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE, android.Manifest.permission.READ_PRECISE_PHONE_STATE}) public static android.telephony.ims.ImsMmTelManager createForSubscriptionId(int);
method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public void getFeatureState(@NonNull java.util.concurrent.Executor, @NonNull java.util.function.Consumer<java.lang.Integer>) throws android.telephony.ims.ImsException;
@@ -1466,10 +1471,13 @@ package android.telephony.ims {
method public void disableIms(int);
method public void enableIms(int);
method public android.telephony.ims.stub.ImsConfigImplBase getConfig(int);
+ method public long getImsServiceCapabilities();
method public android.telephony.ims.stub.ImsRegistrationImplBase getRegistration(int);
+ method @Nullable public android.telephony.ims.stub.SipTransportImplBase getSipTransport(int);
method public final void onUpdateSupportedImsFeatures(android.telephony.ims.stub.ImsFeatureConfiguration) throws android.os.RemoteException;
method public android.telephony.ims.stub.ImsFeatureConfiguration querySupportedImsFeatures();
method public void readyForFeatureCreation();
+ field public static final long CAPABILITY_SIP_DELEGATE_CREATION = 2L; // 0x2L
}
public final class ImsSsData implements android.os.Parcelable {
@@ -1715,6 +1723,10 @@ package android.telephony.ims {
method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setUceSettingEnabled(boolean) throws android.telephony.ims.ImsException;
}
+ public class SipDelegateManager {
+ method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public boolean isSupported() throws android.telephony.ims.ImsException;
+ }
+
}
package android.telephony.ims.feature {
@@ -1964,6 +1976,10 @@ package android.telephony.ims.stub {
method public int updateColr(int);
}
+ public class SipTransportImplBase {
+ ctor public SipTransportImplBase(@NonNull java.util.concurrent.Executor);
+ }
+
}
package android.telephony.mbms {
diff --git a/telephony/java/android/telephony/AccessNetworkConstants.java b/telephony/java/android/telephony/AccessNetworkConstants.java
index 39a754389254..d01297147fdb 100644
--- a/telephony/java/android/telephony/AccessNetworkConstants.java
+++ b/telephony/java/android/telephony/AccessNetworkConstants.java
@@ -18,7 +18,6 @@ package android.telephony;
import android.annotation.IntDef;
import android.annotation.SystemApi;
-import android.annotation.TestApi;
import android.hardware.radio.V1_1.GeranBands;
import android.hardware.radio.V1_5.AccessNetwork;
import android.hardware.radio.V1_5.EutranBands;
@@ -49,7 +48,6 @@ public final class AccessNetworkConstants {
* @hide
*/
@SystemApi
- @TestApi
public static final int TRANSPORT_TYPE_INVALID = -1;
/**
@@ -438,7 +436,6 @@ public final class AccessNetworkConstants {
* @hide
*/
@SystemApi
- @TestApi
public static final int FREQUENCY_RANGE_GROUP_UNKNOWN = 0;
/**
@@ -447,7 +444,6 @@ public final class AccessNetworkConstants {
* @hide
*/
@SystemApi
- @TestApi
public static final int FREQUENCY_RANGE_GROUP_1 = 1;
/**
@@ -456,7 +452,6 @@ public final class AccessNetworkConstants {
* @hide
*/
@SystemApi
- @TestApi
public static final int FREQUENCY_RANGE_GROUP_2 = 2;
/**
@@ -481,7 +476,6 @@ public final class AccessNetworkConstants {
* @hide
*/
@SystemApi
- @TestApi
public static @FrequencyRangeGroup int getFrequencyRangeGroup(@NgranBand int band) {
switch (band) {
case BAND_1:
diff --git a/telephony/java/android/telephony/BarringInfo.java b/telephony/java/android/telephony/BarringInfo.java
index 92423a2f2218..e9698adc0356 100644
--- a/telephony/java/android/telephony/BarringInfo.java
+++ b/telephony/java/android/telephony/BarringInfo.java
@@ -252,7 +252,6 @@ public final class BarringInfo implements Parcelable {
private SparseArray<BarringServiceInfo> mBarringServiceInfos;
/** @hide */
- @TestApi
@SystemApi
public BarringInfo() {
mBarringServiceInfos = new SparseArray<>();
diff --git a/telephony/java/android/telephony/CallQuality.java b/telephony/java/android/telephony/CallQuality.java
index 1effeb774484..fa70c33965ed 100644
--- a/telephony/java/android/telephony/CallQuality.java
+++ b/telephony/java/android/telephony/CallQuality.java
@@ -20,7 +20,6 @@ import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.SystemApi;
-import android.annotation.TestApi;
import android.os.Parcel;
import android.os.Parcelable;
@@ -41,7 +40,6 @@ import java.util.Objects;
* @hide
*/
@SystemApi
-@TestApi
public final class CallQuality implements Parcelable {
// Constants representing the call quality level (see #CallQuality);
diff --git a/telephony/java/android/telephony/CarrierConfigManager.java b/telephony/java/android/telephony/CarrierConfigManager.java
index 8261b53a2c9f..157609130c1b 100755..100644
--- a/telephony/java/android/telephony/CarrierConfigManager.java
+++ b/telephony/java/android/telephony/CarrierConfigManager.java
@@ -23,7 +23,6 @@ import android.annotation.RequiresPermission;
import android.annotation.SuppressLint;
import android.annotation.SystemApi;
import android.annotation.SystemService;
-import android.annotation.TestApi;
import android.compat.annotation.UnsupportedAppUsage;
import android.content.ComponentName;
import android.content.Context;
@@ -3833,11 +3832,26 @@ public class CarrierConfigManager {
public static final String KEY_WIFI_OFF_DEFERRING_TIME_MILLIS_INT =
KEY_PREFIX + "wifi_off_deferring_time_millis_int";
+ /**
+ * A boolean flag specifying whether or not this carrier requires one IMS registration for
+ * all IMS services (MMTEL and RCS).
+ * <p>
+ * If set to {@code true}, the IMS Service must use one IMS registration for all IMS
+ * services. If set to {@code false}, IMS services may use separate IMS registrations for
+ * MMTEL and RCS.
+ * <p>
+ * The default value for this configuration is {@code false}.
+ * @see android.telephony.ims.SipDelegateManager
+ */
+ public static final String KEY_IMS_SINGLE_REGISTRATION_REQUIRED_BOOL =
+ KEY_PREFIX + "ims_single_registration_required_bool";
+
private Ims() {}
private static PersistableBundle getDefaults() {
PersistableBundle defaults = new PersistableBundle();
defaults.putInt(KEY_WIFI_OFF_DEFERRING_TIME_MILLIS_INT, 4000);
+ defaults.putBoolean(KEY_IMS_SINGLE_REGISTRATION_REQUIRED_BOOL, false);
return defaults;
}
}
@@ -4603,7 +4617,6 @@ public class CarrierConfigManager {
*/
@RequiresPermission(Manifest.permission.MODIFY_PHONE_STATE)
@SystemApi
- @TestApi
public void overrideConfig(int subscriptionId, @Nullable PersistableBundle overrideValues) {
overrideConfig(subscriptionId, overrideValues, false);
}
diff --git a/telephony/java/android/telephony/CdmaEriInformation.java b/telephony/java/android/telephony/CdmaEriInformation.java
deleted file mode 100644
index fd0b905e9c3e..000000000000
--- a/telephony/java/android/telephony/CdmaEriInformation.java
+++ /dev/null
@@ -1,169 +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 android.telephony;
-
-import android.annotation.IntDef;
-import android.annotation.NonNull;
-import android.annotation.SystemApi;
-import android.os.Parcel;
-import android.os.Parcelable;
-
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-
-/**
- * CDMA ERI (Enhanced Roaming Indicator) information.
- *
- * This contains the following ERI information
- *
- * 1. ERI (Enhanced Roaming Indicator) icon index. The number is assigned by
- * 3GPP2 C.R1001-H v1.0 Table 8.1-1. Additionally carriers define their own
- * ERI icon index.
- * 2. CDMA ERI icon mode. This represents how the icon should be displayed.
- * Its one of the following CDMA ERI icon mode
- * {@link android.telephony.CdmaEriInformation#ERI_ICON_MODE_NORMAL}
- * {@link android.telephony.CdmaEriInformation#ERI_ICON_MODE_FLASH}
- *
- * @hide
- */
-public final class CdmaEriInformation implements Parcelable {
- /** @hide */
- @Retention(RetentionPolicy.SOURCE)
- @IntDef(prefix = {"ERI_"}, value = {
- ERI_ON,
- ERI_OFF,
- ERI_FLASH
- })
- public @interface EriIconIndex {}
-
- /**
- * ERI (Enhanced Roaming Indicator) is ON i.e value 0 defined by
- * 3GPP2 C.R1001-H v1.0 Table 8.1-1.
- */
- public static final int ERI_ON = 0;
-
- /**
- * ERI (Enhanced Roaming Indicator) is OFF i.e value 1 defined by
- * 3GPP2 C.R1001-H v1.0 Table 8.1-1.
- */
- public static final int ERI_OFF = 1;
-
- /**
- * ERI (Enhanced Roaming Indicator) is FLASH i.e value 2 defined by
- * 3GPP2 C.R1001-H v1.0 Table 8.1-1.
- */
- public static final int ERI_FLASH = 2;
-
- /** @hide */
- @Retention(RetentionPolicy.SOURCE)
- @IntDef(prefix = {"ERI_ICON_MODE_"}, value = {
- ERI_ICON_MODE_NORMAL,
- ERI_ICON_MODE_FLASH
- })
- public @interface EriIconMode {}
-
- /**
- * ERI (Enhanced Roaming Indicator) icon mode is normal. This constant represents that
- * the ERI icon should be displayed normally.
- *
- * Note: ERI is defined 3GPP2 C.R1001-H Table 8.1-1
- */
- public static final int ERI_ICON_MODE_NORMAL = 0;
-
- /**
- * ERI (Enhanced Roaming Indicator) icon mode flash. This constant represents that
- * the ERI icon should be flashing.
- *
- * Note: ERI is defined 3GPP2 C.R1001-H Table 8.1-1
- */
- public static final int ERI_ICON_MODE_FLASH = 1;
-
- private @EriIconIndex int mIconIndex;
- private @EriIconMode int mIconMode;
-
- /**
- * Creates CdmaEriInformation from iconIndex and iconMode
- *
- * @hide
- */
- public CdmaEriInformation(@EriIconIndex int iconIndex, @EriIconMode int iconMode) {
- mIconIndex = iconIndex;
- mIconMode = iconMode;
- }
-
- /** Gets the ERI icon index */
- public @EriIconIndex int getEriIconIndex() {
- return mIconIndex;
- }
-
- /**
- * Sets the ERI icon index
- *
- * @hide
- */
- public void setEriIconIndex(@EriIconIndex int iconIndex) {
- mIconIndex = iconIndex;
- }
-
- /** Gets the ERI icon mode */
- public @EriIconMode int getEriIconMode() {
- return mIconMode;
- }
-
- /**
- * Sets the ERI icon mode
- *
- * @hide
- */
- public void setEriIconMode(@EriIconMode int iconMode) {
- mIconMode = iconMode;
- }
- /** Implement the Parcelable interface */
- @Override
- public void writeToParcel(@NonNull Parcel dest, int flags) {
- dest.writeInt(mIconIndex);
- dest.writeInt(mIconMode);
- }
-
- /** Implement the Parcelable interface */
- @Override
- public int describeContents() {
- return 0;
- }
-
- /**
- * Construct a CdmaEriInformation object from the given parcel
- */
- private CdmaEriInformation(Parcel in) {
- mIconIndex = in.readInt();
- mIconMode = in.readInt();
- }
-
- /** Implement the Parcelable interface */
- public static final @android.annotation.NonNull Parcelable.Creator<CdmaEriInformation> CREATOR =
- new Parcelable.Creator<CdmaEriInformation>() {
- @Override
- public CdmaEriInformation createFromParcel(Parcel in) {
- return new CdmaEriInformation(in);
- }
-
- @Override
- public CdmaEriInformation[] newArray(int size) {
- return new CdmaEriInformation[size];
- }
- };
-}
diff --git a/telephony/java/android/telephony/DataSpecificRegistrationInfo.java b/telephony/java/android/telephony/DataSpecificRegistrationInfo.java
index e91d6fc9d801..597fe8f85cfa 100644
--- a/telephony/java/android/telephony/DataSpecificRegistrationInfo.java
+++ b/telephony/java/android/telephony/DataSpecificRegistrationInfo.java
@@ -19,7 +19,6 @@ package android.telephony;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.SystemApi;
-import android.annotation.TestApi;
import android.os.Parcel;
import android.os.Parcelable;
@@ -31,7 +30,6 @@ import java.util.Objects;
* @hide
*/
@SystemApi
-@TestApi
public final class DataSpecificRegistrationInfo implements Parcelable {
/**
* @hide
diff --git a/telephony/java/android/telephony/ImsManager.java b/telephony/java/android/telephony/ImsManager.java
index 3984bd769edd..28feab27a794 100644
--- a/telephony/java/android/telephony/ImsManager.java
+++ b/telephony/java/android/telephony/ImsManager.java
@@ -19,6 +19,7 @@ package android.telephony.ims;
import android.annotation.NonNull;
import android.annotation.SdkConstant;
import android.annotation.SuppressLint;
+import android.annotation.SystemApi;
import android.annotation.SystemService;
import android.content.Context;
import android.telephony.SubscriptionManager;
@@ -125,4 +126,24 @@ public class ImsManager {
return new ImsMmTelManager(subscriptionId);
}
+
+ /**
+ * Create an instance of SipDelegateManager for the subscription id specified.
+ * <p>
+ * Used for RCS single registration cases, where an IMS application needs to forward SIP
+ * traffic through the device's IMS service.
+ * @param subscriptionId The ID of the subscription that this SipDelegateManager will use.
+ * @throws IllegalArgumentException if the subscription is invalid.
+ * @return a SipDelegateManager instance for the specified subscription ID.
+ * @hide
+ */
+ @SystemApi
+ @NonNull
+ public SipDelegateManager getSipDelegateManager(int subscriptionId) {
+ if (!SubscriptionManager.isValidSubscriptionId(subscriptionId)) {
+ throw new IllegalArgumentException("Invalid subscription ID: " + subscriptionId);
+ }
+
+ return new SipDelegateManager(mContext, subscriptionId);
+ }
}
diff --git a/telephony/java/android/telephony/LteVopsSupportInfo.java b/telephony/java/android/telephony/LteVopsSupportInfo.java
index 7994c1b05977..83e41bf3df3b 100644
--- a/telephony/java/android/telephony/LteVopsSupportInfo.java
+++ b/telephony/java/android/telephony/LteVopsSupportInfo.java
@@ -20,7 +20,6 @@ import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.SystemApi;
-import android.annotation.TestApi;
import android.os.Parcel;
import android.os.Parcelable;
@@ -33,7 +32,6 @@ import java.util.Objects;
* @hide
*/
@SystemApi
-@TestApi
public final class LteVopsSupportInfo implements Parcelable {
/**@hide*/
diff --git a/telephony/java/android/telephony/ModemActivityInfo.java b/telephony/java/android/telephony/ModemActivityInfo.java
index 881d85c73b5d..e164c4bc2491 100644
--- a/telephony/java/android/telephony/ModemActivityInfo.java
+++ b/telephony/java/android/telephony/ModemActivityInfo.java
@@ -37,7 +37,6 @@ import java.util.Objects;
* @hide
*/
@SystemApi
-@TestApi
public final class ModemActivityInfo implements Parcelable {
private static final int TX_POWER_LEVELS = 5;
diff --git a/telephony/java/android/telephony/NetworkRegistrationInfo.java b/telephony/java/android/telephony/NetworkRegistrationInfo.java
index aee1e84ca356..92238420fd32 100644
--- a/telephony/java/android/telephony/NetworkRegistrationInfo.java
+++ b/telephony/java/android/telephony/NetworkRegistrationInfo.java
@@ -20,7 +20,6 @@ import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.SystemApi;
-import android.annotation.TestApi;
import android.os.Parcel;
import android.os.Parcelable;
import android.telephony.AccessNetworkConstants.TransportType;
@@ -71,37 +70,37 @@ public final class NetworkRegistrationInfo implements Parcelable {
* Not registered. The device is not currently searching a new operator to register.
* @hide
*/
- @SystemApi @TestApi
+ @SystemApi
public static final int REGISTRATION_STATE_NOT_REGISTERED_OR_SEARCHING = 0;
/**
* Registered on home network.
* @hide
*/
- @SystemApi @TestApi
+ @SystemApi
public static final int REGISTRATION_STATE_HOME = 1;
/**
* Not registered. The device is currently searching a new operator to register.
* @hide
*/
- @SystemApi @TestApi
+ @SystemApi
public static final int REGISTRATION_STATE_NOT_REGISTERED_SEARCHING = 2;
/**
* Registration denied.
* @hide
*/
- @SystemApi @TestApi
+ @SystemApi
public static final int REGISTRATION_STATE_DENIED = 3;
/**
* Registration state is unknown.
* @hide
*/
- @SystemApi @TestApi
+ @SystemApi
public static final int REGISTRATION_STATE_UNKNOWN = 4;
/**
* Registered on roaming network.
* @hide
*/
- @SystemApi @TestApi
+ @SystemApi
public static final int REGISTRATION_STATE_ROAMING = 5;
/** @hide */
@@ -386,7 +385,7 @@ public final class NetworkRegistrationInfo implements Parcelable {
*
* @hide
*/
- @SystemApi @TestApi
+ @SystemApi
public @RegistrationState int getRegistrationState() {
return mRegistrationState;
}
@@ -451,7 +450,7 @@ public final class NetworkRegistrationInfo implements Parcelable {
* @return the current network roaming type.
* @hide
*/
- @SystemApi @TestApi
+ @SystemApi
public @ServiceState.RoamingType int getRoamingType() {
return mRoamingType;
}
@@ -460,7 +459,7 @@ public final class NetworkRegistrationInfo implements Parcelable {
* @return Whether emergency is enabled.
* @hide
*/
- @SystemApi @TestApi
+ @SystemApi
public boolean isEmergencyEnabled() { return mEmergencyOnly; }
/**
@@ -498,7 +497,7 @@ public final class NetworkRegistrationInfo implements Parcelable {
* 10.5.3.6 for UMTS, 3GPP TS 24.301 9.9.3.9 for LTE, and 3GPP2 A.S0001 6.2.2.44 for CDMA
* @hide
*/
- @SystemApi @TestApi
+ @SystemApi
public int getRejectCause() {
return mRejectCause;
}
@@ -545,7 +544,7 @@ public final class NetworkRegistrationInfo implements Parcelable {
* @hide
*/
@Nullable
- @SystemApi @TestApi
+ @SystemApi
public DataSpecificRegistrationInfo getDataSpecificInfo() {
return mDataSpecificInfo;
}
@@ -680,7 +679,7 @@ public final class NetworkRegistrationInfo implements Parcelable {
* @hide
*/
@Override
- @SystemApi @TestApi
+ @SystemApi
public void writeToParcel(Parcel dest, int flags) {
dest.writeInt(mDomain);
dest.writeInt(mTransportType);
@@ -772,7 +771,7 @@ public final class NetworkRegistrationInfo implements Parcelable {
* </code></pre>
* @hide
*/
- @SystemApi @TestApi
+ @SystemApi
public static final class Builder {
@Domain
private int mDomain;
@@ -877,7 +876,7 @@ public final class NetworkRegistrationInfo implements Parcelable {
* @return The same instance of the builder.
* @hide
*/
- @SystemApi @TestApi
+ @SystemApi
public @NonNull Builder setEmergencyOnly(boolean emergencyOnly) {
mEmergencyOnly = emergencyOnly;
return this;
@@ -891,7 +890,7 @@ public final class NetworkRegistrationInfo implements Parcelable {
* @return The same instance of the builder.
* @hide
*/
- @SystemApi @TestApi
+ @SystemApi
public @NonNull Builder setAvailableServices(
@NonNull @ServiceType List<Integer> availableServices) {
mAvailableServices = availableServices;
@@ -906,7 +905,7 @@ public final class NetworkRegistrationInfo implements Parcelable {
* @return The same instance of the builder.
* @hide
*/
- @SystemApi @TestApi
+ @SystemApi
public @NonNull Builder setCellIdentity(@Nullable CellIdentity cellIdentity) {
mCellIdentity = cellIdentity;
return this;
@@ -929,7 +928,7 @@ public final class NetworkRegistrationInfo implements Parcelable {
* @return the NetworkRegistrationInfo object.
* @hide
*/
- @SystemApi @TestApi
+ @SystemApi
public @NonNull NetworkRegistrationInfo build() {
return new NetworkRegistrationInfo(mDomain, mTransportType, mRegistrationState,
mAccessNetworkTechnology, mRejectCause, mEmergencyOnly, mAvailableServices,
diff --git a/telephony/java/android/telephony/PhoneNumberUtils.java b/telephony/java/android/telephony/PhoneNumberUtils.java
index ec9940836afe..58e368bcc444 100644
--- a/telephony/java/android/telephony/PhoneNumberUtils.java
+++ b/telephony/java/android/telephony/PhoneNumberUtils.java
@@ -2239,7 +2239,6 @@ public class PhoneNumberUtils {
* @hide
*/
@SystemApi
- @TestApi
public static boolean isVoiceMailNumber(@NonNull Context context, int subId,
@Nullable String number) {
String vmNumber, mdn;
@@ -2728,7 +2727,6 @@ public class PhoneNumberUtils {
* @return true if number contains @
*/
@SystemApi
- @TestApi
public static boolean isUriNumber(@Nullable String number) {
// Note we allow either "@" or "%40" to indicate a URI, in case
// the passed-in string is URI-escaped. (Neither "@" nor "%40"
@@ -2747,7 +2745,6 @@ public class PhoneNumberUtils {
* @hide
*/
@SystemApi
- @TestApi
public static @NonNull String getUsernameFromUriNumber(@NonNull String number) {
// The delimiter between username and domain name can be
// either "@" or "%40" (the URI-escaped equivalent.)
diff --git a/telephony/java/android/telephony/SignalStrength.java b/telephony/java/android/telephony/SignalStrength.java
index 1376cddbc41f..7bd0bc0b69ce 100644
--- a/telephony/java/android/telephony/SignalStrength.java
+++ b/telephony/java/android/telephony/SignalStrength.java
@@ -287,11 +287,9 @@ public class SignalStrength implements Parcelable {
}
/**
- * Copy constructors
+ * This constructor is used to create a copy of an existing SignalStrength object.
*
* @param s Source SignalStrength
- *
- * @hide
*/
public SignalStrength(@NonNull SignalStrength s) {
copyFrom(s);
diff --git a/telephony/java/android/telephony/SubscriptionManager.java b/telephony/java/android/telephony/SubscriptionManager.java
index a71a965b1bdb..2e51ef16baf1 100644
--- a/telephony/java/android/telephony/SubscriptionManager.java
+++ b/telephony/java/android/telephony/SubscriptionManager.java
@@ -32,7 +32,6 @@ import android.annotation.SdkConstant.SdkConstantType;
import android.annotation.SuppressAutoDoc;
import android.annotation.SystemApi;
import android.annotation.SystemService;
-import android.annotation.TestApi;
import android.app.PendingIntent;
import android.app.PropertyInvalidatedCache;
import android.compat.annotation.UnsupportedAppUsage;
@@ -279,7 +278,6 @@ public class SubscriptionManager {
*/
@NonNull
@SystemApi
- @TestApi
public static final Uri WFC_ENABLED_CONTENT_URI = Uri.withAppendedPath(CONTENT_URI, "wfc");
/**
@@ -299,7 +297,6 @@ public class SubscriptionManager {
*/
@NonNull
@SystemApi
- @TestApi
public static final Uri ADVANCED_CALLING_ENABLED_CONTENT_URI = Uri.withAppendedPath(
CONTENT_URI, "advanced_calling");
@@ -318,7 +315,6 @@ public class SubscriptionManager {
*/
@NonNull
@SystemApi
- @TestApi
public static final Uri WFC_MODE_CONTENT_URI = Uri.withAppendedPath(CONTENT_URI, "wfc_mode");
/**
@@ -336,7 +332,6 @@ public class SubscriptionManager {
*/
@NonNull
@SystemApi
- @TestApi
public static final Uri WFC_ROAMING_MODE_CONTENT_URI = Uri.withAppendedPath(
CONTENT_URI, "wfc_roaming_mode");
@@ -356,7 +351,6 @@ public class SubscriptionManager {
*/
@NonNull
@SystemApi
- @TestApi
public static final Uri VT_ENABLED_CONTENT_URI = Uri.withAppendedPath(
CONTENT_URI, "vt_enabled");
@@ -375,7 +369,6 @@ public class SubscriptionManager {
*/
@NonNull
@SystemApi
- @TestApi
public static final Uri WFC_ROAMING_ENABLED_CONTENT_URI = Uri.withAppendedPath(
CONTENT_URI, "wfc_roaming_enabled");
@@ -1966,7 +1959,6 @@ public class SubscriptionManager {
* @hide
*/
@SystemApi
- @TestApi
@RequiresPermission(Manifest.permission.MODIFY_PHONE_STATE)
public void setDefaultVoiceSubscriptionId(int subscriptionId) {
if (VDBG) logd("setDefaultVoiceSubId sub id = " + subscriptionId);
diff --git a/telephony/java/android/telephony/TelephonyManager.java b/telephony/java/android/telephony/TelephonyManager.java
index a202644dfafe..9126387b27c5 100644
--- a/telephony/java/android/telephony/TelephonyManager.java
+++ b/telephony/java/android/telephony/TelephonyManager.java
@@ -2843,7 +2843,7 @@ public class TelephonyManager {
*/
@SystemApi(client = SystemApi.Client.MODULE_LIBRARIES)
public static @NonNull @NetworkType int[] getAllNetworkTypes() {
- return NETWORK_TYPES;
+ return NETWORK_TYPES.clone();
}
/**
@@ -5644,27 +5644,78 @@ public class TelephonyManager {
}
}
+ /** @hide */
+ @Retention(RetentionPolicy.SOURCE)
+ @IntDef(prefix = {"ERI_"}, value = {
+ ERI_ON,
+ ERI_OFF,
+ ERI_FLASH
+ })
+ public @interface EriIconIndex {}
+
/**
- * Get the CDMA ERI (Enhanced Roaming Indicator) information
+ * ERI (Enhanced Roaming Indicator) is ON i.e value 0 defined by
+ * 3GPP2 C.R1001-H v1.0 Table 8.1-1.
+ */
+ public static final int ERI_ON = 0;
+
+ /**
+ * ERI (Enhanced Roaming Indicator) is OFF i.e value 1 defined by
+ * 3GPP2 C.R1001-H v1.0 Table 8.1-1.
+ */
+ public static final int ERI_OFF = 1;
+
+ /**
+ * ERI (Enhanced Roaming Indicator) is FLASH i.e value 2 defined by
+ * 3GPP2 C.R1001-H v1.0 Table 8.1-1.
+ */
+ public static final int ERI_FLASH = 2;
+
+ /** @hide */
+ @Retention(RetentionPolicy.SOURCE)
+ @IntDef(prefix = {"ERI_ICON_MODE_"}, value = {
+ ERI_ICON_MODE_NORMAL,
+ ERI_ICON_MODE_FLASH
+ })
+ public @interface EriIconMode {}
+
+ /**
+ * ERI (Enhanced Roaming Indicator) icon mode is normal. This constant represents that
+ * the ERI icon should be displayed normally.
*
- * Returns {@link android.telephony#CdmaEriInformation}
+ * Note: ERI is defined 3GPP2 C.R1001-H Table 8.1-1
+ * @hide
+ */
+ public static final int ERI_ICON_MODE_NORMAL = 0;
+
+ /**
+ * ERI (Enhanced Roaming Indicator) icon mode flash. This constant represents that
+ * the ERI icon should be flashing.
*
+ * Note: ERI is defined 3GPP2 C.R1001-H Table 8.1-1
* @hide
*/
+ public static final int ERI_ICON_MODE_FLASH = 1;
+
+ /**
+ * Returns the CDMA ERI icon index to display. The number is assigned by
+ * 3GPP2 C.R1001-H v1.0 Table 8.1-1. Additionally carriers define their own ERI icon index.
+ * Defined values are {@link #ERI_ON}, {@link #ERI_OFF}, and {@link #ERI_FLASH}.
+ * @hide
+ */
+ @SystemApi
@RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
- @NonNull
- public CdmaEriInformation getCdmaEriInformation() {
- return new CdmaEriInformation(
- getCdmaEriIconIndex(getSubId()), getCdmaEriIconMode(getSubId()));
+ public @EriIconIndex int getCdmaEnhancedRoamingIndicatorIconIndex() {
+ return getCdmaEriIconIndex(getSubId());
}
/**
- * Returns the CDMA ERI icon index to display for a subscription
+ * Returns the CDMA ERI icon index to display for a subscription.
* @hide
*/
@RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
@UnsupportedAppUsage
- public int getCdmaEriIconIndex(int subId) {
+ public @EriIconIndex int getCdmaEriIconIndex(int subId) {
try {
ITelephony telephony = getITelephony();
if (telephony == null)
@@ -5688,7 +5739,7 @@ public class TelephonyManager {
*/
@RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
@UnsupportedAppUsage
- public int getCdmaEriIconMode(int subId) {
+ public @EriIconMode int getCdmaEriIconMode(int subId) {
try {
ITelephony telephony = getITelephony();
if (telephony == null)
@@ -8357,13 +8408,13 @@ public class TelephonyManager {
/**
* Values used to return status for hasCarrierPrivileges call.
*/
- /** @hide */ @SystemApi @TestApi
+ /** @hide */ @SystemApi
public static final int CARRIER_PRIVILEGE_STATUS_HAS_ACCESS = 1;
- /** @hide */ @SystemApi @TestApi
+ /** @hide */ @SystemApi
public static final int CARRIER_PRIVILEGE_STATUS_NO_ACCESS = 0;
- /** @hide */ @SystemApi @TestApi
+ /** @hide */ @SystemApi
public static final int CARRIER_PRIVILEGE_STATUS_RULES_NOT_LOADED = -1;
- /** @hide */ @SystemApi @TestApi
+ /** @hide */ @SystemApi
public static final int CARRIER_PRIVILEGE_STATUS_ERROR_LOADING_RULES = -2;
/**
@@ -8565,7 +8616,6 @@ public class TelephonyManager {
/** @hide */
@SystemApi
- @TestApi
@SuppressLint("Doclava125")
public int checkCarrierPrivilegesForPackage(String pkgName) {
try {
@@ -8598,7 +8648,6 @@ public class TelephonyManager {
/** @hide */
@SystemApi
- @TestApi
public List<String> getCarrierPackageNamesForIntent(Intent intent) {
return getCarrierPackageNamesForIntentAndPhone(intent, getPhoneId());
}
@@ -10100,7 +10149,6 @@ public class TelephonyManager {
* @hide
*/
@SystemApi
- @TestApi
@RequiresPermission(Manifest.permission.INTERACT_ACROSS_USERS)
public @Nullable ComponentName getAndUpdateDefaultRespondViaMessageApplication() {
return SmsApplication.getDefaultRespondViaMessageApplication(mContext, true);
@@ -10113,7 +10161,6 @@ public class TelephonyManager {
* @hide
*/
@SystemApi
- @TestApi
@RequiresPermission(Manifest.permission.INTERACT_ACROSS_USERS)
public @Nullable ComponentName getDefaultRespondViaMessageApplication() {
return SmsApplication.getDefaultRespondViaMessageApplication(mContext, false);
@@ -11861,7 +11908,6 @@ public class TelephonyManager {
*
* @hide
*/
- @TestApi
@SystemApi
public static final int INVALID_EMERGENCY_NUMBER_DB_VERSION = -1;
@@ -11901,7 +11947,6 @@ public class TelephonyManager {
*/
@RequiresPermission(android.Manifest.permission.READ_ACTIVE_EMERGENCY_SESSION)
@SystemApi
- @TestApi
public void updateOtaEmergencyNumberDbFilePath(
@NonNull ParcelFileDescriptor otaParcelFileDescriptor) {
try {
@@ -11927,7 +11972,6 @@ public class TelephonyManager {
*/
@RequiresPermission(android.Manifest.permission.READ_ACTIVE_EMERGENCY_SESSION)
@SystemApi
- @TestApi
public void resetOtaEmergencyNumberDbFilePath() {
try {
ITelephony telephony = getITelephony();
@@ -12149,7 +12193,6 @@ public class TelephonyManager {
*
* @hide
*/
- @TestApi
@SystemApi
@RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
public int getEmergencyNumberDbVersion() {
@@ -12877,7 +12920,6 @@ public class TelephonyManager {
* @hide
*/
@SystemApi
- @TestApi
@RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE)
public void setSystemSelectionChannels(@NonNull List<RadioAccessSpecifier> specifiers,
@NonNull @CallbackExecutor Executor executor,
@@ -12895,7 +12937,6 @@ public class TelephonyManager {
* @hide
*/
@SystemApi
- @TestApi
@RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE)
public void setSystemSelectionChannels(@NonNull List<RadioAccessSpecifier> specifiers) {
Objects.requireNonNull(specifiers, "Specifiers must not be null.");
@@ -13307,7 +13348,6 @@ public class TelephonyManager {
* @hide
*/
@SystemApi
- @TestApi
public static final int MOBILE_DATA_POLICY_DATA_ON_NON_DEFAULT_DURING_VOICE_CALL = 1;
/**
@@ -13322,7 +13362,6 @@ public class TelephonyManager {
* @hide
*/
@SystemApi
- @TestApi
public static final int MOBILE_DATA_POLICY_MMS_ALWAYS_ALLOWED = 2;
/**
@@ -13346,7 +13385,6 @@ public class TelephonyManager {
* @hide
*/
@SystemApi
- @TestApi
@RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE)
public void setMobileDataPolicyEnabledStatus(@MobileDataPolicy int policy, boolean enabled) {
try {
@@ -13370,7 +13408,6 @@ public class TelephonyManager {
* @hide
*/
@SystemApi
- @TestApi
@RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
public boolean isMobileDataPolicyEnabled(@MobileDataPolicy int policy) {
try {
diff --git a/telephony/java/android/telephony/ims/ImsCallForwardInfo.java b/telephony/java/android/telephony/ims/ImsCallForwardInfo.java
index d53a2e6591a2..3f9c8d26ca91 100644
--- a/telephony/java/android/telephony/ims/ImsCallForwardInfo.java
+++ b/telephony/java/android/telephony/ims/ImsCallForwardInfo.java
@@ -19,7 +19,6 @@ package android.telephony.ims;
import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.SystemApi;
-import android.annotation.TestApi;
import android.compat.annotation.UnsupportedAppUsage;
import android.os.Parcel;
import android.os.Parcelable;
@@ -33,7 +32,6 @@ import java.lang.annotation.RetentionPolicy;
* @hide
*/
@SystemApi
-@TestApi
public final class ImsCallForwardInfo implements Parcelable {
/**
diff --git a/telephony/java/android/telephony/ims/ImsCallProfile.java b/telephony/java/android/telephony/ims/ImsCallProfile.java
index f31fcf4050ea..47a0ab61f970 100644
--- a/telephony/java/android/telephony/ims/ImsCallProfile.java
+++ b/telephony/java/android/telephony/ims/ImsCallProfile.java
@@ -48,7 +48,6 @@ import java.util.List;
* @hide
*/
@SystemApi
-@TestApi
public final class ImsCallProfile implements Parcelable {
private static final String TAG = "ImsCallProfile";
diff --git a/telephony/java/android/telephony/ims/ImsCallSessionListener.java b/telephony/java/android/telephony/ims/ImsCallSessionListener.java
index d21a05103241..2fdd195bbb26 100644
--- a/telephony/java/android/telephony/ims/ImsCallSessionListener.java
+++ b/telephony/java/android/telephony/ims/ImsCallSessionListener.java
@@ -19,7 +19,6 @@ package android.telephony.ims;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.SystemApi;
-import android.annotation.TestApi;
import android.os.RemoteException;
import android.telephony.Annotation;
import android.telephony.CallQuality;
@@ -40,7 +39,6 @@ import com.android.ims.internal.IImsCallSession;
// TODO: APIs in here do not conform to API guidelines yet. This can be changed if
// ImsCallSessionListenerConverter is also changed.
@SystemApi
-@TestApi
public class ImsCallSessionListener {
private final IImsCallSessionListener mListener;
diff --git a/telephony/java/android/telephony/ims/ImsConferenceState.java b/telephony/java/android/telephony/ims/ImsConferenceState.java
index 9bf2f44395c4..1fa5f52968e5 100644
--- a/telephony/java/android/telephony/ims/ImsConferenceState.java
+++ b/telephony/java/android/telephony/ims/ImsConferenceState.java
@@ -18,7 +18,6 @@ package android.telephony.ims;
import android.annotation.NonNull;
import android.annotation.SystemApi;
-import android.annotation.TestApi;
import android.os.Bundle;
import android.os.Parcel;
import android.os.Parcelable;
@@ -38,7 +37,6 @@ import java.util.Set;
* @hide
*/
@SystemApi
-@TestApi
public final class ImsConferenceState implements Parcelable {
private static final String TAG = "ImsConferenceState";
/**
diff --git a/telephony/java/android/telephony/ims/ImsException.java b/telephony/java/android/telephony/ims/ImsException.java
index 1c3d58d98b4a..50fb828ea217 100644
--- a/telephony/java/android/telephony/ims/ImsException.java
+++ b/telephony/java/android/telephony/ims/ImsException.java
@@ -19,7 +19,6 @@ package android.telephony.ims;
import android.annotation.IntDef;
import android.annotation.Nullable;
import android.annotation.SystemApi;
-import android.annotation.TestApi;
import android.content.pm.PackageManager;
import android.telephony.SubscriptionManager;
import android.text.TextUtils;
@@ -83,7 +82,6 @@ public final class ImsException extends Exception {
* @hide
*/
@SystemApi
- @TestApi
public ImsException(@Nullable String message) {
super(getMessage(message, CODE_ERROR_UNSPECIFIED));
}
@@ -94,7 +92,6 @@ public final class ImsException extends Exception {
* @hide
*/
@SystemApi
- @TestApi
public ImsException(@Nullable String message, @ImsErrorCode int code) {
super(getMessage(message, code));
mCode = code;
@@ -108,7 +105,6 @@ public final class ImsException extends Exception {
* @hide
*/
@SystemApi
- @TestApi
public ImsException(@Nullable String message, @ImsErrorCode int code,
@Nullable Throwable cause) {
super(getMessage(message, code), cause);
diff --git a/telephony/java/android/telephony/ims/ImsExternalCallState.java b/telephony/java/android/telephony/ims/ImsExternalCallState.java
index 7d73165d4540..fdf636c323b6 100644
--- a/telephony/java/android/telephony/ims/ImsExternalCallState.java
+++ b/telephony/java/android/telephony/ims/ImsExternalCallState.java
@@ -20,7 +20,6 @@ import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.SystemApi;
-import android.annotation.TestApi;
import android.net.Uri;
import android.os.Parcel;
import android.os.Parcelable;
@@ -35,7 +34,6 @@ import java.lang.annotation.RetentionPolicy;
* @hide
*/
@SystemApi
-@TestApi
public final class ImsExternalCallState implements Parcelable {
private static final String TAG = "ImsExternalCallState";
diff --git a/telephony/java/android/telephony/ims/ImsMmTelManager.java b/telephony/java/android/telephony/ims/ImsMmTelManager.java
index 3a0e49e204cb..76c1fafe05fb 100644
--- a/telephony/java/android/telephony/ims/ImsMmTelManager.java
+++ b/telephony/java/android/telephony/ims/ImsMmTelManager.java
@@ -25,7 +25,6 @@ import android.annotation.RequiresPermission;
import android.annotation.SuppressAutoDoc;
import android.annotation.SuppressLint;
import android.annotation.SystemApi;
-import android.annotation.TestApi;
import android.os.Binder;
import android.os.RemoteException;
import android.os.ServiceSpecificException;
@@ -97,7 +96,7 @@ public class ImsMmTelManager implements RegistrationManager {
*/
// Do not add to this class, add to RegistrationManager.RegistrationCallback instead.
@Deprecated
- @SystemApi @TestApi
+ @SystemApi
public static class RegistrationCallback extends RegistrationManager.RegistrationCallback {
/**
@@ -231,7 +230,6 @@ public class ImsMmTelManager implements RegistrationManager {
* @hide
*/
@SystemApi
- @TestApi
@Deprecated
@SuppressAutoDoc // No support for device / profile owner or carrier privileges (b/72967236).
@RequiresPermission(anyOf = {
@@ -280,7 +278,7 @@ public class ImsMmTelManager implements RegistrationManager {
* @hide
*/
@Deprecated
- @SystemApi @TestApi
+ @SystemApi
@RequiresPermission(Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
public void registerImsRegistrationCallback(@NonNull @CallbackExecutor Executor executor,
@NonNull RegistrationCallback c) throws ImsException {
@@ -366,7 +364,7 @@ public class ImsMmTelManager implements RegistrationManager {
* @hide
*/
@Deprecated
- @SystemApi @TestApi
+ @SystemApi
@RequiresPermission(Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
public void unregisterImsRegistrationCallback(@NonNull RegistrationCallback c) {
if (c == null) {
@@ -422,7 +420,7 @@ public class ImsMmTelManager implements RegistrationManager {
* @hide
*/
@Override
- @SystemApi @TestApi
+ @SystemApi
@RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
public void getRegistrationState(@NonNull @CallbackExecutor Executor executor,
@NonNull @ImsRegistrationState Consumer<Integer> stateCallback) {
@@ -681,7 +679,7 @@ public class ImsMmTelManager implements RegistrationManager {
* @hide
*/
@RequiresPermission(Manifest.permission.MODIFY_PHONE_STATE)
- @SystemApi @TestApi
+ @SystemApi
public void setAdvancedCallingSettingEnabled(boolean isEnabled) {
ITelephony iTelephony = getITelephony();
if (iTelephony == null) {
@@ -725,7 +723,7 @@ public class ImsMmTelManager implements RegistrationManager {
* @hide
*/
@RequiresPermission(Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
- @SystemApi @TestApi
+ @SystemApi
public boolean isCapable(@MmTelFeature.MmTelCapabilities.MmTelCapability int capability,
@ImsRegistrationImplBase.ImsRegistrationTech int imsRegTech) {
ITelephony iTelephony = getITelephony();
@@ -758,7 +756,7 @@ public class ImsMmTelManager implements RegistrationManager {
* otherwise.
* @hide
*/
- @SystemApi @TestApi
+ @SystemApi
@RequiresPermission(Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
public boolean isAvailable(@MmTelFeature.MmTelCapabilities.MmTelCapability int capability,
@ImsRegistrationImplBase.ImsRegistrationTech int imsRegTech) {
@@ -790,7 +788,7 @@ public class ImsMmTelManager implements RegistrationManager {
* available.
* @hide
*/
- @SystemApi @TestApi
+ @SystemApi
@RequiresPermission(Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
public void isSupported(@MmTelFeature.MmTelCapabilities.MmTelCapability int capability,
@AccessNetworkConstants.TransportType int transportType,
@@ -879,7 +877,7 @@ public class ImsMmTelManager implements RegistrationManager {
* @see #isVtSettingEnabled()
* @hide
*/
- @SystemApi @TestApi
+ @SystemApi
@RequiresPermission(Manifest.permission.MODIFY_PHONE_STATE)
public void setVtSettingEnabled(boolean isEnabled) {
ITelephony iTelephony = getITelephony();
@@ -954,7 +952,7 @@ public class ImsMmTelManager implements RegistrationManager {
* @see #isVoWiFiSettingEnabled()
* @hide
*/
- @SystemApi @TestApi
+ @SystemApi
@RequiresPermission(Manifest.permission.MODIFY_PHONE_STATE)
public void setVoWiFiSettingEnabled(boolean isEnabled) {
ITelephony iTelephony = getITelephony();
@@ -1032,7 +1030,7 @@ public class ImsMmTelManager implements RegistrationManager {
* @see #isVoWiFiRoamingSettingEnabled()
* @hide
*/
- @SystemApi @TestApi
+ @SystemApi
@RequiresPermission(Manifest.permission.MODIFY_PHONE_STATE)
public void setVoWiFiRoamingSettingEnabled(boolean isEnabled) {
ITelephony iTelephony = getITelephony();
@@ -1069,7 +1067,7 @@ public class ImsMmTelManager implements RegistrationManager {
* @see #setVoWiFiSettingEnabled(boolean)
* @hide
*/
- @SystemApi @TestApi
+ @SystemApi
@RequiresPermission(Manifest.permission.MODIFY_PHONE_STATE)
public void setVoWiFiNonPersistent(boolean isCapable, int mode) {
ITelephony iTelephony = getITelephony();
@@ -1152,7 +1150,7 @@ public class ImsMmTelManager implements RegistrationManager {
* @see #getVoWiFiModeSetting()
* @hide
*/
- @SystemApi @TestApi
+ @SystemApi
@RequiresPermission(Manifest.permission.MODIFY_PHONE_STATE)
public void setVoWiFiModeSetting(@WiFiCallingMode int mode) {
ITelephony iTelephony = getITelephony();
@@ -1188,7 +1186,7 @@ public class ImsMmTelManager implements RegistrationManager {
* @see #setVoWiFiRoamingSettingEnabled(boolean)
* @hide
*/
- @SystemApi @TestApi
+ @SystemApi
@RequiresPermission(Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
public @WiFiCallingMode int getVoWiFiRoamingModeSetting() {
ITelephony iTelephony = getITelephony();
@@ -1224,7 +1222,7 @@ public class ImsMmTelManager implements RegistrationManager {
* @see #getVoWiFiRoamingModeSetting()
* @hide
*/
- @SystemApi @TestApi
+ @SystemApi
@RequiresPermission(Manifest.permission.MODIFY_PHONE_STATE)
public void setVoWiFiRoamingModeSetting(@WiFiCallingMode int mode) {
ITelephony iTelephony = getITelephony();
@@ -1258,7 +1256,7 @@ public class ImsMmTelManager implements RegistrationManager {
* @param isEnabled if true RTT should be enabled during calls made on this subscription.
* @hide
*/
- @SystemApi @TestApi
+ @SystemApi
@RequiresPermission(Manifest.permission.MODIFY_PHONE_STATE)
public void setRttCapabilitySetting(boolean isEnabled) {
ITelephony iTelephony = getITelephony();
@@ -1338,7 +1336,7 @@ public class ImsMmTelManager implements RegistrationManager {
* the IMS service is not available.
* @hide
*/
- @SystemApi @TestApi
+ @SystemApi
@RequiresPermission(Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
public void getFeatureState(@NonNull @CallbackExecutor Executor executor,
@NonNull @ImsFeature.ImsState Consumer<Integer> callback) throws ImsException {
diff --git a/telephony/java/android/telephony/ims/ImsService.java b/telephony/java/android/telephony/ims/ImsService.java
index 90a6de7b66a3..9ab5aeb9c34c 100644
--- a/telephony/java/android/telephony/ims/ImsService.java
+++ b/telephony/java/android/telephony/ims/ImsService.java
@@ -18,8 +18,8 @@ package android.telephony.ims;
import android.annotation.LongDef;
import android.annotation.Nullable;
+import android.annotation.SuppressLint;
import android.annotation.SystemApi;
-import android.annotation.TestApi;
import android.app.Service;
import android.content.Intent;
import android.os.IBinder;
@@ -101,7 +101,6 @@ import java.util.Map;
* @hide
*/
@SystemApi
-@TestApi
public class ImsService extends Service {
private static final String LOG_TAG = "ImsService";
@@ -127,7 +126,6 @@ public class ImsService extends Service {
* {@link #getImsServiceCapabilities()}, {@link #getSipTransport(int)} must not return null, and
* this ImsService MUST report the ability to create both {@link ImsFeature#FEATURE_MMTEL} and
* {@link ImsFeature#FEATURE_RCS} features.
- * @hide
*/
public static final long CAPABILITY_SIP_DELEGATE_CREATION = 1 << 1;
@@ -425,9 +423,12 @@ public class ImsService extends Service {
* <p>
* This should be a static configuration and should not change at runtime.
* @return The optional static capabilities of this ImsService implementation.
- * @hide
*/
+ // ImsService follows a different convention, since it is a stub class. The on* methods are
+ // final and call back into the framework with a state update.
+ @SuppressLint("OnNameExpected")
public @ImsServiceCapability long getImsServiceCapabilities() {
+ // Stub implementation to be implemented by ImsService.
return 0L;
}
@@ -515,9 +516,12 @@ public class ImsService extends Service {
* supported for this ImsService.
* @param slotId The slot that is associated with the SipTransport implementation.
* @return the SipTransport implementation for the specified slot.
- * @hide Keep this hidden until there is something to expose in SipTransport.
*/
+ // ImsService follows a different convention, since it is a stub class. The on* methods are
+ // final and call back into the framework with a state update.
+ @SuppressLint("OnNameExpected")
public @Nullable SipTransportImplBase getSipTransport(int slotId) {
+ // Stub implementation for ImsServices that do not support SipTransport.
return null;
}
@@ -558,4 +562,4 @@ public class ImsService extends Service {
result.append("}");
return result.toString();
}
-} \ No newline at end of file
+}
diff --git a/telephony/java/android/telephony/ims/ImsSsData.java b/telephony/java/android/telephony/ims/ImsSsData.java
index 70bf0c57366d..fb8e5d37875b 100644
--- a/telephony/java/android/telephony/ims/ImsSsData.java
+++ b/telephony/java/android/telephony/ims/ImsSsData.java
@@ -19,7 +19,6 @@ import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.SystemApi;
-import android.annotation.TestApi;
import android.os.Parcel;
import android.os.Parcelable;
@@ -37,7 +36,6 @@ import java.util.List;
* {@hide}
*/
@SystemApi
-@TestApi
public final class ImsSsData implements Parcelable {
private static final String TAG = ImsSsData.class.getCanonicalName();
diff --git a/telephony/java/android/telephony/ims/ImsSsInfo.java b/telephony/java/android/telephony/ims/ImsSsInfo.java
index 9cce95fc67f8..27b56b8c5b47 100644
--- a/telephony/java/android/telephony/ims/ImsSsInfo.java
+++ b/telephony/java/android/telephony/ims/ImsSsInfo.java
@@ -20,7 +20,6 @@ import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.SystemApi;
-import android.annotation.TestApi;
import android.compat.annotation.UnsupportedAppUsage;
import android.os.Parcel;
import android.os.Parcelable;
@@ -38,7 +37,6 @@ import java.lang.annotation.RetentionPolicy;
* @hide
*/
@SystemApi
-@TestApi
public final class ImsSsInfo implements Parcelable {
/**@hide*/
diff --git a/telephony/java/android/telephony/ims/ImsStreamMediaProfile.java b/telephony/java/android/telephony/ims/ImsStreamMediaProfile.java
index b70fd649ab79..131cb1a505fb 100644
--- a/telephony/java/android/telephony/ims/ImsStreamMediaProfile.java
+++ b/telephony/java/android/telephony/ims/ImsStreamMediaProfile.java
@@ -18,7 +18,6 @@ package android.telephony.ims;
import android.annotation.NonNull;
import android.annotation.SystemApi;
-import android.annotation.TestApi;
import android.compat.annotation.UnsupportedAppUsage;
import android.os.Parcel;
import android.os.Parcelable;
@@ -30,7 +29,6 @@ import android.os.Parcelable;
* @hide
*/
@SystemApi
-@TestApi
public final class ImsStreamMediaProfile implements Parcelable {
private static final String TAG = "ImsStreamMediaProfile";
diff --git a/telephony/java/android/telephony/ims/ImsSuppServiceNotification.java b/telephony/java/android/telephony/ims/ImsSuppServiceNotification.java
index f67f68e2e425..16303685d0a3 100644
--- a/telephony/java/android/telephony/ims/ImsSuppServiceNotification.java
+++ b/telephony/java/android/telephony/ims/ImsSuppServiceNotification.java
@@ -19,7 +19,6 @@ package android.telephony.ims;
import android.annotation.NonNull;
import android.annotation.SystemApi;
-import android.annotation.TestApi;
import android.os.Parcel;
import android.os.Parcelable;
@@ -32,7 +31,6 @@ import java.util.Arrays;
* @hide
*/
@SystemApi
-@TestApi
public final class ImsSuppServiceNotification implements Parcelable {
private static final String TAG = "ImsSuppServiceNotification";
diff --git a/telephony/java/android/telephony/ims/ImsUtListener.java b/telephony/java/android/telephony/ims/ImsUtListener.java
index 460a032ce7e0..baa0576cdf13 100644
--- a/telephony/java/android/telephony/ims/ImsUtListener.java
+++ b/telephony/java/android/telephony/ims/ImsUtListener.java
@@ -18,7 +18,6 @@ package android.telephony.ims;
import android.annotation.NonNull;
import android.annotation.SystemApi;
-import android.annotation.TestApi;
import android.os.Bundle;
import android.os.RemoteException;
import android.telephony.ims.stub.ImsUtImplBase;
@@ -34,7 +33,6 @@ import com.android.ims.internal.IImsUtListener;
// DO NOT remove or change the existing APIs, only add new ones to this Base implementation or you
// will break other implementations of ImsUt maintained by other ImsServices.
@SystemApi
-@TestApi
public class ImsUtListener {
/**
diff --git a/telephony/java/android/telephony/ims/ImsVideoCallProvider.java b/telephony/java/android/telephony/ims/ImsVideoCallProvider.java
index 569c6d5a4e4d..2fca4096f447 100644
--- a/telephony/java/android/telephony/ims/ImsVideoCallProvider.java
+++ b/telephony/java/android/telephony/ims/ImsVideoCallProvider.java
@@ -17,14 +17,12 @@
package android.telephony.ims;
import android.annotation.SystemApi;
-import android.annotation.TestApi;
import android.compat.annotation.UnsupportedAppUsage;
import android.net.Uri;
import android.os.Handler;
import android.os.Looper;
import android.os.Message;
import android.os.RemoteException;
-import android.telecom.Connection;
import android.telecom.VideoProfile;
import android.telecom.VideoProfile.CameraCapabilities;
import android.view.Surface;
@@ -37,7 +35,6 @@ import com.android.internal.os.SomeArgs;
* @hide
*/
@SystemApi
-@TestApi
public abstract class ImsVideoCallProvider {
private static final int MSG_SET_CALLBACK = 1;
private static final int MSG_SET_CAMERA = 2;
diff --git a/telephony/java/android/telephony/ims/ProvisioningManager.java b/telephony/java/android/telephony/ims/ProvisioningManager.java
index 3affdf64aae7..24ae979bb08d 100644
--- a/telephony/java/android/telephony/ims/ProvisioningManager.java
+++ b/telephony/java/android/telephony/ims/ProvisioningManager.java
@@ -23,7 +23,6 @@ import android.annotation.Nullable;
import android.annotation.RequiresPermission;
import android.annotation.StringDef;
import android.annotation.SystemApi;
-import android.annotation.TestApi;
import android.annotation.WorkerThread;
import android.os.Binder;
import android.os.RemoteException;
@@ -59,7 +58,6 @@ import java.util.concurrent.Executor;
* @hide
*/
@SystemApi
-@TestApi
public class ProvisioningManager {
/**@hide*/
diff --git a/telephony/java/android/telephony/ims/RcsUceAdapter.java b/telephony/java/android/telephony/ims/RcsUceAdapter.java
index 4606f7d625aa..c2ddcea3dbd3 100644
--- a/telephony/java/android/telephony/ims/RcsUceAdapter.java
+++ b/telephony/java/android/telephony/ims/RcsUceAdapter.java
@@ -22,7 +22,6 @@ import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.RequiresPermission;
import android.annotation.SystemApi;
-import android.annotation.TestApi;
import android.content.Context;
import android.net.Uri;
import android.os.Binder;
@@ -519,7 +518,6 @@ public class RcsUceAdapter {
* @hide
*/
@SystemApi
- @TestApi
@RequiresPermission(Manifest.permission.MODIFY_PHONE_STATE)
public void setUceSettingEnabled(boolean isEnabled) throws ImsException {
IImsRcsController imsRcsController = getIImsRcsController();
diff --git a/telephony/java/android/telephony/ims/SipDelegateManager.java b/telephony/java/android/telephony/ims/SipDelegateManager.java
new file mode 100644
index 000000000000..82c8a9cd58f4
--- /dev/null
+++ b/telephony/java/android/telephony/ims/SipDelegateManager.java
@@ -0,0 +1,93 @@
+/*
+ * 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 android.telephony.ims;
+
+import android.Manifest;
+import android.annotation.RequiresPermission;
+import android.annotation.SystemApi;
+import android.content.Context;
+import android.os.IBinder;
+import android.os.RemoteException;
+import android.os.ServiceSpecificException;
+import android.telephony.CarrierConfigManager;
+import android.telephony.TelephonyFrameworkInitializer;
+import android.telephony.ims.aidl.IImsRcsController;
+
+import com.android.internal.annotations.VisibleForTesting;
+
+/**
+ * Manages the creation and destruction of SipDelegates, which allow an IMS application to forward
+ * SIP messages for the purposes of providing a single IMS registration to the carrier's IMS network
+ * from multiple sources.
+ * @hide
+ */
+@SystemApi
+public class SipDelegateManager {
+
+ private final Context mContext;
+ private final int mSubId;
+
+ /**
+ * Only visible for testing. To instantiate an instance of this class, please use
+ * {@link ImsManager#getSipDelegateManager(int)}.
+ * @hide
+ */
+ @VisibleForTesting
+ public SipDelegateManager(Context context, int subId) {
+ mContext = context;
+ mSubId = subId;
+ }
+
+ /**
+ * Determines if creating SIP delegates are supported for the subscription specified.
+ * <p>
+ * If SIP delegates are not supported on this device or the carrier associated with this
+ * subscription, creating a SIP delegate will always fail, as this feature is not supported.
+ * @return true if this device supports creating a SIP delegate and the carrier associated with
+ * this subscription supports single registration, false if creating SIP delegates is not
+ * supported.
+ * @throws ImsException If the remote ImsService is not available for any reason or the
+ * subscription associated with this instance is no longer active. See
+ * {@link ImsException#getCode()} for more information.
+ *
+ * @see CarrierConfigManager.Ims#KEY_IMS_SINGLE_REGISTRATION_REQUIRED_BOOL
+ */
+ @RequiresPermission(Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
+ public boolean isSupported() throws ImsException {
+ try {
+ IImsRcsController controller = getIImsRcsController();
+ if (controller == null) {
+ throw new ImsException("Telephony server is down",
+ ImsException.CODE_ERROR_SERVICE_UNAVAILABLE);
+ }
+ return controller.isSipDelegateSupported(mSubId);
+ } catch (ServiceSpecificException e) {
+ throw new ImsException(e.getMessage(), e.errorCode);
+ } catch (RemoteException e) {
+ throw new ImsException(e.getMessage(),
+ ImsException.CODE_ERROR_SERVICE_UNAVAILABLE);
+ }
+ }
+
+ private IImsRcsController getIImsRcsController() {
+ IBinder binder = TelephonyFrameworkInitializer
+ .getTelephonyServiceManager()
+ .getTelephonyImsServiceRegisterer()
+ .get();
+ return IImsRcsController.Stub.asInterface(binder);
+ }
+}
diff --git a/telephony/java/android/telephony/ims/aidl/IImsRcsController.aidl b/telephony/java/android/telephony/ims/aidl/IImsRcsController.aidl
index e01ea9179452..6d25a09e079f 100644
--- a/telephony/java/android/telephony/ims/aidl/IImsRcsController.aidl
+++ b/telephony/java/android/telephony/ims/aidl/IImsRcsController.aidl
@@ -53,6 +53,9 @@ interface IImsRcsController {
void registerUcePublishStateCallback(int subId, IRcsUcePublishStateCallback c);
void unregisterUcePublishStateCallback(int subId, IRcsUcePublishStateCallback c);
+ // SipDelegateManager
+ boolean isSipDelegateSupported(int subId);
+
// Internal commands that should not be made public
void registerRcsFeatureCallback(int slotId, in IImsServiceFeatureCallback callback);
void unregisterImsFeatureCallback(in IImsServiceFeatureCallback callback);
diff --git a/telephony/java/android/telephony/ims/feature/CapabilityChangeRequest.java b/telephony/java/android/telephony/ims/feature/CapabilityChangeRequest.java
index 1918bcb00733..87a5094a95f3 100644
--- a/telephony/java/android/telephony/ims/feature/CapabilityChangeRequest.java
+++ b/telephony/java/android/telephony/ims/feature/CapabilityChangeRequest.java
@@ -18,7 +18,6 @@ package android.telephony.ims.feature;
import android.annotation.NonNull;
import android.annotation.SystemApi;
-import android.annotation.TestApi;
import android.os.Parcel;
import android.os.Parcelable;
import android.telephony.ims.stub.ImsRegistrationImplBase;
@@ -34,7 +33,6 @@ import java.util.Set;
* {@hide}
*/
@SystemApi
-@TestApi
public final class CapabilityChangeRequest implements Parcelable {
/**
diff --git a/telephony/java/android/telephony/ims/feature/ImsFeature.java b/telephony/java/android/telephony/ims/feature/ImsFeature.java
index e5779b315c93..b0a7b62c88ab 100644
--- a/telephony/java/android/telephony/ims/feature/ImsFeature.java
+++ b/telephony/java/android/telephony/ims/feature/ImsFeature.java
@@ -44,7 +44,6 @@ import java.util.Map;
* @hide
*/
@SystemApi
-@TestApi
public abstract class ImsFeature {
private static final String LOG_TAG = "ImsFeature";
@@ -62,19 +61,19 @@ public abstract class ImsFeature {
* CSFB for emergency calling.
* @hide
*/
- @SystemApi @TestApi
+ @SystemApi
public static final int FEATURE_EMERGENCY_MMTEL = 0;
/**
* This feature supports the MMTEL feature.
* @hide
*/
- @SystemApi @TestApi
+ @SystemApi
public static final int FEATURE_MMTEL = 1;
/**
* This feature supports the RCS feature.
* @hide
*/
- @SystemApi @TestApi
+ @SystemApi
public static final int FEATURE_RCS = 2;
/**
* Total number of features defined
@@ -124,7 +123,7 @@ public abstract class ImsFeature {
* during this time will result in an {@link IllegalStateException}.
* @hide
*/
- @SystemApi @TestApi
+ @SystemApi
public static final int STATE_UNAVAILABLE = 0;
/**
* This {@link ImsFeature} state is initializing and should not be communicated with. This will
@@ -132,14 +131,14 @@ public abstract class ImsFeature {
* during this time will result in an {@link IllegalStateException}.
* @hide
*/
- @SystemApi @TestApi
+ @SystemApi
public static final int STATE_INITIALIZING = 1;
/**
* This {@link ImsFeature} is ready for communication. Do not attempt to call framework methods
* until {@see #onFeatureReady()} is called.
* @hide
*/
- @SystemApi @TestApi
+ @SystemApi
public static final int STATE_READY = 2;
/**
@@ -169,13 +168,13 @@ public abstract class ImsFeature {
* The capability was unable to be changed.
* @hide
*/
- @SystemApi @TestApi
+ @SystemApi
public static final int CAPABILITY_ERROR_GENERIC = -1;
/**
* The capability was able to be changed.
* @hide
*/
- @SystemApi @TestApi
+ @SystemApi
public static final int CAPABILITY_SUCCESS = 0;
/**
@@ -349,7 +348,7 @@ public abstract class ImsFeature {
* subscription IDs associated with this slot.
* @hide
*/
- @SystemApi @TestApi
+ @SystemApi
public final int getSlotIndex() {
return mSlotId;
}
@@ -359,7 +358,7 @@ public abstract class ImsFeature {
* or {@link #STATE_UNAVAILABLE} if it has not been updated yet.
* @hide
*/
- @SystemApi @TestApi
+ @SystemApi
public @ImsState int getFeatureState() {
synchronized (mLock) {
return mState;
@@ -373,7 +372,7 @@ public abstract class ImsFeature {
* {@link #STATE_INITIALIZING}, or {@link #STATE_READY}.
* @hide
*/
- @SystemApi @TestApi
+ @SystemApi
public final void setFeatureState(@ImsState int state) {
synchronized (mLock) {
if (mState != state) {
diff --git a/telephony/java/android/telephony/ims/feature/MmTelFeature.java b/telephony/java/android/telephony/ims/feature/MmTelFeature.java
index d8a10ebb7bde..508d1a79d27e 100644
--- a/telephony/java/android/telephony/ims/feature/MmTelFeature.java
+++ b/telephony/java/android/telephony/ims/feature/MmTelFeature.java
@@ -20,7 +20,6 @@ import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.SystemApi;
-import android.annotation.TestApi;
import android.os.Bundle;
import android.os.Message;
import android.os.RemoteException;
@@ -60,7 +59,7 @@ public class MmTelFeature extends ImsFeature {
/**
* @hide
*/
- @SystemApi @TestApi
+ @SystemApi
public MmTelFeature() {
}
@@ -228,7 +227,7 @@ public class MmTelFeature extends ImsFeature {
* @see #removeCapabilities(int)
* @hide
*/
- @SystemApi @TestApi
+ @SystemApi
public MmTelCapabilities() {
super();
}
@@ -237,7 +236,7 @@ public class MmTelFeature extends ImsFeature {
* @hide
*/
@Deprecated
- @SystemApi @TestApi
+ @SystemApi
public MmTelCapabilities(Capabilities c) {
mCapabilities = c.mCapabilities;
}
@@ -248,7 +247,7 @@ public class MmTelFeature extends ImsFeature {
* bitfield.
* @hide
*/
- @SystemApi @TestApi
+ @SystemApi
public MmTelCapabilities(@MmTelCapability int capabilities) {
super(capabilities);
}
@@ -288,7 +287,7 @@ public class MmTelFeature extends ImsFeature {
* @hide
*/
@Override
- @SystemApi @TestApi
+ @SystemApi
public final void addCapabilities(@MmTelCapability int capabilities) {
super.addCapabilities(capabilities);
}
@@ -297,7 +296,7 @@ public class MmTelFeature extends ImsFeature {
* @hide
*/
@Override
- @SystemApi @TestApi
+ @SystemApi
public final void removeCapabilities(@MmTelCapability int capability) {
super.removeCapabilities(capability);
}
@@ -375,14 +374,14 @@ public class MmTelFeature extends ImsFeature {
* outgoing call as IMS.
* @hide
*/
- @SystemApi @TestApi
+ @SystemApi
public static final int PROCESS_CALL_IMS = 0;
/**
* To be returned by {@link #shouldProcessCall(String[])} when the telephony framework should
* not process the outgoing call as IMS and should instead use circuit switch.
* @hide
*/
- @SystemApi @TestApi
+ @SystemApi
public static final int PROCESS_CALL_CSFB = 1;
/** @hide */
@@ -400,7 +399,7 @@ public class MmTelFeature extends ImsFeature {
* This is an optional boolean flag.
* @hide
*/
- @SystemApi @TestApi
+ @SystemApi
public static final String EXTRA_IS_USSD = "android.telephony.ims.feature.extra.IS_USSD";
/**
@@ -413,7 +412,7 @@ public class MmTelFeature extends ImsFeature {
* This is an optional boolean flag.
* @hide
*/
- @SystemApi @TestApi
+ @SystemApi
public static final String EXTRA_IS_UNKNOWN_CALL =
"android.telephony.ims.feature.extra.IS_UNKNOWN_CALL";
@@ -453,7 +452,7 @@ public class MmTelFeature extends ImsFeature {
* @hide
*/
@Override
- @SystemApi @TestApi
+ @SystemApi
public @NonNull final MmTelCapabilities queryCapabilityStatus() {
return new MmTelCapabilities(super.queryCapabilityStatus());
}
@@ -468,7 +467,7 @@ public class MmTelFeature extends ImsFeature {
* {@link #changeEnabledCapabilities}) should also show the status as disabled.
* @hide
*/
- @SystemApi @TestApi
+ @SystemApi
public final void notifyCapabilitiesStatusChanged(@NonNull MmTelCapabilities c) {
if (c == null) {
throw new IllegalArgumentException("MmTelCapabilities must be non-null!");
@@ -483,7 +482,7 @@ public class MmTelFeature extends ImsFeature {
* {@link #EXTRA_IS_UNKNOWN_CALL} and {@link #EXTRA_IS_USSD} above.
* @hide
*/
- @SystemApi @TestApi
+ @SystemApi
public final void notifyIncomingCall(@NonNull ImsCallSessionImplBase c,
@NonNull Bundle extras) {
if (c == null || extras == null) {
@@ -509,7 +508,7 @@ public class MmTelFeature extends ImsFeature {
* @param reason The {@link ImsReasonInfo} call rejection reason.
* @hide
*/
- @SystemApi @TestApi
+ @SystemApi
public final void notifyRejectedCall(@NonNull ImsCallProfile callProfile,
@NonNull ImsReasonInfo reason) {
if (callProfile == null || reason == null) {
@@ -548,7 +547,7 @@ public class MmTelFeature extends ImsFeature {
* @link count the new Voice Message count.
* @hide
*/
- @SystemApi @TestApi
+ @SystemApi
public final void notifyVoiceMessageCountUpdate(int count) {
IImsMmTelListener listener = getListener();
if (listener == null) {
@@ -571,7 +570,7 @@ public class MmTelFeature extends ImsFeature {
* @hide
*/
@Override
- @SystemApi @TestApi
+ @SystemApi
public boolean queryCapabilityConfiguration(@MmTelCapabilities.MmTelCapability int capability,
@ImsRegistrationImplBase.ImsRegistrationTech int radioTech) {
// Base implementation - Override to provide functionality
@@ -592,7 +591,7 @@ public class MmTelFeature extends ImsFeature {
* * @hide
*/
@Override
- @SystemApi @TestApi
+ @SystemApi
public void changeEnabledCapabilities(@NonNull CapabilityChangeRequest request,
@NonNull CapabilityCallbackProxy c) {
// Base implementation, no-op
@@ -617,7 +616,7 @@ public class MmTelFeature extends ImsFeature {
* @return a {@link ImsCallProfile} object
* @hide
*/
- @SystemApi @TestApi
+ @SystemApi
public @Nullable ImsCallProfile createCallProfile(int callSessionType, int callType) {
// Base Implementation - Should be overridden
return null;
@@ -640,7 +639,7 @@ public class MmTelFeature extends ImsFeature {
* @param profile a call profile to make the call
* @hide
*/
- @SystemApi @TestApi
+ @SystemApi
public @Nullable ImsCallSessionImplBase createCallSession(@NonNull ImsCallProfile profile) {
// Base Implementation - Should be overridden
return null;
@@ -659,7 +658,7 @@ public class MmTelFeature extends ImsFeature {
* call will be placed over IMS or via CSFB.
* @hide
*/
- @SystemApi @TestApi
+ @SystemApi
public @ProcessCallResult int shouldProcessCall(@NonNull String[] numbers) {
return PROCESS_CALL_IMS;
}
@@ -694,7 +693,7 @@ public class MmTelFeature extends ImsFeature {
* configuration.
* @hide
*/
- @SystemApi @TestApi
+ @SystemApi
public @NonNull ImsUtImplBase getUt() {
// Base Implementation - Should be overridden
return new ImsUtImplBase();
@@ -705,7 +704,7 @@ public class MmTelFeature extends ImsFeature {
* calls that support it.
* @hide
*/
- @SystemApi @TestApi
+ @SystemApi
public @NonNull ImsEcbmImplBase getEcbm() {
// Base Implementation - Should be overridden
return new ImsEcbmImplBase();
@@ -716,7 +715,7 @@ public class MmTelFeature extends ImsFeature {
* package processing for multi-endpoint.
* @hide
*/
- @SystemApi @TestApi
+ @SystemApi
public @NonNull ImsMultiEndpointImplBase getMultiEndpoint() {
// Base Implementation - Should be overridden
return new ImsMultiEndpointImplBase();
@@ -744,7 +743,7 @@ public class MmTelFeature extends ImsFeature {
* }
* @hide
*/
- @SystemApi @TestApi
+ @SystemApi
public void setUiTtyMode(int mode, @Nullable Message onCompleteMessage) {
// Base Implementation - Should be overridden
}
@@ -780,7 +779,7 @@ public class MmTelFeature extends ImsFeature {
* Provider.
* @hide
*/
- @SystemApi @TestApi
+ @SystemApi
public @NonNull ImsSmsImplBase getSmsImplementation() {
return new ImsSmsImplBase();
}
@@ -794,7 +793,7 @@ public class MmTelFeature extends ImsFeature {
* @hide
*/
@Override
- @SystemApi @TestApi
+ @SystemApi
public void onFeatureRemoved() {
// Base Implementation - Should be overridden
}
@@ -804,7 +803,7 @@ public class MmTelFeature extends ImsFeature {
* @hide
*/
@Override
- @SystemApi @TestApi
+ @SystemApi
public void onFeatureReady() {
// Base Implementation - Should be overridden
}
diff --git a/telephony/java/android/telephony/ims/feature/RcsFeature.java b/telephony/java/android/telephony/ims/feature/RcsFeature.java
index 98b0bcf6075b..b8ae146784d4 100644
--- a/telephony/java/android/telephony/ims/feature/RcsFeature.java
+++ b/telephony/java/android/telephony/ims/feature/RcsFeature.java
@@ -20,7 +20,6 @@ import android.annotation.CallbackExecutor;
import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.SystemApi;
-import android.annotation.TestApi;
import android.net.Uri;
import android.os.RemoteException;
import android.telephony.ims.RcsContactUceCapability;
@@ -50,7 +49,6 @@ import java.util.function.Supplier;
* @hide
*/
@SystemApi
-@TestApi
public class RcsFeature extends ImsFeature {
private static final String LOG_TAG = "RcsFeature";
diff --git a/telephony/java/android/telephony/ims/stub/ImsCallSessionImplBase.java b/telephony/java/android/telephony/ims/stub/ImsCallSessionImplBase.java
index 8f738d216cbe..1cebdd582b58 100644
--- a/telephony/java/android/telephony/ims/stub/ImsCallSessionImplBase.java
+++ b/telephony/java/android/telephony/ims/stub/ImsCallSessionImplBase.java
@@ -18,7 +18,6 @@ package android.telephony.ims.stub;
import android.annotation.NonNull;
import android.annotation.SystemApi;
-import android.annotation.TestApi;
import android.os.Message;
import android.os.RemoteException;
import android.telephony.ims.ImsCallProfile;
@@ -39,7 +38,6 @@ import com.android.ims.internal.IImsVideoCallProvider;
* @hide
*/
@SystemApi
-@TestApi
// DO NOT remove or change the existing APIs, only add new ones to this Base implementation or you
// will break other implementations of ImsCallSession maintained by other ImsServices.
public class ImsCallSessionImplBase implements AutoCloseable {
diff --git a/telephony/java/android/telephony/ims/stub/ImsConfigImplBase.java b/telephony/java/android/telephony/ims/stub/ImsConfigImplBase.java
index 4ef44d3ec9ef..e0290a5dc2af 100644
--- a/telephony/java/android/telephony/ims/stub/ImsConfigImplBase.java
+++ b/telephony/java/android/telephony/ims/stub/ImsConfigImplBase.java
@@ -19,7 +19,6 @@ package android.telephony.ims.stub;
import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.SystemApi;
-import android.annotation.TestApi;
import android.content.Context;
import android.os.PersistableBundle;
import android.os.RemoteException;
@@ -51,7 +50,6 @@ import java.util.HashMap;
* @hide
*/
@SystemApi
-@TestApi
public class ImsConfigImplBase {
private static final String TAG = "ImsConfigImplBase";
diff --git a/telephony/java/android/telephony/ims/stub/ImsEcbmImplBase.java b/telephony/java/android/telephony/ims/stub/ImsEcbmImplBase.java
index 4a3a2eaf4225..06c35eaec6dd 100644
--- a/telephony/java/android/telephony/ims/stub/ImsEcbmImplBase.java
+++ b/telephony/java/android/telephony/ims/stub/ImsEcbmImplBase.java
@@ -17,7 +17,6 @@
package android.telephony.ims.stub;
import android.annotation.SystemApi;
-import android.annotation.TestApi;
import android.os.RemoteException;
import android.util.Log;
@@ -34,7 +33,6 @@ import com.android.ims.internal.IImsEcbmListener;
* @hide
*/
@SystemApi
-@TestApi
public class ImsEcbmImplBase {
private static final String TAG = "ImsEcbmImplBase";
diff --git a/telephony/java/android/telephony/ims/stub/ImsFeatureConfiguration.java b/telephony/java/android/telephony/ims/stub/ImsFeatureConfiguration.java
index 4e7307e2fa0c..cd9ebbf38e35 100644
--- a/telephony/java/android/telephony/ims/stub/ImsFeatureConfiguration.java
+++ b/telephony/java/android/telephony/ims/stub/ImsFeatureConfiguration.java
@@ -19,7 +19,6 @@ package android.telephony.ims.stub;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.SystemApi;
-import android.annotation.TestApi;
import android.os.Parcel;
import android.os.Parcelable;
import android.telephony.ims.feature.ImsFeature;
@@ -36,7 +35,6 @@ import java.util.Set;
* @hide
*/
@SystemApi
-@TestApi
public final class ImsFeatureConfiguration implements Parcelable {
public static final class FeatureSlotPair {
diff --git a/telephony/java/android/telephony/ims/stub/ImsMultiEndpointImplBase.java b/telephony/java/android/telephony/ims/stub/ImsMultiEndpointImplBase.java
index 0ae5bba5d722..d002903a11b6 100644
--- a/telephony/java/android/telephony/ims/stub/ImsMultiEndpointImplBase.java
+++ b/telephony/java/android/telephony/ims/stub/ImsMultiEndpointImplBase.java
@@ -17,7 +17,6 @@
package android.telephony.ims.stub;
import android.annotation.SystemApi;
-import android.annotation.TestApi;
import android.os.RemoteException;
import android.telephony.ims.ImsExternalCallState;
import android.util.Log;
@@ -38,7 +37,6 @@ import java.util.List;
* @hide
*/
@SystemApi
-@TestApi
public class ImsMultiEndpointImplBase {
private static final String TAG = "MultiEndpointImplBase";
diff --git a/telephony/java/android/telephony/ims/stub/ImsRegistrationImplBase.java b/telephony/java/android/telephony/ims/stub/ImsRegistrationImplBase.java
index 2cdf70e6cf4c..12abdd1d7e11 100644
--- a/telephony/java/android/telephony/ims/stub/ImsRegistrationImplBase.java
+++ b/telephony/java/android/telephony/ims/stub/ImsRegistrationImplBase.java
@@ -18,7 +18,6 @@ package android.telephony.ims.stub;
import android.annotation.IntDef;
import android.annotation.SystemApi;
-import android.annotation.TestApi;
import android.net.Uri;
import android.os.RemoteException;
import android.telephony.ims.ImsReasonInfo;
@@ -40,7 +39,6 @@ import java.lang.annotation.RetentionPolicy;
* @hide
*/
@SystemApi
-@TestApi
public class ImsRegistrationImplBase {
private static final String LOG_TAG = "ImsRegistrationImplBase";
diff --git a/telephony/java/android/telephony/ims/stub/ImsSmsImplBase.java b/telephony/java/android/telephony/ims/stub/ImsSmsImplBase.java
index a9a33c0e1507..2783e299236b 100644
--- a/telephony/java/android/telephony/ims/stub/ImsSmsImplBase.java
+++ b/telephony/java/android/telephony/ims/stub/ImsSmsImplBase.java
@@ -19,7 +19,6 @@ package android.telephony.ims.stub;
import android.annotation.IntDef;
import android.annotation.IntRange;
import android.annotation.SystemApi;
-import android.annotation.TestApi;
import android.os.RemoteException;
import android.telephony.SmsManager;
import android.telephony.SmsMessage;
@@ -38,7 +37,6 @@ import java.lang.annotation.RetentionPolicy;
* @hide
*/
@SystemApi
-@TestApi
public class ImsSmsImplBase {
private static final String LOG_TAG = "SmsImplBase";
diff --git a/telephony/java/android/telephony/ims/stub/ImsUtImplBase.java b/telephony/java/android/telephony/ims/stub/ImsUtImplBase.java
index 8564f7affd6d..f5219d5b49e8 100644
--- a/telephony/java/android/telephony/ims/stub/ImsUtImplBase.java
+++ b/telephony/java/android/telephony/ims/stub/ImsUtImplBase.java
@@ -20,7 +20,6 @@ import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.SystemApi;
-import android.annotation.TestApi;
import android.os.Bundle;
import android.os.RemoteException;
import android.telephony.ims.ImsUtListener;
@@ -40,7 +39,6 @@ import java.lang.annotation.RetentionPolicy;
// DO NOT remove or change the existing APIs, only add new ones to this Base implementation or you
// will break other implementations of ImsUt maintained by other ImsServices.
@SystemApi
-@TestApi
public class ImsUtImplBase {
/**
* Bar all incoming calls. (See 3GPP TS 24.611)
diff --git a/telephony/java/android/telephony/ims/stub/SipTransportImplBase.java b/telephony/java/android/telephony/ims/stub/SipTransportImplBase.java
index 17bd4b14925f..b2b2914b3739 100644
--- a/telephony/java/android/telephony/ims/stub/SipTransportImplBase.java
+++ b/telephony/java/android/telephony/ims/stub/SipTransportImplBase.java
@@ -17,6 +17,7 @@
package android.telephony.ims.stub;
import android.annotation.NonNull;
+import android.annotation.SystemApi;
import android.telephony.ims.aidl.ISipTransport;
import java.util.concurrent.Executor;
@@ -24,9 +25,9 @@ import java.util.concurrent.Executor;
/**
* Manages the creation and destruction of SipDelegates in order to proxy SIP traffic to other
* IMS applications in order to support IMS single registration.
- *
- * @hide Until there is an implementation, keep this hidden
+ * @hide
*/
+@SystemApi
public class SipTransportImplBase {
private final Executor mBinderExecutor;
diff --git a/telephony/java/android/telephony/mbms/DownloadRequest.java b/telephony/java/android/telephony/mbms/DownloadRequest.java
index ac258cd40d65..eb59f87a6c02 100644
--- a/telephony/java/android/telephony/mbms/DownloadRequest.java
+++ b/telephony/java/android/telephony/mbms/DownloadRequest.java
@@ -19,7 +19,6 @@ package android.telephony.mbms;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.SystemApi;
-import android.annotation.TestApi;
import android.content.Intent;
import android.net.Uri;
import android.os.Parcel;
@@ -186,7 +185,6 @@ public final class DownloadRequest implements Parcelable {
* @hide
*/
@SystemApi
- @TestApi
public Builder setServiceId(String serviceId) {
fileServiceId = serviceId;
return this;
diff --git a/telephony/java/android/telephony/mbms/FileInfo.java b/telephony/java/android/telephony/mbms/FileInfo.java
index ada2872874f5..e52b2ce0c505 100644
--- a/telephony/java/android/telephony/mbms/FileInfo.java
+++ b/telephony/java/android/telephony/mbms/FileInfo.java
@@ -17,7 +17,6 @@
package android.telephony.mbms;
import android.annotation.SystemApi;
-import android.annotation.TestApi;
import android.net.Uri;
import android.os.Parcel;
import android.os.Parcelable;
@@ -50,7 +49,6 @@ public final class FileInfo implements Parcelable {
* @hide
*/
@SystemApi
- @TestApi
public FileInfo(Uri uri, String mimeType) {
this.uri = uri;
this.mimeType = mimeType;
diff --git a/telephony/java/android/telephony/mbms/FileServiceInfo.java b/telephony/java/android/telephony/mbms/FileServiceInfo.java
index 8c79ab63b131..8777e7f59e3f 100644
--- a/telephony/java/android/telephony/mbms/FileServiceInfo.java
+++ b/telephony/java/android/telephony/mbms/FileServiceInfo.java
@@ -17,7 +17,6 @@
package android.telephony.mbms;
import android.annotation.SystemApi;
-import android.annotation.TestApi;
import android.os.Parcel;
import android.os.Parcelable;
@@ -36,7 +35,6 @@ public final class FileServiceInfo extends ServiceInfo implements Parcelable {
/** @hide */
@SystemApi
- @TestApi
public FileServiceInfo(Map<Locale, String> newNames, String newClassName,
List<Locale> newLocales, String newServiceId, Date start, Date end,
List<FileInfo> newFiles) {
diff --git a/telephony/java/android/telephony/mbms/StreamingServiceInfo.java b/telephony/java/android/telephony/mbms/StreamingServiceInfo.java
index 8ad1d8940ca7..316e86568213 100644
--- a/telephony/java/android/telephony/mbms/StreamingServiceInfo.java
+++ b/telephony/java/android/telephony/mbms/StreamingServiceInfo.java
@@ -17,7 +17,6 @@
package android.telephony.mbms;
import android.annotation.SystemApi;
-import android.annotation.TestApi;
import android.os.Parcel;
import android.os.Parcelable;
@@ -42,7 +41,6 @@ public final class StreamingServiceInfo extends ServiceInfo implements Parcelabl
* @hide
*/
@SystemApi
- @TestApi
public StreamingServiceInfo(Map<Locale, String> names, String className,
List<Locale> locales, String serviceId, Date start, Date end) {
super(names, className, locales, serviceId, start, end);
diff --git a/telephony/java/android/telephony/mbms/UriPathPair.java b/telephony/java/android/telephony/mbms/UriPathPair.java
index f53d7e0287f3..9258919919b7 100644
--- a/telephony/java/android/telephony/mbms/UriPathPair.java
+++ b/telephony/java/android/telephony/mbms/UriPathPair.java
@@ -17,7 +17,6 @@
package android.telephony.mbms;
import android.annotation.SystemApi;
-import android.annotation.TestApi;
import android.content.ContentResolver;
import android.net.Uri;
import android.os.Parcel;
@@ -30,7 +29,6 @@ import android.telephony.mbms.vendor.VendorUtils;
* @hide
*/
@SystemApi
-@TestApi
public final class UriPathPair implements Parcelable {
private final Uri mFilePathUri;
private final Uri mContentUri;
diff --git a/telephony/java/android/telephony/mbms/vendor/MbmsDownloadServiceBase.java b/telephony/java/android/telephony/mbms/vendor/MbmsDownloadServiceBase.java
index 3053ea03bebe..ffc1d2efe2ae 100644
--- a/telephony/java/android/telephony/mbms/vendor/MbmsDownloadServiceBase.java
+++ b/telephony/java/android/telephony/mbms/vendor/MbmsDownloadServiceBase.java
@@ -18,7 +18,6 @@ package android.telephony.mbms.vendor;
import android.annotation.NonNull;
import android.annotation.SystemApi;
-import android.annotation.TestApi;
import android.content.Intent;
import android.os.Binder;
import android.os.IBinder;
@@ -45,7 +44,6 @@ import java.util.Map;
* @hide
*/
@SystemApi
-@TestApi
public class MbmsDownloadServiceBase extends IMbmsDownloadService.Stub {
private final Map<IBinder, DownloadStatusListener> mDownloadStatusListenerBinderMap =
new HashMap<>();
@@ -576,7 +574,6 @@ public class MbmsDownloadServiceBase extends IMbmsDownloadService.Stub {
// Following two methods exist to workaround b/124210145
/** @hide */
@SystemApi
- @TestApi
@Override
public android.os.IBinder asBinder() {
return super.asBinder();
@@ -584,7 +581,6 @@ public class MbmsDownloadServiceBase extends IMbmsDownloadService.Stub {
/** @hide */
@SystemApi
- @TestApi
@Override
public boolean onTransact(int code, android.os.Parcel data, android.os.Parcel reply,
int flags) throws RemoteException {
diff --git a/telephony/java/android/telephony/mbms/vendor/MbmsGroupCallServiceBase.java b/telephony/java/android/telephony/mbms/vendor/MbmsGroupCallServiceBase.java
index 1335b52673d2..e5b18bb5d644 100644
--- a/telephony/java/android/telephony/mbms/vendor/MbmsGroupCallServiceBase.java
+++ b/telephony/java/android/telephony/mbms/vendor/MbmsGroupCallServiceBase.java
@@ -18,7 +18,6 @@ package android.telephony.mbms.vendor;
import android.annotation.NonNull;
import android.annotation.SystemApi;
-import android.annotation.TestApi;
import android.app.Service;
import android.content.Intent;
import android.os.Binder;
@@ -41,7 +40,6 @@ import java.util.List;
* @hide
*/
@SystemApi
-@TestApi
public class MbmsGroupCallServiceBase extends Service {
private final IBinder mInterface = new Stub() {
@Override
diff --git a/telephony/java/android/telephony/mbms/vendor/MbmsStreamingServiceBase.java b/telephony/java/android/telephony/mbms/vendor/MbmsStreamingServiceBase.java
index cced44759527..e169b16ca958 100644
--- a/telephony/java/android/telephony/mbms/vendor/MbmsStreamingServiceBase.java
+++ b/telephony/java/android/telephony/mbms/vendor/MbmsStreamingServiceBase.java
@@ -18,7 +18,6 @@ package android.telephony.mbms.vendor;
import android.annotation.Nullable;
import android.annotation.SystemApi;
-import android.annotation.TestApi;
import android.content.Intent;
import android.net.Uri;
import android.os.Binder;
@@ -39,7 +38,6 @@ import java.util.List;
* @hide
*/
@SystemApi
-@TestApi
public class MbmsStreamingServiceBase extends IMbmsStreamingService.Stub {
/**
* Initialize streaming service for this app and subId, registering the listener.
@@ -299,7 +297,6 @@ public class MbmsStreamingServiceBase extends IMbmsStreamingService.Stub {
// Following two methods exist to workaround b/124210145
/** @hide */
@SystemApi
- @TestApi
@Override
public android.os.IBinder asBinder() {
return super.asBinder();
@@ -307,7 +304,6 @@ public class MbmsStreamingServiceBase extends IMbmsStreamingService.Stub {
/** @hide */
@SystemApi
- @TestApi
@Override
public boolean onTransact(int code, android.os.Parcel data, android.os.Parcel reply,
int flags) throws RemoteException {
diff --git a/telephony/java/android/telephony/mbms/vendor/VendorUtils.java b/telephony/java/android/telephony/mbms/vendor/VendorUtils.java
index f1cac8cf8286..a43f12244168 100644
--- a/telephony/java/android/telephony/mbms/vendor/VendorUtils.java
+++ b/telephony/java/android/telephony/mbms/vendor/VendorUtils.java
@@ -17,7 +17,6 @@
package android.telephony.mbms.vendor;
import android.annotation.SystemApi;
-import android.annotation.TestApi;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
@@ -35,7 +34,6 @@ import java.util.List;
* @hide
*/
@SystemApi
-@TestApi
public class VendorUtils {
/**
diff --git a/test-mock/api/test-current.txt b/test-mock/api/test-current.txt
index 32ca250b6c74..79d746a57cc5 100644
--- a/test-mock/api/test-current.txt
+++ b/test-mock/api/test-current.txt
@@ -6,21 +6,12 @@ package android.test.mock {
}
@Deprecated public class MockPackageManager extends android.content.pm.PackageManager {
- method public void addOnPermissionsChangeListener(android.content.pm.PackageManager.OnPermissionsChangedListener);
- method public boolean arePermissionsIndividuallyControlled();
- method public String getDefaultBrowserPackageNameAsUser(int);
method public int getInstallReason(String, android.os.UserHandle);
method public java.util.List<android.content.pm.ApplicationInfo> getInstalledApplicationsAsUser(int, int);
- method public java.util.List<android.content.pm.PackageInfo> getInstalledPackagesAsUser(int, int);
method public String[] getNamesForUids(int[]);
method public String getPermissionControllerPackageName();
- method public int getPermissionFlags(String, String, android.os.UserHandle);
method @NonNull public String getServicesSystemSharedLibraryPackageName();
method @NonNull public String getSharedSystemSharedLibraryPackageName();
- method public void grantRuntimePermission(String, String, android.os.UserHandle);
- method public void removeOnPermissionsChangeListener(android.content.pm.PackageManager.OnPermissionsChangedListener);
- method public void revokeRuntimePermission(String, String, android.os.UserHandle);
- method public void updatePermissionFlags(String, String, int, int, android.os.UserHandle);
}
}
diff --git a/tests/RollbackTest/StagedRollbackTest/src/com/android/tests/rollback/host/StagedRollbackTest.java b/tests/RollbackTest/StagedRollbackTest/src/com/android/tests/rollback/host/StagedRollbackTest.java
index bf7a6ff3ca77..725bfa95166a 100644
--- a/tests/RollbackTest/StagedRollbackTest/src/com/android/tests/rollback/host/StagedRollbackTest.java
+++ b/tests/RollbackTest/StagedRollbackTest/src/com/android/tests/rollback/host/StagedRollbackTest.java
@@ -280,7 +280,7 @@ public class StagedRollbackTest extends BaseHostJUnit4Test {
after.removeAll(before);
// There should be only one /data/misc_ce/0/rollback/<rollbackId> created during test
assertThat(after).hasSize(1);
- after.forEach(dir -> assertDirectoryIsEmpty(dir));
+ assertDirectoryIsEmpty(after.get(0));
}
/**
@@ -336,31 +336,37 @@ public class StagedRollbackTest extends BaseHostJUnit4Test {
String oldFilePath1 = apexDataDirDeSys(APK_IN_APEX_TESTAPEX_NAME) + "/" + TEST_FILENAME_1;
String oldFilePath2 =
apexDataDirDeSys(APK_IN_APEX_TESTAPEX_NAME) + TEST_SUBDIR + TEST_FILENAME_2;
- pushString(TEST_STRING_1, oldFilePath1);
- pushString(TEST_STRING_2, oldFilePath2);
+ runAsRoot(() -> {
+ assertThat(getDevice().pushString(TEST_STRING_1, oldFilePath1)).isTrue();
+ assertThat(getDevice().pushString(TEST_STRING_2, oldFilePath2)).isTrue();
+ });
// Install new version of the APEX with rollback enabled
runPhase("testRollbackApexDataDirectories_Phase1");
getDevice().reboot();
// Replace files in data directory
- getDevice().deleteFile(oldFilePath1);
- getDevice().deleteFile(oldFilePath2);
String newFilePath3 = apexDataDirDeSys(APK_IN_APEX_TESTAPEX_NAME) + "/" + TEST_FILENAME_3;
String newFilePath4 =
apexDataDirDeSys(APK_IN_APEX_TESTAPEX_NAME) + TEST_SUBDIR + TEST_FILENAME_4;
- pushString(TEST_STRING_3, newFilePath3);
- pushString(TEST_STRING_4, newFilePath4);
+ runAsRoot(() -> {
+ getDevice().deleteFile(oldFilePath1);
+ getDevice().deleteFile(oldFilePath2);
+ assertThat(getDevice().pushString(TEST_STRING_3, newFilePath3)).isTrue();
+ assertThat(getDevice().pushString(TEST_STRING_4, newFilePath4)).isTrue();
+ });
// Roll back the APEX
runPhase("testRollbackApexDataDirectories_Phase2");
getDevice().reboot();
// Verify that old files have been restored and new files are gone
- assertEquals(TEST_STRING_1, getDevice().pullFileContents(oldFilePath1));
- assertEquals(TEST_STRING_2, getDevice().pullFileContents(oldFilePath2));
- assertNull(getDevice().pullFile(newFilePath3));
- assertNull(getDevice().pullFile(newFilePath4));
+ runAsRoot(() -> {
+ assertEquals(TEST_STRING_1, getDevice().pullFileContents(oldFilePath1));
+ assertEquals(TEST_STRING_2, getDevice().pullFileContents(oldFilePath2));
+ assertNull(getDevice().pullFile(newFilePath3));
+ assertNull(getDevice().pullFile(newFilePath4));
+ });
// Verify snapshots are deleted after restoration
List<String> after = getSnapshotDirectories("/data/misc/apexrollback");
@@ -368,7 +374,7 @@ public class StagedRollbackTest extends BaseHostJUnit4Test {
after.removeAll(before);
// There should be only one /data/misc/apexrollback/<rollbackId> created during test
assertThat(after).hasSize(1);
- after.forEach(dir -> assertDirectoryIsEmpty(dir));
+ assertDirectoryIsEmpty(after.get(0));
}
/**
@@ -384,32 +390,38 @@ public class StagedRollbackTest extends BaseHostJUnit4Test {
APK_IN_APEX_TESTAPEX_NAME, 0) + "/" + TEST_FILENAME_1;
String oldFilePath2 =
apexDataDirDeUser(APK_IN_APEX_TESTAPEX_NAME, 0) + TEST_SUBDIR + TEST_FILENAME_2;
- pushString(TEST_STRING_1, oldFilePath1);
- pushString(TEST_STRING_2, oldFilePath2);
+ runAsRoot(() -> {
+ assertThat(getDevice().pushString(TEST_STRING_1, oldFilePath1)).isTrue();
+ assertThat(getDevice().pushString(TEST_STRING_2, oldFilePath2)).isTrue();
+ });
// Install new version of the APEX with rollback enabled
runPhase("testRollbackApexDataDirectories_Phase1");
getDevice().reboot();
// Replace files in data directory
- getDevice().deleteFile(oldFilePath1);
- getDevice().deleteFile(oldFilePath2);
String newFilePath3 =
apexDataDirDeUser(APK_IN_APEX_TESTAPEX_NAME, 0) + "/" + TEST_FILENAME_3;
String newFilePath4 =
apexDataDirDeUser(APK_IN_APEX_TESTAPEX_NAME, 0) + TEST_SUBDIR + TEST_FILENAME_4;
- pushString(TEST_STRING_3, newFilePath3);
- pushString(TEST_STRING_4, newFilePath4);
+ runAsRoot(() -> {
+ getDevice().deleteFile(oldFilePath1);
+ getDevice().deleteFile(oldFilePath2);
+ assertThat(getDevice().pushString(TEST_STRING_3, newFilePath3)).isTrue();
+ assertThat(getDevice().pushString(TEST_STRING_4, newFilePath4)).isTrue();
+ });
// Roll back the APEX
runPhase("testRollbackApexDataDirectories_Phase2");
getDevice().reboot();
// Verify that old files have been restored and new files are gone
- assertEquals(TEST_STRING_1, getDevice().pullFileContents(oldFilePath1));
- assertEquals(TEST_STRING_2, getDevice().pullFileContents(oldFilePath2));
- assertNull(getDevice().pullFile(newFilePath3));
- assertNull(getDevice().pullFile(newFilePath4));
+ runAsRoot(() -> {
+ assertEquals(TEST_STRING_1, getDevice().pullFileContents(oldFilePath1));
+ assertEquals(TEST_STRING_2, getDevice().pullFileContents(oldFilePath2));
+ assertNull(getDevice().pullFile(newFilePath3));
+ assertNull(getDevice().pullFile(newFilePath4));
+ });
// Verify snapshots are deleted after restoration
List<String> after = getSnapshotDirectories("/data/misc_de/0/apexrollback");
@@ -417,7 +429,7 @@ public class StagedRollbackTest extends BaseHostJUnit4Test {
after.removeAll(before);
// There should be only one /data/misc_de/0/apexrollback/<rollbackId> created during test
assertThat(after).hasSize(1);
- after.forEach(dir -> assertDirectoryIsEmpty(dir));
+ assertDirectoryIsEmpty(after.get(0));
}
/**
@@ -432,31 +444,37 @@ public class StagedRollbackTest extends BaseHostJUnit4Test {
String oldFilePath1 = apexDataDirCe(APK_IN_APEX_TESTAPEX_NAME, 0) + "/" + TEST_FILENAME_1;
String oldFilePath2 =
apexDataDirCe(APK_IN_APEX_TESTAPEX_NAME, 0) + TEST_SUBDIR + TEST_FILENAME_2;
- pushString(TEST_STRING_1, oldFilePath1);
- pushString(TEST_STRING_2, oldFilePath2);
+ runAsRoot(() -> {
+ assertThat(getDevice().pushString(TEST_STRING_1, oldFilePath1)).isTrue();
+ assertThat(getDevice().pushString(TEST_STRING_2, oldFilePath2)).isTrue();
+ });
// Install new version of the APEX with rollback enabled
runPhase("testRollbackApexDataDirectories_Phase1");
getDevice().reboot();
// Replace files in data directory
- getDevice().deleteFile(oldFilePath1);
- getDevice().deleteFile(oldFilePath2);
String newFilePath3 = apexDataDirCe(APK_IN_APEX_TESTAPEX_NAME, 0) + "/" + TEST_FILENAME_3;
String newFilePath4 =
apexDataDirCe(APK_IN_APEX_TESTAPEX_NAME, 0) + TEST_SUBDIR + TEST_FILENAME_4;
- pushString(TEST_STRING_3, newFilePath3);
- pushString(TEST_STRING_4, newFilePath4);
+ runAsRoot(() -> {
+ getDevice().deleteFile(oldFilePath1);
+ getDevice().deleteFile(oldFilePath2);
+ assertThat(getDevice().pushString(TEST_STRING_3, newFilePath3)).isTrue();
+ assertThat(getDevice().pushString(TEST_STRING_4, newFilePath4)).isTrue();
+ });
// Roll back the APEX
runPhase("testRollbackApexDataDirectories_Phase2");
getDevice().reboot();
// Verify that old files have been restored and new files are gone
- assertEquals(TEST_STRING_1, getDevice().pullFileContents(oldFilePath1));
- assertEquals(TEST_STRING_2, getDevice().pullFileContents(oldFilePath2));
- assertNull(getDevice().pullFile(newFilePath3));
- assertNull(getDevice().pullFile(newFilePath4));
+ runAsRoot(() -> {
+ assertEquals(TEST_STRING_1, getDevice().pullFileContents(oldFilePath1));
+ assertEquals(TEST_STRING_2, getDevice().pullFileContents(oldFilePath2));
+ assertNull(getDevice().pullFile(newFilePath3));
+ assertNull(getDevice().pullFile(newFilePath4));
+ });
// Verify snapshots are deleted after restoration
List<String> after = getSnapshotDirectories("/data/misc_ce/0/apexrollback");
@@ -464,7 +482,7 @@ public class StagedRollbackTest extends BaseHostJUnit4Test {
after.removeAll(before);
// There should be only one /data/misc_ce/0/apexrollback/<rollbackId> created during test
assertThat(after).hasSize(1);
- after.forEach(dir -> assertDirectoryIsEmpty(dir));
+ assertDirectoryIsEmpty(after.get(0));
}
/**
@@ -478,30 +496,36 @@ public class StagedRollbackTest extends BaseHostJUnit4Test {
// Push files to apk data directory
String oldFilePath1 = apkDataDirDe(TESTAPP_A, 0) + "/" + TEST_FILENAME_1;
String oldFilePath2 = apkDataDirDe(TESTAPP_A, 0) + TEST_SUBDIR + TEST_FILENAME_2;
- pushString(TEST_STRING_1, oldFilePath1);
- pushString(TEST_STRING_2, oldFilePath2);
+ runAsRoot(() -> {
+ assertThat(getDevice().pushString(TEST_STRING_1, oldFilePath1)).isTrue();
+ assertThat(getDevice().pushString(TEST_STRING_2, oldFilePath2)).isTrue();
+ });
// Install version 2 of TESTAPP_A with rollback enabled
runPhase("testRollbackApkDataDirectories_Phase2");
getDevice().reboot();
// Replace files in data directory
- getDevice().deleteFile(oldFilePath1);
- getDevice().deleteFile(oldFilePath2);
String newFilePath3 = apkDataDirDe(TESTAPP_A, 0) + "/" + TEST_FILENAME_3;
String newFilePath4 = apkDataDirDe(TESTAPP_A, 0) + TEST_SUBDIR + TEST_FILENAME_4;
- pushString(TEST_STRING_3, newFilePath3);
- pushString(TEST_STRING_4, newFilePath4);
+ runAsRoot(() -> {
+ getDevice().deleteFile(oldFilePath1);
+ getDevice().deleteFile(oldFilePath2);
+ assertThat(getDevice().pushString(TEST_STRING_3, newFilePath3)).isTrue();
+ assertThat(getDevice().pushString(TEST_STRING_4, newFilePath4)).isTrue();
+ });
// Roll back the APK
runPhase("testRollbackApkDataDirectories_Phase3");
getDevice().reboot();
// Verify that old files have been restored and new files are gone
- assertEquals(TEST_STRING_1, getDevice().pullFileContents(oldFilePath1));
- assertEquals(TEST_STRING_2, getDevice().pullFileContents(oldFilePath2));
- assertNull(getDevice().pullFile(newFilePath3));
- assertNull(getDevice().pullFile(newFilePath4));
+ runAsRoot(() -> {
+ assertEquals(TEST_STRING_1, getDevice().pullFileContents(oldFilePath1));
+ assertEquals(TEST_STRING_2, getDevice().pullFileContents(oldFilePath2));
+ assertNull(getDevice().pullFile(newFilePath3));
+ assertNull(getDevice().pullFile(newFilePath4));
+ });
}
@Test
@@ -513,8 +537,10 @@ public class StagedRollbackTest extends BaseHostJUnit4Test {
String oldFilePath1 = apexDataDirCe(APK_IN_APEX_TESTAPEX_NAME, 0) + "/" + TEST_FILENAME_1;
String oldFilePath2 =
apexDataDirCe(APK_IN_APEX_TESTAPEX_NAME, 0) + TEST_SUBDIR + TEST_FILENAME_2;
- pushString(TEST_STRING_1, oldFilePath1);
- pushString(TEST_STRING_2, oldFilePath2);
+ runAsRoot(() -> {
+ assertThat(getDevice().pushString(TEST_STRING_1, oldFilePath1)).isTrue();
+ assertThat(getDevice().pushString(TEST_STRING_2, oldFilePath2)).isTrue();
+ });
// Install new version of the APEX with rollback enabled
runPhase("testRollbackApexDataDirectories_Phase1");
@@ -527,9 +553,11 @@ public class StagedRollbackTest extends BaseHostJUnit4Test {
assertThat(after).hasSize(1);
// Expire all rollbacks and check CE snapshot directories are deleted
runPhase("testCleanUp");
- for (String dir : after) {
- assertNull(getDevice().getFileEntry(dir));
- }
+ runAsRoot(() -> {
+ for (String dir : after) {
+ assertNull(getDevice().getFileEntry(dir));
+ }
+ });
}
private void pushTestApex() throws Exception {
@@ -563,26 +591,34 @@ public class StagedRollbackTest extends BaseHostJUnit4Test {
}
private List<String> getSnapshotDirectories(String baseDir) throws Exception {
- IFileEntry f = getDevice().getFileEntry(baseDir);
- if (f == null) {
- Log.d(TAG, "baseDir doesn't exist: " + baseDir);
- return Collections.EMPTY_LIST;
+ try {
+ getDevice().enableAdbRoot();
+ IFileEntry f = getDevice().getFileEntry(baseDir);
+ if (f == null) {
+ Log.d(TAG, "baseDir doesn't exist: " + baseDir);
+ return Collections.EMPTY_LIST;
+ }
+ List<String> list = f.getChildren(false)
+ .stream().filter(entry -> entry.getName().matches("\\d+(-prerestore)?"))
+ .map(entry -> entry.getFullPath())
+ .collect(Collectors.toList());
+ Log.d(TAG, "getSnapshotDirectories=" + list);
+ return list;
+ } finally {
+ getDevice().disableAdbRoot();
}
- List<String> list = f.getChildren(false)
- .stream().filter(entry -> entry.getName().matches("\\d+(-prerestore)?"))
- .map(entry -> entry.getFullPath())
- .collect(Collectors.toList());
- Log.d(TAG, "getSnapshotDirectories=" + list);
- return list;
}
- private void assertDirectoryIsEmpty(String path) {
+ private void assertDirectoryIsEmpty(String path) throws Exception {
try {
+ getDevice().enableAdbRoot();
IFileEntry file = getDevice().getFileEntry(path);
assertTrue("Not a directory: " + path, file.isDirectory());
assertTrue("Directory not empty: " + path, file.getChildren(false).isEmpty());
} catch (DeviceNotAvailableException e) {
fail("Can't access directory: " + path);
+ } finally {
+ getDevice().disableAdbRoot();
}
}
@@ -621,10 +657,15 @@ public class StagedRollbackTest extends BaseHostJUnit4Test {
}
}
- private void pushString(String contents, String deviceFilePath) throws Exception {
+ @FunctionalInterface
+ private interface ExceptionalRunnable {
+ void run() throws Exception;
+ }
+
+ private void runAsRoot(ExceptionalRunnable runnable) throws Exception {
try {
getDevice().enableAdbRoot();
- assertThat(getDevice().pushString(contents, deviceFilePath)).isTrue();
+ runnable.run();
} finally {
getDevice().disableAdbRoot();
}
diff --git a/tests/net/Android.bp b/tests/net/Android.bp
index cd2dc0403bd6..a7622198cec7 100644
--- a/tests/net/Android.bp
+++ b/tests/net/Android.bp
@@ -50,6 +50,7 @@ android_test {
platform_apis: true,
test_suites: ["device-tests"],
certificate: "platform",
+ jarjar_rules: "jarjar-rules.txt",
static_libs: [
"androidx.test.rules",
"FrameworksNetCommonTests",
diff --git a/tests/net/common/Android.bp b/tests/net/common/Android.bp
index 46d680fc4511..373aac604b2a 100644
--- a/tests/net/common/Android.bp
+++ b/tests/net/common/Android.bp
@@ -25,6 +25,7 @@ java_library {
"junit",
"mockito-target-minus-junit4",
"net-tests-utils",
+ "net-utils-framework-common",
"platform-test-annotations",
],
libs: [
diff --git a/tests/net/common/java/android/net/LinkPropertiesTest.java b/tests/net/common/java/android/net/LinkPropertiesTest.java
index 3c3076f11727..550953d0612d 100644
--- a/tests/net/common/java/android/net/LinkPropertiesTest.java
+++ b/tests/net/common/java/android/net/LinkPropertiesTest.java
@@ -32,7 +32,6 @@ import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
import android.net.LinkProperties.ProvisioningChange;
-import android.net.util.LinkPropertiesUtils.CompareResult;
import android.os.Build;
import android.system.OsConstants;
import android.util.ArraySet;
@@ -41,6 +40,7 @@ import androidx.core.os.BuildCompat;
import androidx.test.filters.SmallTest;
import androidx.test.runner.AndroidJUnit4;
+import com.android.net.module.util.LinkPropertiesUtils.CompareResult;
import com.android.testutils.DevSdkIgnoreRule;
import com.android.testutils.DevSdkIgnoreRule.IgnoreAfter;
import com.android.testutils.DevSdkIgnoreRule.IgnoreUpTo;
@@ -52,7 +52,6 @@ import org.junit.runner.RunWith;
import java.net.Inet4Address;
import java.net.Inet6Address;
import java.net.InetAddress;
-import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
@@ -447,23 +446,21 @@ public class LinkPropertiesTest {
assertEquals(3, lp.getRoutes().size());
assertAllRoutesHaveInterface("wlan0", lp);
- // Check comparisons work.
+ // Check routes are updated correctly when calling setInterfaceName.
LinkProperties lp2 = new LinkProperties(lp);
assertAllRoutesHaveInterface("wlan0", lp2);
- // LinkProperties#compareAllRoutes exists both in R and before R, but the return type
- // changed in R, so a test compiled with the R version of LinkProperties cannot run on Q.
- if (isAtLeastR()) {
- assertEquals(0, lp.compareAllRoutes(lp2).added.size());
- assertEquals(0, lp.compareAllRoutes(lp2).removed.size());
- }
+ final CompareResult<RouteInfo> cr1 =
+ new CompareResult<>(lp.getAllRoutes(), lp2.getAllRoutes());
+ assertEquals(0, cr1.added.size());
+ assertEquals(0, cr1.removed.size());
lp2.setInterfaceName("p2p0");
assertAllRoutesHaveInterface("p2p0", lp2);
assertAllRoutesNotHaveInterface("wlan0", lp2);
- if (isAtLeastR()) {
- assertEquals(3, lp.compareAllRoutes(lp2).added.size());
- assertEquals(3, lp.compareAllRoutes(lp2).removed.size());
- }
+ final CompareResult<RouteInfo> cr2 =
+ new CompareResult<>(lp.getAllRoutes(), lp2.getAllRoutes());
+ assertEquals(3, cr2.added.size());
+ assertEquals(3, cr2.removed.size());
// Remove route with incorrect interface, no route removed.
lp.removeRoute(new RouteInfo(prefix2, null, null));
@@ -954,28 +951,6 @@ public class LinkPropertiesTest {
assertTrue(rmnet3.getAllRoutes().isEmpty());
rmnet3.ensureDirectlyConnectedRoutes();
assertEqualRoutes(Collections.singletonList(directRoute3), rmnet3.getAllRoutes());
-
- }
-
- @Test @IgnoreUpTo(Build.VERSION_CODES.Q)
- public void testCompareResult() {
- // Either adding or removing items
- compareResult(Arrays.asList(1, 2, 3, 4), Arrays.asList(1),
- Arrays.asList(2, 3, 4), new ArrayList<>());
- compareResult(Arrays.asList(1, 2), Arrays.asList(3, 2, 1, 4),
- new ArrayList<>(), Arrays.asList(3, 4));
-
-
- // adding and removing items at the same time
- compareResult(Arrays.asList(1, 2, 3, 4), Arrays.asList(2, 3, 4, 5),
- Arrays.asList(1), Arrays.asList(5));
- compareResult(Arrays.asList(1, 2, 3), Arrays.asList(4, 5, 6),
- Arrays.asList(1, 2, 3), Arrays.asList(4, 5, 6));
-
- // null cases
- compareResult(Arrays.asList(1, 2, 3), null, Arrays.asList(1, 2, 3), new ArrayList<>());
- compareResult(null, Arrays.asList(3, 2, 1), new ArrayList<>(), Arrays.asList(1, 2, 3));
- compareResult(null, null, new ArrayList<>(), new ArrayList<>());
}
private void assertEqualRoutes(Collection<RouteInfo> expected, Collection<RouteInfo> actual) {
@@ -987,13 +962,6 @@ public class LinkPropertiesTest {
assertEquals(expectedSet, actualSet);
}
- private <T> void compareResult(List<T> oldItems, List<T> newItems, List<T> expectRemoved,
- List<T> expectAdded) {
- CompareResult<T> result = new CompareResult<>(oldItems, newItems);
- assertEquals(new ArraySet<>(expectAdded), new ArraySet<>(result.added));
- assertEquals(new ArraySet<>(expectRemoved), (new ArraySet<>(result.removed)));
- }
-
private static LinkProperties makeLinkPropertiesForParceling() {
LinkProperties source = new LinkProperties();
source.setInterfaceName(NAME);
diff --git a/tests/net/jarjar-rules.txt b/tests/net/jarjar-rules.txt
new file mode 100644
index 000000000000..ca8867206dda
--- /dev/null
+++ b/tests/net/jarjar-rules.txt
@@ -0,0 +1,2 @@
+# Module library in frameworks/libs/net
+rule com.android.net.module.util.** android.net.frameworktests.util.@1
diff --git a/tests/net/java/com/android/server/ConnectivityServiceTest.java b/tests/net/java/com/android/server/ConnectivityServiceTest.java
index 71fa3b4b50d7..1aae6cb35239 100644
--- a/tests/net/java/com/android/server/ConnectivityServiceTest.java
+++ b/tests/net/java/com/android/server/ConnectivityServiceTest.java
@@ -313,6 +313,8 @@ public class ConnectivityServiceTest {
private static final long TIMESTAMP = 1234L;
private static final int NET_ID = 110;
+ // Set a non-zero value to verify the flow to set tcp init rwnd value.
+ private static final int TEST_TCP_INIT_RWND = 60;
private static final String CLAT_PREFIX = "v4-";
private static final String MOBILE_IFNAME = "test_rmnet_data0";
@@ -355,6 +357,7 @@ public class ConnectivityServiceTest {
@Mock LocationManager mLocationManager;
@Mock AppOpsManager mAppOpsManager;
@Mock TelephonyManager mTelephonyManager;
+ @Mock MockableSystemProperties mSystemProperties;
private ArgumentCaptor<ResolverParamsParcel> mResolverParamsParcelCaptor =
ArgumentCaptor.forClass(ResolverParamsParcel.class);
@@ -1257,15 +1260,15 @@ public class ConnectivityServiceTest {
}
private ConnectivityService.Dependencies makeDependencies() {
- final MockableSystemProperties systemProperties = spy(new MockableSystemProperties());
- when(systemProperties.getInt("net.tcp.default_init_rwnd", 0)).thenReturn(0);
- when(systemProperties.getBoolean("ro.radio.noril", false)).thenReturn(false);
-
+ doReturn(TEST_TCP_INIT_RWND).when(mSystemProperties)
+ .getInt("net.tcp.default_init_rwnd", 0);
+ doReturn(false).when(mSystemProperties).getBoolean("ro.radio.noril", false);
+ doNothing().when(mSystemProperties).setTcpInitRwnd(anyInt());
final ConnectivityService.Dependencies deps = mock(ConnectivityService.Dependencies.class);
doReturn(mCsHandlerThread).when(deps).makeHandlerThread();
doReturn(new TestNetIdManager()).when(deps).makeNetIdManager();
doReturn(mNetworkStack).when(deps).getNetworkStack();
- doReturn(systemProperties).when(deps).getSystemProperties();
+ doReturn(mSystemProperties).when(deps).getSystemProperties();
doReturn(mock(ProxyTracker.class)).when(deps).makeProxyTracker(any(), any());
doReturn(mMetricsService).when(deps).getMetricsLogger();
doReturn(true).when(deps).queryUserAccess(anyInt(), anyInt());
@@ -6146,7 +6149,7 @@ public class ConnectivityServiceTest {
// Switching default network updates TCP buffer sizes.
verifyTcpBufferSizeChange(ConnectivityService.DEFAULT_TCP_BUFFER_SIZES);
-
+ verify(mSystemProperties, times(1)).setTcpInitRwnd(eq(TEST_TCP_INIT_RWND));
// Add an IPv4 address. Expect prefix discovery to be stopped. Netd doesn't tell us that
// the NAT64 prefix was removed because one was never discovered.
cellLp.addLinkAddress(myIpv4);
@@ -6583,14 +6586,14 @@ public class ConnectivityServiceTest {
mCellNetworkAgent.connect(false);
networkCallback.expectAvailableCallbacksUnvalidated(mCellNetworkAgent);
verifyTcpBufferSizeChange(ConnectivityService.DEFAULT_TCP_BUFFER_SIZES);
-
+ verify(mSystemProperties, times(1)).setTcpInitRwnd(eq(TEST_TCP_INIT_RWND));
// Change link Properties should have updated tcp buffer size.
LinkProperties lp = new LinkProperties();
lp.setTcpBufferSizes(testTcpBufferSizes);
mCellNetworkAgent.sendLinkProperties(lp);
networkCallback.expectCallback(CallbackEntry.LINK_PROPERTIES_CHANGED, mCellNetworkAgent);
verifyTcpBufferSizeChange(testTcpBufferSizes);
-
+ verify(mSystemProperties, times(2)).setTcpInitRwnd(eq(TEST_TCP_INIT_RWND));
// Clean up.
mCellNetworkAgent.disconnect();
networkCallback.expectCallback(CallbackEntry.LOST, mCellNetworkAgent);
diff --git a/tests/net/java/com/android/server/connectivity/DnsManagerTest.java b/tests/net/java/com/android/server/connectivity/DnsManagerTest.java
index 32bfa7059b0b..f5b85ca06f92 100644
--- a/tests/net/java/com/android/server/connectivity/DnsManagerTest.java
+++ b/tests/net/java/com/android/server/connectivity/DnsManagerTest.java
@@ -98,7 +98,6 @@ public class DnsManagerTest {
@Mock Context mCtx;
@Mock IDnsResolver mMockDnsResolver;
- @Mock MockableSystemProperties mSystemProperties;
private void assertResolverOptionsEquals(
@NonNull ResolverOptionsParcel actual,
@@ -137,7 +136,7 @@ public class DnsManagerTest {
mContentResolver.addProvider(Settings.AUTHORITY,
new FakeSettingsProvider());
when(mCtx.getContentResolver()).thenReturn(mContentResolver);
- mDnsManager = new DnsManager(mCtx, mMockDnsResolver, mSystemProperties);
+ mDnsManager = new DnsManager(mCtx, mMockDnsResolver);
// Clear the private DNS settings
Settings.Global.putString(mContentResolver, PRIVATE_DNS_DEFAULT_MODE, "");
diff --git a/wifi/api/current.txt b/wifi/api/current.txt
index d6e89223ba95..f0cf75c8bf72 100644
--- a/wifi/api/current.txt
+++ b/wifi/api/current.txt
@@ -563,6 +563,7 @@ package android.net.wifi.aware {
method public int getMaxServiceNameLength();
method public int getMaxServiceSpecificInfoLength();
method public int getSupportedCipherSuites();
+ method public boolean isInstantCommunicationModeSupported();
method public void writeToParcel(android.os.Parcel, int);
field @NonNull public static final android.os.Parcelable.Creator<android.net.wifi.aware.Characteristics> CREATOR;
field public static final int WIFI_AWARE_CIPHER_SUITE_NCS_SK_128 = 1; // 0x1
@@ -661,6 +662,7 @@ package android.net.wifi.aware {
method public android.net.wifi.aware.Characteristics getCharacteristics();
method public boolean isAvailable();
method public boolean isDeviceAttached();
+ method public boolean isInstantCommunicationModeEnabled();
field public static final String ACTION_WIFI_AWARE_STATE_CHANGED = "android.net.wifi.aware.action.WIFI_AWARE_STATE_CHANGED";
field public static final int WIFI_AWARE_DATA_PATH_ROLE_INITIATOR = 0; // 0x0
field public static final int WIFI_AWARE_DATA_PATH_ROLE_RESPONDER = 1; // 0x1
diff --git a/wifi/api/system-current.txt b/wifi/api/system-current.txt
index 98cb849084d4..da5888b6adee 100644
--- a/wifi/api/system-current.txt
+++ b/wifi/api/system-current.txt
@@ -263,7 +263,7 @@ package android.net.wifi {
field public static final int BAND_2GHZ = 1; // 0x1
field public static final int BAND_5GHZ = 2; // 0x2
field public static final int BAND_6GHZ = 4; // 0x4
- field public static final int BAND_ANY = 7; // 0x7
+ field @Deprecated public static final int BAND_ANY = 7; // 0x7
field public static final int RANDOMIZATION_NONE = 0; // 0x0
field public static final int RANDOMIZATION_PERSISTENT = 1; // 0x1
}
@@ -800,6 +800,10 @@ package android.net.wifi.aware {
method @Deprecated public android.net.NetworkSpecifier createNetworkSpecifierPmk(@NonNull android.net.wifi.aware.PeerHandle, @NonNull byte[]);
}
+ public class WifiAwareManager {
+ method public void enableInstantCommunicationMode(boolean);
+ }
+
public class WifiAwareSession implements java.lang.AutoCloseable {
method public android.net.NetworkSpecifier createNetworkSpecifierPmk(int, @NonNull byte[], @NonNull byte[]);
}
diff --git a/wifi/java/android/net/wifi/SoftApConfiguration.java b/wifi/java/android/net/wifi/SoftApConfiguration.java
index 237922a6fe1e..2649b66c703f 100644
--- a/wifi/java/android/net/wifi/SoftApConfiguration.java
+++ b/wifi/java/android/net/wifi/SoftApConfiguration.java
@@ -90,6 +90,9 @@ public final class SoftApConfiguration implements Parcelable {
* Device is allowed to choose the optimal band (2Ghz, 5Ghz, 6Ghz) based on device capability,
* operating country code and current radio conditions.
* @hide
+ *
+ * @deprecated The bands are a bit mask - use any combination of {@code BAND_},
+ * for instance {@code BAND_2GHZ | BAND_5GHZ | BAND_6GHZ}.
*/
@SystemApi
public static final int BAND_ANY = BAND_2GHZ | BAND_5GHZ | BAND_6GHZ;
diff --git a/wifi/java/android/net/wifi/WifiConfiguration.java b/wifi/java/android/net/wifi/WifiConfiguration.java
index 7c2556d8cffd..fd4e1ddac3a2 100644
--- a/wifi/java/android/net/wifi/WifiConfiguration.java
+++ b/wifi/java/android/net/wifi/WifiConfiguration.java
@@ -1626,6 +1626,14 @@ public class WifiConfiguration implements Parcelable {
private boolean mHasEverConnected;
/**
+ * Boolean indicating if captive portal has never been detected on this network.
+ *
+ * This should be true by default, for newly created WifiConfigurations until a captive
+ * portal is detected.
+ */
+ private boolean mHasNeverDetectedCaptivePortal = true;
+
+ /**
* set whether this network is visible in latest Qualified Network Selection
* @param seen value set to candidate
* @hide
@@ -1714,6 +1722,19 @@ public class WifiConfiguration implements Parcelable {
return mHasEverConnected;
}
+ /**
+ * Set whether a captive portal has never been detected on this network.
+ * @hide
+ */
+ public void setHasNeverDetectedCaptivePortal(boolean value) {
+ mHasNeverDetectedCaptivePortal = value;
+ }
+
+ /** @hide */
+ public boolean hasNeverDetectedCaptivePortal() {
+ return mHasNeverDetectedCaptivePortal;
+ }
+
/** @hide */
public NetworkSelectionStatus() {
// previously stored configs will not have this parameter, so we default to false.
@@ -1989,6 +2010,7 @@ public class WifiConfiguration implements Parcelable {
setCandidateScore(source.getCandidateScore());
setConnectChoice(source.getConnectChoice());
setHasEverConnected(source.hasEverConnected());
+ setHasNeverDetectedCaptivePortal(source.hasNeverDetectedCaptivePortal());
}
/** @hide */
@@ -2008,6 +2030,7 @@ public class WifiConfiguration implements Parcelable {
dest.writeInt(CONNECT_CHOICE_NOT_EXISTS);
}
dest.writeInt(hasEverConnected() ? 1 : 0);
+ dest.writeInt(hasNeverDetectedCaptivePortal() ? 1 : 0);
}
/** @hide */
@@ -2026,6 +2049,7 @@ public class WifiConfiguration implements Parcelable {
setConnectChoice(null);
}
setHasEverConnected(in.readInt() != 0);
+ setHasNeverDetectedCaptivePortal(in.readInt() != 0);
}
}
@@ -2287,6 +2311,8 @@ public class WifiConfiguration implements Parcelable {
}
sbuf.append(" hasEverConnected: ")
.append(mNetworkSelectionStatus.hasEverConnected()).append("\n");
+ sbuf.append(" hasNeverDetectedCaptivePortal: ")
+ .append(mNetworkSelectionStatus.hasNeverDetectedCaptivePortal()).append("\n");
if (this.numAssociation > 0) {
sbuf.append(" numAssociation ").append(this.numAssociation).append("\n");
diff --git a/wifi/java/android/net/wifi/aware/Characteristics.java b/wifi/java/android/net/wifi/aware/Characteristics.java
index d5fd48e9e7b3..116786516b3b 100644
--- a/wifi/java/android/net/wifi/aware/Characteristics.java
+++ b/wifi/java/android/net/wifi/aware/Characteristics.java
@@ -17,6 +17,7 @@
package android.net.wifi.aware;
import android.annotation.IntDef;
+import android.net.wifi.util.SdkLevelUtil;
import android.os.Bundle;
import android.os.Parcel;
import android.os.Parcelable;
@@ -37,6 +38,9 @@ public final class Characteristics implements Parcelable {
public static final String KEY_MAX_MATCH_FILTER_LENGTH = "key_max_match_filter_length";
/** @hide */
public static final String KEY_SUPPORTED_CIPHER_SUITES = "key_supported_cipher_suites";
+ /** @hide */
+ public static final String KEY_IS_INSTANT_COMMUNICATION_MODE_SUPPORTED =
+ "key_is_instant_communication_mode_supported";
private Bundle mCharacteristics = new Bundle();
@@ -83,6 +87,17 @@ public final class Characteristics implements Parcelable {
return mCharacteristics.getInt(KEY_MAX_MATCH_FILTER_LENGTH);
}
+ /**
+ * Check if instant communication mode is supported by device.
+ * @return True if supported, false otherwise.
+ */
+ public boolean isInstantCommunicationModeSupported() {
+ if (!SdkLevelUtil.isAtLeastS()) {
+ throw new UnsupportedOperationException();
+ }
+ return mCharacteristics.getBoolean(KEY_IS_INSTANT_COMMUNICATION_MODE_SUPPORTED);
+ }
+
/** @hide */
@IntDef(flag = true, prefix = { "WIFI_AWARE_CIPHER_SUITE_" }, value = {
WIFI_AWARE_CIPHER_SUITE_NCS_SK_128,
diff --git a/wifi/java/android/net/wifi/aware/IWifiAwareManager.aidl b/wifi/java/android/net/wifi/aware/IWifiAwareManager.aidl
index f5b1edce1d69..cd2ca692137d 100644
--- a/wifi/java/android/net/wifi/aware/IWifiAwareManager.aidl
+++ b/wifi/java/android/net/wifi/aware/IWifiAwareManager.aidl
@@ -37,6 +37,8 @@ interface IWifiAwareManager
boolean isUsageEnabled();
Characteristics getCharacteristics();
boolean isDeviceAttached();
+ void enableInstantCommunicationMode(in String callingPackage, boolean enable);
+ boolean isInstantCommunicationModeEnabled();
// client API
void connect(in IBinder binder, in String callingPackage, in String callingFeatureId,
diff --git a/wifi/java/android/net/wifi/aware/WifiAwareManager.java b/wifi/java/android/net/wifi/aware/WifiAwareManager.java
index 03f5f401fc40..bb146e37d48c 100644
--- a/wifi/java/android/net/wifi/aware/WifiAwareManager.java
+++ b/wifi/java/android/net/wifi/aware/WifiAwareManager.java
@@ -22,12 +22,14 @@ import android.annotation.Nullable;
import android.annotation.RequiresPermission;
import android.annotation.SdkConstant;
import android.annotation.SdkConstant.SdkConstantType;
+import android.annotation.SystemApi;
import android.annotation.SystemService;
import android.content.Context;
import android.net.ConnectivityManager;
import android.net.NetworkRequest;
import android.net.NetworkSpecifier;
import android.net.wifi.util.HexEncoding;
+import android.net.wifi.util.SdkLevelUtil;
import android.os.Binder;
import android.os.Build;
import android.os.Bundle;
@@ -208,6 +210,9 @@ public class WifiAwareManager {
* or not (false).
*/
public boolean isDeviceAttached() {
+ if (!SdkLevelUtil.isAtLeastS()) {
+ throw new UnsupportedOperationException();
+ }
try {
return mService.isDeviceAttached();
} catch (RemoteException e) {
@@ -216,6 +221,42 @@ public class WifiAwareManager {
}
/**
+ * Enable the Wifi Aware Instant communication mode. If the device doesn't support this feature
+ * calling this API will result no action.
+ * @see Characteristics#isInstantCommunicationModeSupported()
+ * @param enable true for enable, false otherwise.
+ * @hide
+ */
+ @SystemApi
+ public void enableInstantCommunicationMode(boolean enable) {
+ if (!SdkLevelUtil.isAtLeastS()) {
+ throw new UnsupportedOperationException();
+ }
+ try {
+ mService.enableInstantCommunicationMode(mContext.getOpPackageName(), enable);
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
+
+ /**
+ * Return the current status of the Wifi Aware instant communication mode.
+ * If the device doesn't support this feature, return will always be false.
+ * @see Characteristics#isInstantCommunicationModeSupported()
+ * @return true if it is enabled, false otherwise.
+ */
+ public boolean isInstantCommunicationModeEnabled() {
+ if (!SdkLevelUtil.isAtLeastS()) {
+ throw new UnsupportedOperationException();
+ }
+ try {
+ return mService.isInstantCommunicationModeEnabled();
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
+
+ /**
* Returns the characteristics of the Wi-Fi Aware interface: a set of parameters which specify
* limitations on configurations, e.g. the maximum service name length.
*
diff --git a/wifi/tests/src/android/net/wifi/aware/WifiAwareManagerTest.java b/wifi/tests/src/android/net/wifi/aware/WifiAwareManagerTest.java
index d163fb0e6adf..2cf7f2c1b8cf 100644
--- a/wifi/tests/src/android/net/wifi/aware/WifiAwareManagerTest.java
+++ b/wifi/tests/src/android/net/wifi/aware/WifiAwareManagerTest.java
@@ -22,6 +22,7 @@ import static android.net.wifi.aware.WifiAwareNetworkSpecifier.NETWORK_SPECIFIER
import static org.hamcrest.core.IsEqual.equalTo;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
+import static org.junit.Assume.assumeTrue;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.anyString;
@@ -38,6 +39,7 @@ import android.content.pm.PackageManager;
import android.net.MacAddress;
import android.net.wifi.RttManager;
import android.net.wifi.util.HexEncoding;
+import android.net.wifi.util.SdkLevelUtil;
import android.os.Build;
import android.os.Handler;
import android.os.IBinder;
@@ -156,6 +158,19 @@ public class WifiAwareManagerTest {
verify(mockAwareService).isDeviceAttached();
}
+ /**
+ * Validate pass-through of isInstantCommunicationModeEnabled() and
+ * enableInstantCommunicationMode() API
+ */
+ @Test
+ public void testEnableInstantCommunicationMode() throws Exception {
+ assumeTrue(SdkLevelUtil.isAtLeastS());
+ mDut.isInstantCommunicationModeEnabled();
+ verify(mockAwareService).isInstantCommunicationModeEnabled();
+ mDut.enableInstantCommunicationMode(true);
+ verify(mockAwareService).enableInstantCommunicationMode(anyString(), eq(true));
+ }
+
/*
* WifiAwareEventCallbackProxy Tests
*/