summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Android.bp20
-rw-r--r--apex/Android.bp17
-rw-r--r--apex/media/framework/api/current.txt3
-rw-r--r--apex/media/framework/java/android/media/MediaParser.java147
-rw-r--r--apex/permission/framework/Android.bp4
-rw-r--r--apex/permission/service/Android.bp1
-rw-r--r--apex/statsd/tests/libstatspull/src/com/android/internal/os/statsd/libstats/LibStatsPullTests.java4
-rw-r--r--api/current.txt45
-rwxr-xr-xapi/system-current.txt115
-rw-r--r--cmds/screencap/screencap.cpp38
-rw-r--r--cmds/statsd/Android.bp1
-rw-r--r--cmds/statsd/src/StatsLogProcessor.cpp1
-rw-r--r--cmds/statsd/src/StatsService.cpp23
-rw-r--r--cmds/statsd/src/atoms.proto186
-rw-r--r--cmds/statsd/src/external/PullUidProvider.h39
-rw-r--r--cmds/statsd/src/external/StatsPullerManager.cpp127
-rw-r--r--cmds/statsd/src/external/StatsPullerManager.h53
-rw-r--r--cmds/statsd/src/guardrail/StatsdStats.h2
-rw-r--r--cmds/statsd/src/logd/LogEvent.cpp2
-rw-r--r--cmds/statsd/src/metrics/GaugeMetricProducer.cpp20
-rw-r--r--cmds/statsd/src/metrics/GaugeMetricProducer.h6
-rw-r--r--cmds/statsd/src/metrics/MetricProducer.h6
-rw-r--r--cmds/statsd/src/metrics/MetricsManager.cpp102
-rw-r--r--cmds/statsd/src/metrics/MetricsManager.h30
-rw-r--r--cmds/statsd/src/metrics/ValueMetricProducer.cpp17
-rw-r--r--cmds/statsd/src/metrics/ValueMetricProducer.h2
-rw-r--r--cmds/statsd/src/metrics/metrics_manager_util.cpp6
-rw-r--r--cmds/statsd/src/packages/UidMap.cpp8
-rw-r--r--cmds/statsd/src/packages/UidMap.h2
-rw-r--r--cmds/statsd/src/shell/ShellSubscriber.cpp26
-rw-r--r--cmds/statsd/src/shell/ShellSubscriber.h19
-rw-r--r--cmds/statsd/src/shell/shell_config.proto3
-rw-r--r--cmds/statsd/src/statsd_config.proto10
-rw-r--r--cmds/statsd/tests/MetricsManager_test.cpp125
-rw-r--r--cmds/statsd/tests/e2e/GaugeMetric_e2e_pull_test.cpp1
-rw-r--r--cmds/statsd/tests/e2e/PartialBucket_e2e_test.cpp2
-rw-r--r--cmds/statsd/tests/e2e/ValueMetric_pull_e2e_test.cpp1
-rw-r--r--cmds/statsd/tests/external/StatsCallbackPuller_test.cpp5
-rw-r--r--cmds/statsd/tests/external/StatsPullerManager_test.cpp150
-rw-r--r--cmds/statsd/tests/metrics/GaugeMetricProducer_test.cpp107
-rw-r--r--cmds/statsd/tests/metrics/ValueMetricProducer_test.cpp622
-rw-r--r--cmds/statsd/tests/metrics/metrics_test_helper.h17
-rw-r--r--cmds/statsd/tests/shell/ShellSubscriber_test.cpp6
-rw-r--r--cmds/statsd/tools/localtools/src/com/android/statsd/shelltools/testdrive/TestDrive.java41
-rw-r--r--core/java/android/app/ActivityManagerInternal.java9
-rw-r--r--core/java/android/app/AppOpsManager.java2
-rw-r--r--core/java/android/app/ContextImpl.java4
-rw-r--r--core/java/android/app/IActivityManager.aidl3
-rw-r--r--core/java/android/app/IActivityTaskManager.aidl11
-rw-r--r--core/java/android/app/SystemServiceRegistry.java2
-rw-r--r--core/java/android/app/TaskEmbedder.java24
-rw-r--r--core/java/android/content/Context.java9
-rw-r--r--core/java/android/content/ContextWrapper.java8
-rw-r--r--core/java/android/content/pm/DataLoaderParams.java22
-rw-r--r--core/java/android/content/pm/DataLoaderParamsParcel.aidl2
-rw-r--r--core/java/android/content/pm/PackageParser.java10
-rw-r--r--core/java/android/content/pm/parsing/ParsingPackageImpl.java4
-rw-r--r--core/java/android/content/pm/parsing/ParsingPackageUtils.java29
-rw-r--r--core/java/android/hardware/biometrics/BiometricConstants.java14
-rw-r--r--core/java/android/hardware/biometrics/BiometricPrompt.java37
-rw-r--r--core/java/android/hardware/biometrics/IBiometricServiceReceiver.aidl2
-rw-r--r--core/java/android/hardware/biometrics/IBiometricServiceReceiverInternal.aidl2
-rw-r--r--core/java/android/hardware/soundtrigger/ConversionUtil.java26
-rw-r--r--core/java/android/hardware/soundtrigger/SoundTrigger.java445
-rw-r--r--core/java/android/net/ConnectivityManager.java30
-rw-r--r--core/java/android/net/NetworkAgent.java160
-rw-r--r--core/java/android/net/NetworkAgentConfig.java3
-rw-r--r--core/java/android/net/NetworkCapabilities.java2
-rw-r--r--core/java/android/net/NetworkProvider.java16
-rw-r--r--core/java/android/net/NetworkRequest.java4
-rw-r--r--core/java/android/net/NetworkSpecifier.java4
-rw-r--r--core/java/android/net/SocketKeepalive.java11
-rw-r--r--core/java/android/net/StringNetworkSpecifier.java2
-rw-r--r--core/java/android/net/TelephonyNetworkSpecifier.java2
-rw-r--r--core/java/android/os/IVibratorService.aidl2
-rw-r--r--core/java/android/os/Process.java12
-rw-r--r--core/java/android/os/RecoverySystem.java17
-rw-r--r--core/java/android/os/SystemVibrator.java11
-rw-r--r--core/java/android/os/VibrationEffect.java12
-rw-r--r--core/java/android/os/Vibrator.java94
-rw-r--r--core/java/android/os/ZygoteProcess.java38
-rw-r--r--core/java/android/provider/Settings.java27
-rw-r--r--core/java/android/provider/Telephony.java1
-rw-r--r--core/java/android/security/FileIntegrityManager.java7
-rw-r--r--core/java/android/security/IFileIntegrityService.aidl2
-rw-r--r--core/java/android/service/contentcapture/ContentCaptureService.java2
-rw-r--r--core/java/android/service/controls/ControlsProviderService.java7
-rw-r--r--core/java/android/service/dataloader/DataLoaderService.java11
-rw-r--r--core/java/android/service/dreams/DreamService.java3
-rw-r--r--core/java/android/service/voice/AlwaysOnHotwordDetector.java2
-rw-r--r--core/java/android/telephony/PhoneStateListener.java38
-rw-r--r--core/java/android/view/InsetsController.java30
-rw-r--r--core/java/android/view/InsetsSource.java7
-rw-r--r--core/java/android/view/InsetsState.java30
-rw-r--r--core/java/android/view/PendingInsetsController.java9
-rw-r--r--core/java/android/view/Surface.java16
-rw-r--r--core/java/android/view/SurfaceControl.java8
-rw-r--r--core/java/android/view/View.java5
-rw-r--r--core/java/android/view/ViewConfiguration.java38
-rw-r--r--core/java/android/view/ViewRootImpl.java17
-rw-r--r--core/java/android/view/Window.java5
-rw-r--r--core/java/android/view/WindowInsets.java1
-rw-r--r--core/java/android/view/WindowInsetsController.java9
-rw-r--r--core/java/android/view/WindowManager.java12
-rw-r--r--core/java/android/view/autofill/AutofillManager.java49
-rw-r--r--core/java/android/view/autofill/IAutoFillManagerClient.aidl5
-rw-r--r--core/java/android/view/contentcapture/ContentCaptureContext.java2
-rw-r--r--core/java/android/view/contentcapture/ContentCaptureEvent.java2
-rw-r--r--core/java/android/view/contentcapture/ContentCaptureManager.java7
-rw-r--r--core/java/android/view/contentcapture/ContentCaptureSession.java9
-rw-r--r--core/java/com/android/internal/os/Zygote.java29
-rw-r--r--core/java/com/android/internal/os/ZygoteArguments.java15
-rw-r--r--core/java/com/android/internal/os/ZygoteConnection.java3
-rw-r--r--core/java/com/android/internal/policy/DecorView.java37
-rw-r--r--core/java/com/android/internal/widget/DecorCaptionView.java29
-rw-r--r--core/jni/android_util_AssetManager.cpp4
-rw-r--r--core/jni/com_android_internal_os_Zygote.cpp109
-rw-r--r--core/proto/android/providers/settings/secure.proto12
-rw-r--r--core/res/res/values/attrs_manifest.xml32
-rw-r--r--core/res/res/values/config.xml7
-rw-r--r--core/res/res/values/public.xml3
-rw-r--r--core/res/res/values/strings.xml14
-rw-r--r--core/res/res/values/symbols.xml4
-rw-r--r--core/tests/coretests/src/android/service/controls/ControlProviderServiceTest.java9
-rw-r--r--core/tests/coretests/src/android/view/InsetsControllerTest.java22
-rw-r--r--core/tests/coretests/src/android/view/InsetsStateTest.java29
-rw-r--r--core/tests/coretests/src/android/widget/EditorCursorDragTest.java1
-rw-r--r--data/etc/privapp-permissions-platform.xml4
-rw-r--r--graphics/java/android/graphics/drawable/AdaptiveIconDrawable.java1
-rw-r--r--libs/androidfw/Android.bp1
-rw-r--r--libs/androidfw/AssetManager2.cpp73
-rw-r--r--libs/androidfw/DynamicLibManager.cpp34
-rw-r--r--libs/androidfw/include/androidfw/AssetManager2.h13
-rw-r--r--libs/androidfw/include/androidfw/DynamicLibManager.h48
-rw-r--r--libs/androidfw/include/androidfw/MutexGuard.h3
-rw-r--r--libs/androidfw/tests/AssetManager2_test.cpp63
-rw-r--r--libs/hwui/renderthread/CanvasContext.cpp8
-rw-r--r--media/java/android/media/AudioDeviceInfo.java4
-rw-r--r--media/java/android/media/AudioManager.java22
-rw-r--r--media/java/android/media/AudioMetadata.java95
-rw-r--r--media/java/android/media/AudioMetadataMap.java59
-rw-r--r--media/java/android/media/AudioMetadataReadMap.java81
-rw-r--r--media/java/android/media/AudioTrack.java101
-rw-r--r--media/java/android/media/IAudioService.aidl2
-rw-r--r--media/java/android/media/MediaRoute2Info.java36
-rw-r--r--media/java/android/media/soundtrigger/SoundTriggerManager.java10
-rw-r--r--media/packages/BluetoothMidiService/src/com/android/bluetoothmidiservice/BluetoothPacketDecoder.java80
-rw-r--r--packages/SettingsLib/res/values/strings.xml8
-rw-r--r--packages/SettingsLib/src/com/android/settingslib/media/LocalMediaManager.java37
-rw-r--r--packages/SettingsProvider/src/android/provider/settings/backup/SecureSettings.java3
-rw-r--r--packages/SettingsProvider/src/android/provider/settings/validators/SecureSettingsValidators.java7
-rw-r--r--packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java11
-rw-r--r--packages/Shell/src/com/android/shell/BugreportProgressService.java4
-rw-r--r--packages/SystemUI/res/drawable/control_background_ripple.xml23
-rw-r--r--packages/SystemUI/res/drawable/ic_device_air_freshener_off.xml43
-rw-r--r--packages/SystemUI/res/drawable/ic_device_air_freshener_on.xml43
-rw-r--r--packages/SystemUI/res/drawable/ic_device_air_purifier_off.xml34
-rw-r--r--packages/SystemUI/res/drawable/ic_device_air_purifier_on.xml34
-rw-r--r--packages/SystemUI/res/drawable/ic_device_blinds_off.xml25
-rw-r--r--packages/SystemUI/res/drawable/ic_device_blinds_on.xml25
-rw-r--r--packages/SystemUI/res/drawable/ic_device_camera_off.xml25
-rw-r--r--packages/SystemUI/res/drawable/ic_device_camera_on.xml25
-rw-r--r--packages/SystemUI/res/drawable/ic_device_dishwasher_off.xml34
-rw-r--r--packages/SystemUI/res/drawable/ic_device_dishwasher_on.xml25
-rw-r--r--packages/SystemUI/res/drawable/ic_device_doorbell_off.xml34
-rw-r--r--packages/SystemUI/res/drawable/ic_device_doorbell_on.xml28
-rw-r--r--packages/SystemUI/res/drawable/ic_device_drawer_off.xml28
-rw-r--r--packages/SystemUI/res/drawable/ic_device_drawer_on.xml25
-rw-r--r--packages/SystemUI/res/drawable/ic_device_fan_off.xml25
-rw-r--r--packages/SystemUI/res/drawable/ic_device_fan_on.xml25
-rw-r--r--packages/SystemUI/res/drawable/ic_device_garage_off.xml28
-rw-r--r--packages/SystemUI/res/drawable/ic_device_garage_on.xml28
-rw-r--r--packages/SystemUI/res/drawable/ic_device_gate_off.xml31
-rw-r--r--packages/SystemUI/res/drawable/ic_device_gate_on.xml34
-rw-r--r--packages/SystemUI/res/drawable/ic_device_hood_off.xml28
-rw-r--r--packages/SystemUI/res/drawable/ic_device_hood_on.xml28
-rw-r--r--packages/SystemUI/res/drawable/ic_device_kettle_off.xml31
-rw-r--r--packages/SystemUI/res/drawable/ic_device_kettle_on.xml28
-rw-r--r--packages/SystemUI/res/drawable/ic_device_light_off.xml31
-rw-r--r--packages/SystemUI/res/drawable/ic_device_light_on.xml31
-rw-r--r--packages/SystemUI/res/drawable/ic_device_lock_off.xml28
-rw-r--r--packages/SystemUI/res/drawable/ic_device_lock_on.xml25
-rw-r--r--packages/SystemUI/res/drawable/ic_device_microwave_off.xml37
-rw-r--r--packages/SystemUI/res/drawable/ic_device_microwave_on.xml25
-rw-r--r--packages/SystemUI/res/drawable/ic_device_mop_off.xml25
-rw-r--r--packages/SystemUI/res/drawable/ic_device_mop_on.xml25
-rw-r--r--packages/SystemUI/res/drawable/ic_device_multicooker_off.xml34
-rw-r--r--packages/SystemUI/res/drawable/ic_device_multicooker_on.xml31
-rw-r--r--packages/SystemUI/res/drawable/ic_device_outlet_off.xml34
-rw-r--r--packages/SystemUI/res/drawable/ic_device_outlet_on.xml25
-rw-r--r--packages/SystemUI/res/drawable/ic_device_pergola_off.xml28
-rw-r--r--packages/SystemUI/res/drawable/ic_device_pergola_on.xml28
-rw-r--r--packages/SystemUI/res/drawable/ic_device_refrigerator_off.xml25
-rw-r--r--packages/SystemUI/res/drawable/ic_device_refrigerator_on.xml28
-rw-r--r--packages/SystemUI/res/drawable/ic_device_remote_control_off.xml46
-rw-r--r--packages/SystemUI/res/drawable/ic_device_remote_control_on.xml28
-rw-r--r--packages/SystemUI/res/drawable/ic_device_security_system_off.xml28
-rw-r--r--packages/SystemUI/res/drawable/ic_device_security_system_on.xml25
-rw-r--r--packages/SystemUI/res/drawable/ic_device_set_top_off.xml34
-rw-r--r--packages/SystemUI/res/drawable/ic_device_set_top_on.xml25
-rw-r--r--packages/SystemUI/res/drawable/ic_device_sprinkler_off.xml52
-rw-r--r--packages/SystemUI/res/drawable/ic_device_sprinkler_on.xml52
-rw-r--r--packages/SystemUI/res/drawable/ic_device_styler_off.xml25
-rw-r--r--packages/SystemUI/res/drawable/ic_device_styler_on.xml25
-rw-r--r--packages/SystemUI/res/drawable/ic_device_switch_off.xml31
-rw-r--r--packages/SystemUI/res/drawable/ic_device_switch_on.xml28
-rw-r--r--packages/SystemUI/res/drawable/ic_device_thermostat_gm2_24px.xml9
-rw-r--r--packages/SystemUI/res/drawable/ic_device_thermostat_off.xml25
-rw-r--r--packages/SystemUI/res/drawable/ic_device_thermostat_on.xml25
-rw-r--r--packages/SystemUI/res/drawable/ic_device_tv_off.xml25
-rw-r--r--packages/SystemUI/res/drawable/ic_device_tv_on.xml25
-rw-r--r--packages/SystemUI/res/drawable/ic_device_vacuum_off.xml25
-rw-r--r--packages/SystemUI/res/drawable/ic_device_vacuum_on.xml28
-rw-r--r--packages/SystemUI/res/drawable/ic_device_valve_off.xml28
-rw-r--r--packages/SystemUI/res/drawable/ic_device_valve_on.xml28
-rw-r--r--packages/SystemUI/res/drawable/ic_device_washer_off.xml34
-rw-r--r--packages/SystemUI/res/drawable/ic_device_washer_on.xml25
-rw-r--r--packages/SystemUI/res/drawable/ic_device_water_heater_off.xml28
-rw-r--r--packages/SystemUI/res/drawable/ic_device_water_heater_on.xml28
-rw-r--r--packages/SystemUI/res/drawable/ic_device_window_off.xml25
-rw-r--r--packages/SystemUI/res/drawable/ic_device_window_on.xml25
-rw-r--r--packages/SystemUI/res/drawable/ic_light_off_gm2_24px.xml19
-rw-r--r--packages/SystemUI/res/drawable/ic_lightbulb_outline_gm2_24px.xml9
-rw-r--r--packages/SystemUI/res/drawable/ic_lock_gm2_24px.xml9
-rw-r--r--packages/SystemUI/res/drawable/ic_lock_open_gm2_24px.xml12
-rw-r--r--packages/SystemUI/res/drawable/ic_power_gm2_24px.xml9
-rw-r--r--packages/SystemUI/res/drawable/ic_power_off_gm2_24px.xml9
-rw-r--r--packages/SystemUI/res/drawable/ic_switches_gm2_24px.xml9
-rw-r--r--packages/SystemUI/res/drawable/ic_vacuum_gm2_24px.xml9
-rw-r--r--packages/SystemUI/res/drawable/ic_videocam_gm2_24px.xml9
-rw-r--r--packages/SystemUI/res/layout-land/auth_credential_pattern_view.xml11
-rw-r--r--packages/SystemUI/res/layout/auth_biometric_contents.xml16
-rw-r--r--packages/SystemUI/res/layout/auth_credential_password_view.xml21
-rw-r--r--packages/SystemUI/res/layout/auth_credential_pattern_view.xml11
-rw-r--r--packages/SystemUI/res/layout/controls_base_item.xml45
-rw-r--r--packages/SystemUI/res/values-television/dimens.xml20
-rw-r--r--packages/SystemUI/res/values-television/styles.xml5
-rw-r--r--packages/SystemUI/res/values/dimens.xml3
-rw-r--r--packages/SystemUI/res/values/strings.xml4
-rw-r--r--packages/SystemUI/res/values/styles.xml34
-rw-r--r--packages/SystemUI/shared/src/com/android/systemui/shared/system/ActivityManagerWrapper.java14
-rw-r--r--packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java39
-rw-r--r--packages/SystemUI/src/com/android/systemui/biometrics/AuthContainerView.java9
-rw-r--r--packages/SystemUI/src/com/android/systemui/biometrics/AuthController.java13
-rw-r--r--packages/SystemUI/src/com/android/systemui/biometrics/AuthCredentialPasswordView.java2
-rw-r--r--packages/SystemUI/src/com/android/systemui/biometrics/AuthDialogCallback.java7
-rw-r--r--packages/SystemUI/src/com/android/systemui/bubbles/BadgedImageView.java117
-rw-r--r--packages/SystemUI/src/com/android/systemui/bubbles/Bubble.java37
-rw-r--r--packages/SystemUI/src/com/android/systemui/bubbles/BubbleController.java8
-rw-r--r--packages/SystemUI/src/com/android/systemui/bubbles/BubbleData.java2
-rw-r--r--packages/SystemUI/src/com/android/systemui/bubbles/BubbleOverflow.java2
-rw-r--r--packages/SystemUI/src/com/android/systemui/bubbles/BubbleOverflowActivity.java2
-rw-r--r--packages/SystemUI/src/com/android/systemui/bubbles/BubbleStackView.java42
-rw-r--r--packages/SystemUI/src/com/android/systemui/bubbles/animation/StackAnimationController.java2
-rw-r--r--packages/SystemUI/src/com/android/systemui/controls/controller/ControlsControllerImpl.kt17
-rw-r--r--packages/SystemUI/src/com/android/systemui/controls/management/ControlAdapter.kt9
-rw-r--r--packages/SystemUI/src/com/android/systemui/controls/ui/RenderInfo.kt156
-rw-r--r--packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsImpl.java8
-rw-r--r--packages/SystemUI/src/com/android/systemui/pip/PipTaskOrganizer.java62
-rw-r--r--packages/SystemUI/src/com/android/systemui/pip/phone/PipManager.java3
-rw-r--r--packages/SystemUI/src/com/android/systemui/pip/phone/PipMotionHelper.java6
-rw-r--r--packages/SystemUI/src/com/android/systemui/pip/tv/PipManager.java3
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/PagedTileLayout.java3
-rw-r--r--packages/SystemUI/src/com/android/systemui/recents/RecentsOnboarding.java6
-rw-r--r--packages/SystemUI/src/com/android/systemui/stackdivider/Divider.java14
-rw-r--r--packages/SystemUI/src/com/android/systemui/stackdivider/DividerView.java9
-rw-r--r--packages/SystemUI/src/com/android/systemui/stackdivider/SplitScreenTaskOrganizer.java24
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/KeyguardIndicationController.java32
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/EdgeBackGestureHandler.java2
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBouncer.java3
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/policy/BatteryControllerImpl.java6
-rw-r--r--packages/SystemUI/src/com/android/systemui/usb/StorageNotification.java23
-rw-r--r--packages/SystemUI/tests/src/com/android/keyguard/KeyguardUpdateMonitorTest.java20
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/biometrics/AuthContainerViewTest.java3
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/controls/controller/ControlsControllerImplTest.kt46
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/KeyguardIndicationControllerTest.java6
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/KeyguardBouncerTest.java13
-rw-r--r--packages/Tethering/common/TetheringLib/Android.bp7
-rw-r--r--packages/Tethering/src/com/android/server/connectivity/tethering/Tethering.java31
-rw-r--r--packages/Tethering/src/com/android/server/connectivity/tethering/TetheringService.java1
-rw-r--r--packages/Tethering/tests/unit/src/com/android/server/connectivity/tethering/TetheringTest.java1
-rw-r--r--services/Android.bp1
-rw-r--r--services/contentcapture/java/com/android/server/contentcapture/ContentCapturePerUserService.java2
-rw-r--r--services/contentcapture/java/com/android/server/contentcapture/ContentCaptureServerSession.java2
-rw-r--r--services/core/java/com/android/server/ConnectivityService.java9
-rw-r--r--services/core/java/com/android/server/NetworkManagementService.java1
-rw-r--r--services/core/java/com/android/server/PackageWatchdog.java13
-rw-r--r--services/core/java/com/android/server/StorageManagerService.java3
-rw-r--r--services/core/java/com/android/server/TelephonyRegistry.java74
-rw-r--r--services/core/java/com/android/server/VibratorService.java17
-rw-r--r--services/core/java/com/android/server/am/ActiveServices.java9
-rw-r--r--services/core/java/com/android/server/am/ActivityManagerService.java25
-rw-r--r--services/core/java/com/android/server/am/OomAdjuster.java22
-rw-r--r--services/core/java/com/android/server/am/ProcessList.java74
-rw-r--r--services/core/java/com/android/server/am/UserController.java9
-rw-r--r--services/core/java/com/android/server/appop/AppOpsService.java40
-rw-r--r--services/core/java/com/android/server/audio/AudioService.java37
-rw-r--r--services/core/java/com/android/server/biometrics/AuthService.java3
-rw-r--r--services/core/java/com/android/server/biometrics/BiometricService.java32
-rw-r--r--services/core/java/com/android/server/hdmi/README.md7
-rw-r--r--services/core/java/com/android/server/hdmi/cec_key_handling.md36
-rw-r--r--services/core/java/com/android/server/incident/PendingReports.java2
-rw-r--r--services/core/java/com/android/server/input/InputManagerService.java6
-rw-r--r--services/core/java/com/android/server/location/RemoteListenerHelper.java2
-rw-r--r--services/core/java/com/android/server/location/gnss/ExponentialBackOff.java (renamed from services/core/java/com/android/server/location/ExponentialBackOff.java)18
-rw-r--r--services/core/java/com/android/server/location/gnss/GnssAntennaInfoProvider.java (renamed from services/core/java/com/android/server/location/GnssAntennaInfoProvider.java)4
-rw-r--r--services/core/java/com/android/server/location/gnss/GnssBatchingProvider.java (renamed from services/core/java/com/android/server/location/GnssBatchingProvider.java)18
-rw-r--r--services/core/java/com/android/server/location/gnss/GnssCapabilitiesProvider.java (renamed from services/core/java/com/android/server/location/GnssCapabilitiesProvider.java)4
-rw-r--r--services/core/java/com/android/server/location/gnss/GnssConfiguration.java (renamed from services/core/java/com/android/server/location/GnssConfiguration.java)4
-rw-r--r--services/core/java/com/android/server/location/gnss/GnssGeofenceProvider.java (renamed from services/core/java/com/android/server/location/GnssGeofenceProvider.java)18
-rw-r--r--services/core/java/com/android/server/location/gnss/GnssLocationProvider.java (renamed from services/core/java/com/android/server/location/GnssLocationProvider.java)9
-rw-r--r--services/core/java/com/android/server/location/gnss/GnssManagerService.java8
-rw-r--r--services/core/java/com/android/server/location/gnss/GnssMeasurementCorrectionsProvider.java (renamed from services/core/java/com/android/server/location/GnssMeasurementCorrectionsProvider.java)4
-rw-r--r--services/core/java/com/android/server/location/gnss/GnssMeasurementsProvider.java (renamed from services/core/java/com/android/server/location/GnssMeasurementsProvider.java)6
-rw-r--r--services/core/java/com/android/server/location/gnss/GnssNavigationMessageProvider.java (renamed from services/core/java/com/android/server/location/GnssNavigationMessageProvider.java)6
-rw-r--r--services/core/java/com/android/server/location/gnss/GnssNetworkConnectivityHandler.java (renamed from services/core/java/com/android/server/location/GnssNetworkConnectivityHandler.java)4
-rw-r--r--services/core/java/com/android/server/location/gnss/GnssPositionMode.java (renamed from services/core/java/com/android/server/location/GnssPositionMode.java)18
-rw-r--r--services/core/java/com/android/server/location/gnss/GnssSatelliteBlacklistHelper.java (renamed from services/core/java/com/android/server/location/GnssSatelliteBlacklistHelper.java)18
-rw-r--r--services/core/java/com/android/server/location/gnss/GnssStatusListenerHelper.java (renamed from services/core/java/com/android/server/location/GnssStatusListenerHelper.java)9
-rw-r--r--services/core/java/com/android/server/location/gnss/GnssVisibilityControl.java (renamed from services/core/java/com/android/server/location/GnssVisibilityControl.java)4
-rw-r--r--services/core/java/com/android/server/location/gnss/GpsPsdsDownloader.java (renamed from services/core/java/com/android/server/location/GpsPsdsDownloader.java)4
-rw-r--r--services/core/java/com/android/server/location/gnss/NtpTimeHelper.java (renamed from services/core/java/com/android/server/location/NtpTimeHelper.java)19
-rw-r--r--services/core/java/com/android/server/locksettings/LockSettingsService.java6
-rw-r--r--services/core/java/com/android/server/locksettings/RebootEscrowManager.java144
-rw-r--r--services/core/java/com/android/server/media/MediaRouter2ServiceImpl.java22
-rw-r--r--services/core/java/com/android/server/media/SystemMediaRoute2Provider.java32
-rw-r--r--services/core/java/com/android/server/notification/BubbleExtractor.java3
-rwxr-xr-xservices/core/java/com/android/server/notification/NotificationManagerService.java57
-rw-r--r--services/core/java/com/android/server/notification/NotificationRecord.java14
-rw-r--r--services/core/java/com/android/server/pm/PackageInstallerSession.java3
-rw-r--r--services/core/java/com/android/server/pm/PackageManagerShellCommand.java39
-rw-r--r--services/core/java/com/android/server/pm/PackageManagerShellCommandDataLoader.java105
-rw-r--r--services/core/java/com/android/server/pm/permission/PermissionManagerService.java76
-rw-r--r--services/core/java/com/android/server/policy/PhoneWindowManager.java3
-rw-r--r--services/core/java/com/android/server/policy/WindowManagerPolicy.java4
-rw-r--r--services/core/java/com/android/server/security/FileIntegrityService.java43
-rw-r--r--services/core/java/com/android/server/soundtrigger_middleware/SoundTriggerMiddlewareValidation.java53
-rw-r--r--services/core/java/com/android/server/wm/ActivityRecord.java2
-rw-r--r--services/core/java/com/android/server/wm/ActivityStack.java14
-rw-r--r--services/core/java/com/android/server/wm/ActivityTaskManagerService.java43
-rw-r--r--services/core/java/com/android/server/wm/DisplayContent.java39
-rw-r--r--services/core/java/com/android/server/wm/DisplayPolicy.java11
-rw-r--r--services/core/java/com/android/server/wm/InputMonitor.java21
-rw-r--r--services/core/java/com/android/server/wm/RecentTasks.java24
-rw-r--r--services/core/java/com/android/server/wm/RecentsAnimation.java6
-rw-r--r--services/core/java/com/android/server/wm/RootWindowContainer.java27
-rw-r--r--services/core/java/com/android/server/wm/RunningTasks.java34
-rw-r--r--services/core/java/com/android/server/wm/Task.java45
-rw-r--r--services/core/java/com/android/server/wm/TaskOrganizerController.java70
-rw-r--r--services/core/java/com/android/server/wm/TaskPositioner.java5
-rw-r--r--services/core/java/com/android/server/wm/WindowManagerService.java22
-rw-r--r--services/core/java/com/android/server/wm/WindowState.java6
-rw-r--r--services/core/java/com/android/server/wm/WindowSurfacePlacer.java4
-rw-r--r--services/core/jni/com_android_server_input_InputManagerService.cpp63
-rw-r--r--services/core/jni/com_android_server_location_GnssLocationProvider.cpp126
-rw-r--r--services/core/jni/com_android_server_pm_PackageManagerShellCommandDataLoader.cpp139
-rw-r--r--services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java11
-rw-r--r--services/devicepolicy/java/com/android/server/devicepolicy/Owners.java10
-rw-r--r--services/incremental/IncrementalService.cpp1
-rw-r--r--services/java/com/android/server/SystemServer.java8
-rw-r--r--services/robotests/src/com/android/server/location/gnss/GnssAntennaInfoProviderTest.java (renamed from services/robotests/src/com/android/server/location/GnssAntennaInfoProviderTest.java)5
-rw-r--r--services/robotests/src/com/android/server/location/gnss/GnssBatchingProviderTest.java (renamed from services/robotests/src/com/android/server/location/GnssBatchingProviderTest.java)20
-rw-r--r--services/robotests/src/com/android/server/location/gnss/GnssGeofenceProviderTest.java (renamed from services/robotests/src/com/android/server/location/GnssGeofenceProviderTest.java)18
-rw-r--r--services/robotests/src/com/android/server/location/gnss/GnssMeasurementsProviderTest.java (renamed from services/robotests/src/com/android/server/location/GnssMeasurementsProviderTest.java)21
-rw-r--r--services/robotests/src/com/android/server/location/gnss/GnssNavigationMessageProviderTest.java (renamed from services/robotests/src/com/android/server/location/GnssNavigationMessageProviderTest.java)21
-rw-r--r--services/robotests/src/com/android/server/location/gnss/GnssPositionModeTest.java (renamed from services/robotests/src/com/android/server/location/GnssPositionModeTest.java)18
-rw-r--r--services/robotests/src/com/android/server/location/gnss/GnssSatelliteBlacklistHelperTest.java (renamed from services/robotests/src/com/android/server/location/GnssSatelliteBlacklistHelperTest.java)21
-rw-r--r--services/robotests/src/com/android/server/location/gnss/NtpTimeHelperTest.java (renamed from services/robotests/src/com/android/server/location/NtpTimeHelperTest.java)20
-rw-r--r--services/tests/servicestests/Android.bp10
-rw-r--r--services/tests/servicestests/src/com/android/server/MountServiceTests.java279
-rw-r--r--services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerServiceTestable.java2
-rw-r--r--services/tests/servicestests/src/com/android/server/location/gnss/GnssManagerServiceTest.java14
-rw-r--r--services/tests/servicestests/src/com/android/server/pm/PackageParserTest.java66
-rw-r--r--services/tests/servicestests/test-apps/PackageParserApp/Android.bp53
-rw-r--r--services/tests/servicestests/test-apps/PackageParserApp/AndroidManifestApp1.xml25
-rw-r--r--services/tests/servicestests/test-apps/PackageParserApp/AndroidManifestApp2.xml26
-rw-r--r--services/tests/servicestests/test-apps/PackageParserApp/AndroidManifestApp3.xml26
-rw-r--r--services/tests/servicestests/test-apps/PackageParserApp/res/values/values.xml19
-rw-r--r--services/tests/servicestests/test-apps/PackageParserApp/src/com/android/servicestests/apps/packageparserapp/TestActivity.java (renamed from core/java/android/content/pm/NamedParcelFileDescriptor.aidl)20
-rw-r--r--services/tests/uiservicestests/src/com/android/server/notification/BubbleExtractorTest.java30
-rwxr-xr-xservices/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java75
-rw-r--r--services/tests/uiservicestests/src/com/android/server/notification/RoleObserverTest.java3
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/AppTransitionTests.java4
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/AppWindowTokenTests.java2
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/LaunchParamsPersisterTests.java6
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/RecentTasksTest.java35
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/RecentsAnimationControllerTest.java2
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/RunningTasksTest.java20
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/SizeCompatTests.java2
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/TaskOrganizerTests.java134
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/TaskRecordTests.java16
-rw-r--r--services/voiceinteraction/java/com/android/server/soundtrigger/SoundTriggerDbHelper.java11
-rw-r--r--services/voiceinteraction/java/com/android/server/soundtrigger/SoundTriggerHelper.java6
-rw-r--r--services/voiceinteraction/java/com/android/server/soundtrigger/SoundTriggerService.java60
-rw-r--r--services/voiceinteraction/java/com/android/server/voiceinteraction/DatabaseHelper.java27
-rw-r--r--services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerService.java14
-rw-r--r--startop/iorap/src/com/google/android/startop/iorap/IorapForwardingService.java2
-rw-r--r--telecomm/java/android/telecom/TelecomManager.java18
-rw-r--r--telephony/api/system-current.txt4
-rw-r--r--telephony/common/com/android/internal/telephony/TelephonyPermissions.java3
-rw-r--r--telephony/java/android/telephony/SignalStrength.java2
-rw-r--r--telephony/java/android/telephony/TelephonyManager.java27
-rw-r--r--telephony/java/com/android/internal/telephony/DctConstants.java4
-rw-r--r--test-mock/src/android/test/mock/MockContext.java6
-rw-r--r--tests/AppLaunch/src/com/android/tests/applaunch/AppLaunch.java108
-rw-r--r--tests/PackageWatchdog/src/com/android/server/PackageWatchdogTest.java22
-rw-r--r--tests/SoundTriggerTestApp/src/com/android/test/soundtrigger/SoundTriggerTestService.java33
-rw-r--r--tests/SoundTriggerTests/src/android/hardware/soundtrigger/SoundTriggerTest.java65
-rw-r--r--tests/SoundTriggerTests/src/android/hardware/soundtrigger/stubhal/GenericSoundModelTest.java47
-rw-r--r--tests/VoiceEnrollment/src/com/android/test/voiceenrollment/EnrollmentUtil.java18
-rw-r--r--tests/VoiceEnrollment/src/com/android/test/voiceenrollment/TestEnrollmentActivity.java8
-rw-r--r--tests/net/java/com/android/server/ConnectivityServiceTest.java54
-rw-r--r--wifi/Android.bp1
-rw-r--r--wifi/java/android/net/wifi/WifiNetworkAgentSpecifier.java2
-rw-r--r--wifi/java/android/net/wifi/WifiNetworkSpecifier.java2
-rw-r--r--wifi/java/android/net/wifi/aware/WifiAwareAgentNetworkSpecifier.java2
-rw-r--r--wifi/java/android/net/wifi/aware/WifiAwareNetworkSpecifier.java2
-rw-r--r--wifi/tests/src/android/net/wifi/WifiNetworkAgentSpecifierTest.java34
-rw-r--r--wifi/tests/src/android/net/wifi/WifiNetworkSpecifierTest.java12
-rw-r--r--wifi/tests/src/android/net/wifi/aware/WifiAwareAgentNetworkSpecifierTest.java14
420 files changed, 8089 insertions, 3296 deletions
diff --git a/Android.bp b/Android.bp
index 7f4cd849ab77..6653bd44966b 100644
--- a/Android.bp
+++ b/Android.bp
@@ -577,25 +577,6 @@ platform_compat_config {
src: ":framework-annotation-proc",
}
-// A library including just UnsupportedAppUsage.java classes.
-//
-// Provided for target so that libraries can use it without depending on
-// the whole of framework or the core platform API.
-//
-// Built for host so that the annotation processor can also use this annotation.
-java_library {
- name: "unsupportedappusage-annotation",
- host_supported: true,
- srcs: [
- "core/java/android/annotation/IntDef.java",
- ],
- static_libs: [
- "art.module.api.annotations",
- ],
-
- sdk_version: "core_current",
-}
-
// A temporary build target that is conditionally included on the bootclasspath if
// android.test.base library has been removed and which provides support for
// maintaining backwards compatibility for APKs that target pre-P and depend on
@@ -971,7 +952,6 @@ filegroup {
"core/java/android/content/pm/InstallationFileLocation.aidl",
"core/java/android/content/pm/IDataLoaderStatusListener.aidl",
"core/java/android/content/pm/IPackageInstallerSessionFileSystemConnector.aidl",
- "core/java/android/content/pm/NamedParcelFileDescriptor.aidl",
],
path: "core/java",
}
diff --git a/apex/Android.bp b/apex/Android.bp
index e8f6e6bf2c46..d0889efc0405 100644
--- a/apex/Android.bp
+++ b/apex/Android.bp
@@ -88,18 +88,30 @@ java_defaults {
name: "framework-module-stubs-lib-defaults-publicapi",
installable: false,
sdk_version: "module_current",
+ dist: {
+ targets: ["sdk", "win_sdk"],
+ dir: "apistubs/android/public",
+ },
}
java_defaults {
name: "framework-module-stubs-lib-defaults-systemapi",
installable: false,
sdk_version: "module_current",
+ dist: {
+ targets: ["sdk", "win_sdk"],
+ dir: "apistubs/android/system",
+ },
}
java_defaults {
name: "framework-module-stubs-lib-defaults-module_libs_api",
installable: false,
sdk_version: "module_current",
+ dist: {
+ targets: ["sdk", "win_sdk"],
+ dir: "apistubs/android/module-lib",
+ },
}
// The defaults for module_libs comes in two parts - defaults for API checks
@@ -137,6 +149,7 @@ stubs_defaults {
name: "service-module-stubs-srcs-defaults",
args: mainline_service_stubs_args,
installable: false,
+ filter_packages: ["com.android."],
check_api: {
current: {
api_file: "api/current.txt",
@@ -153,4 +166,8 @@ stubs_defaults {
// module java_library system_server stub libs.
java_defaults {
name: "service-module-stubs-defaults",
+ dist: {
+ targets: ["sdk", "win_sdk"],
+ dir: "apistubs/android/system-server",
+ },
}
diff --git a/apex/media/framework/api/current.txt b/apex/media/framework/api/current.txt
index 839fb5143196..9cec748e7b8e 100644
--- a/apex/media/framework/api/current.txt
+++ b/apex/media/framework/api/current.txt
@@ -29,7 +29,7 @@ package android.media {
method public boolean advance(@NonNull android.media.MediaParser.SeekableInputReader) throws java.io.IOException;
method @NonNull public static android.media.MediaParser create(@NonNull android.media.MediaParser.OutputConsumer, @NonNull java.lang.String...);
method @NonNull public static android.media.MediaParser createByName(@NonNull String, @NonNull android.media.MediaParser.OutputConsumer);
- method @Nullable public String getParserName();
+ method @NonNull public String getParserName();
method @NonNull public static java.util.List<java.lang.String> getParserNames(@NonNull android.media.MediaFormat);
method public void release();
method public void seek(@NonNull android.media.MediaParser.SeekPoint);
@@ -65,6 +65,7 @@ package android.media {
field public static final String PARSER_NAME_OGG = "android.media.mediaparser.OggParser";
field public static final String PARSER_NAME_PS = "android.media.mediaparser.PsParser";
field public static final String PARSER_NAME_TS = "android.media.mediaparser.TsParser";
+ field public static final String PARSER_NAME_UNKNOWN = "android.media.mediaparser.UNKNOWN";
field public static final String PARSER_NAME_WAV = "android.media.mediaparser.WavParser";
}
diff --git a/apex/media/framework/java/android/media/MediaParser.java b/apex/media/framework/java/android/media/MediaParser.java
index 5f86ed621084..d8ae485ddd4d 100644
--- a/apex/media/framework/java/android/media/MediaParser.java
+++ b/apex/media/framework/java/android/media/MediaParser.java
@@ -45,6 +45,7 @@ import com.google.android.exoplayer2.extractor.ogg.OggExtractor;
import com.google.android.exoplayer2.extractor.ts.Ac3Extractor;
import com.google.android.exoplayer2.extractor.ts.Ac4Extractor;
import com.google.android.exoplayer2.extractor.ts.AdtsExtractor;
+import com.google.android.exoplayer2.extractor.ts.DefaultTsPayloadReaderFactory;
import com.google.android.exoplayer2.extractor.ts.PsExtractor;
import com.google.android.exoplayer2.extractor.ts.TsExtractor;
import com.google.android.exoplayer2.extractor.wav.WavExtractor;
@@ -452,6 +453,7 @@ public final class MediaParser {
@StringDef(
prefix = {"PARSER_NAME_"},
value = {
+ PARSER_NAME_UNKNOWN,
PARSER_NAME_MATROSKA,
PARSER_NAME_FMP4,
PARSER_NAME_MP4,
@@ -469,6 +471,7 @@ public final class MediaParser {
})
public @interface ParserName {}
+ public static final String PARSER_NAME_UNKNOWN = "android.media.mediaparser.UNKNOWN";
public static final String PARSER_NAME_MATROSKA = "android.media.mediaparser.MatroskaParser";
public static final String PARSER_NAME_FMP4 = "android.media.mediaparser.FragmentedMp4Parser";
public static final String PARSER_NAME_MP4 = "android.media.mediaparser.Mp4Parser";
@@ -644,6 +647,9 @@ public final class MediaParser {
private static final Map<String, ExtractorFactory> EXTRACTOR_FACTORIES_BY_NAME;
private static final Map<String, Class> EXPECTED_TYPE_BY_PARAMETER_NAME;
+ private static final String TS_MODE_SINGLE_PMT = "single_pmt";
+ private static final String TS_MODE_MULTI_PMT = "multi_pmt";
+ private static final String TS_MODE_HLS = "hls";
// Instance creation methods.
@@ -817,6 +823,12 @@ public final class MediaParser {
+ value.getClass().getSimpleName()
+ " was passed.");
}
+ if (PARAMETER_TS_MODE.equals(parameterName)
+ && !TS_MODE_SINGLE_PMT.equals(value)
+ && !TS_MODE_HLS.equals(value)
+ && !TS_MODE_MULTI_PMT.equals(value)) {
+ throw new IllegalArgumentException(PARAMETER_TS_MODE + " does not accept: " + value);
+ }
mParserParameters.put(parameterName, value);
return this;
}
@@ -836,14 +848,14 @@ public final class MediaParser {
* Returns the name of the backing parser implementation.
*
* <p>If this instance was creating using {@link #createByName}, the provided name is returned.
- * If this instance was created using {@link #create}, this method will return null until the
- * first call to {@link #advance}, after which the name of the backing parser implementation is
- * returned.
+ * If this instance was created using {@link #create}, this method will return {@link
+ * #PARSER_NAME_UNKNOWN} until the first call to {@link #advance}, after which the name of the
+ * backing parser implementation is returned.
*
* @return The name of the backing parser implementation, or null if the backing parser
* implementation has not yet been selected.
*/
- @Nullable
+ @NonNull
@ParserName
public String getParserName() {
return mExtractorName;
@@ -880,13 +892,12 @@ public final class MediaParser {
// TODO: Apply parameters when creating extractor instances.
if (mExtractor == null) {
- if (mExtractorName != null) {
+ if (!mExtractorName.equals(PARSER_NAME_UNKNOWN)) {
mExtractor = EXTRACTOR_FACTORIES_BY_NAME.get(mExtractorName).createInstance();
mExtractor.init(new ExtractorOutputAdapter());
} else {
for (String parserName : mParserNamesPool) {
- Extractor extractor =
- EXTRACTOR_FACTORIES_BY_NAME.get(parserName).createInstance();
+ Extractor extractor = createExtractor(parserName);
try {
if (extractor.sniff(mExtractorInput)) {
mExtractorName = parserName;
@@ -974,9 +985,7 @@ public final class MediaParser {
mParserParameters = new HashMap<>();
mOutputConsumer = outputConsumer;
mParserNamesPool = parserNamesPool;
- if (!sniff) {
- mExtractorName = parserNamesPool[0];
- }
+ mExtractorName = sniff ? PARSER_NAME_UNKNOWN : parserNamesPool[0];
mPositionHolder = new PositionHolder();
mDataSource = new InputReadingDataSource();
removePendingSeek();
@@ -993,6 +1002,124 @@ public final class MediaParser {
mPendingSeekTimeMicros = -1;
}
+ private Extractor createExtractor(String parserName) {
+ int flags = 0;
+ switch (parserName) {
+ case PARSER_NAME_MATROSKA:
+ flags =
+ getBooleanParameter(PARAMETER_MATROSKA_DISABLE_CUES_SEEKING)
+ ? MatroskaExtractor.FLAG_DISABLE_SEEK_FOR_CUES
+ : 0;
+ return new MatroskaExtractor(flags);
+ case PARSER_NAME_FMP4:
+ flags |=
+ getBooleanParameter(PARAMETER_MP4_IGNORE_EDIT_LISTS)
+ ? FragmentedMp4Extractor.FLAG_WORKAROUND_IGNORE_EDIT_LISTS
+ : 0;
+ flags |=
+ getBooleanParameter(PARAMETER_MP4_IGNORE_TFDT_BOX)
+ ? FragmentedMp4Extractor.FLAG_WORKAROUND_IGNORE_TFDT_BOX
+ : 0;
+ flags |=
+ getBooleanParameter(PARAMETER_MP4_TREAT_VIDEO_FRAMES_AS_KEYFRAMES)
+ ? FragmentedMp4Extractor
+ .FLAG_WORKAROUND_EVERY_VIDEO_FRAME_IS_SYNC_FRAME
+ : 0;
+ return new FragmentedMp4Extractor(flags);
+ case PARSER_NAME_MP4:
+ flags |=
+ getBooleanParameter(PARAMETER_MP4_IGNORE_EDIT_LISTS)
+ ? Mp4Extractor.FLAG_WORKAROUND_IGNORE_EDIT_LISTS
+ : 0;
+ return new Mp4Extractor();
+ case PARSER_NAME_MP3:
+ flags |=
+ getBooleanParameter(PARAMETER_MP3_DISABLE_ID3)
+ ? Mp3Extractor.FLAG_DISABLE_ID3_METADATA
+ : 0;
+ flags |=
+ getBooleanParameter(PARAMETER_MP3_ENABLE_CBR_SEEKING)
+ ? Mp3Extractor.FLAG_ENABLE_CONSTANT_BITRATE_SEEKING
+ : 0;
+ // TODO: Add index seeking once we update the ExoPlayer version.
+ return new Mp3Extractor(flags);
+ case PARSER_NAME_ADTS:
+ flags |=
+ getBooleanParameter(PARAMETER_ADTS_ENABLE_CBR_SEEKING)
+ ? AdtsExtractor.FLAG_ENABLE_CONSTANT_BITRATE_SEEKING
+ : 0;
+ return new AdtsExtractor(flags);
+ case PARSER_NAME_AC3:
+ return new Ac3Extractor();
+ case PARSER_NAME_TS:
+ flags |=
+ getBooleanParameter(PARAMETER_TS_ALLOW_NON_IDR_AVC_KEYFRAMES)
+ ? DefaultTsPayloadReaderFactory.FLAG_ALLOW_NON_IDR_KEYFRAMES
+ : 0;
+ flags |=
+ getBooleanParameter(PARAMETER_TS_DETECT_ACCESS_UNITS)
+ ? DefaultTsPayloadReaderFactory.FLAG_DETECT_ACCESS_UNITS
+ : 0;
+ flags |=
+ getBooleanParameter(PARAMETER_TS_ENABLE_HDMV_DTS_AUDIO_STREAMS)
+ ? DefaultTsPayloadReaderFactory.FLAG_ENABLE_HDMV_DTS_AUDIO_STREAMS
+ : 0;
+ flags |=
+ getBooleanParameter(PARAMETER_TS_IGNORE_AAC_STREAM)
+ ? DefaultTsPayloadReaderFactory.FLAG_IGNORE_AAC_STREAM
+ : 0;
+ flags |=
+ getBooleanParameter(PARAMETER_TS_IGNORE_AVC_STREAM)
+ ? DefaultTsPayloadReaderFactory.FLAG_IGNORE_H264_STREAM
+ : 0;
+ flags |=
+ getBooleanParameter(PARAMETER_TS_IGNORE_SPLICE_INFO_STREAM)
+ ? DefaultTsPayloadReaderFactory.FLAG_IGNORE_SPLICE_INFO_STREAM
+ : 0;
+ String tsMode = getStringParameter(PARAMETER_TS_MODE, TS_MODE_SINGLE_PMT);
+ int hlsMode =
+ TS_MODE_SINGLE_PMT.equals(tsMode)
+ ? TsExtractor.MODE_SINGLE_PMT
+ : TS_MODE_HLS.equals(tsMode)
+ ? TsExtractor.MODE_HLS
+ : TsExtractor.MODE_MULTI_PMT;
+ return new TsExtractor(hlsMode, flags);
+ case PARSER_NAME_FLV:
+ return new FlvExtractor();
+ case PARSER_NAME_OGG:
+ return new OggExtractor();
+ case PARSER_NAME_PS:
+ return new PsExtractor();
+ case PARSER_NAME_WAV:
+ return new WavExtractor();
+ case PARSER_NAME_AMR:
+ flags |=
+ getBooleanParameter(PARAMETER_AMR_ENABLE_CBR_SEEKING)
+ ? AmrExtractor.FLAG_ENABLE_CONSTANT_BITRATE_SEEKING
+ : 0;
+ return new AmrExtractor(flags);
+ case PARSER_NAME_AC4:
+ return new Ac4Extractor();
+ case PARSER_NAME_FLAC:
+ flags |=
+ getBooleanParameter(PARAMETER_FLAC_DISABLE_ID3)
+ ? FlacExtractor.FLAG_DISABLE_ID3_METADATA
+ : 0;
+ return new FlacExtractor(flags);
+ default:
+ // Should never happen.
+ throw new IllegalStateException("Unexpected attempt to create: " + parserName);
+ }
+ }
+
+ private boolean getBooleanParameter(String name) {
+ return (boolean) mParserParameters.getOrDefault(name, false);
+ }
+
+ private String getStringParameter(String name, String defaultValue) {
+ return (String) mParserParameters.getOrDefault(name, defaultValue);
+ }
+
// Private classes.
private static final class InputReadingDataSource implements DataSource {
diff --git a/apex/permission/framework/Android.bp b/apex/permission/framework/Android.bp
index 3fefeb51aa11..793247e88614 100644
--- a/apex/permission/framework/Android.bp
+++ b/apex/permission/framework/Android.bp
@@ -31,6 +31,10 @@ java_library {
"com.android.permission",
"test_com.android.permission",
],
+ permitted_packages: [
+ "android.permission",
+ "android.app.role",
+ ],
hostdex: true,
installable: true,
visibility: [
diff --git a/apex/permission/service/Android.bp b/apex/permission/service/Android.bp
index 679c98ddcbb5..5cdcdd335a12 100644
--- a/apex/permission/service/Android.bp
+++ b/apex/permission/service/Android.bp
@@ -17,6 +17,7 @@ filegroup {
srcs: [
"java/**/*.java",
],
+ path: "java",
}
java_library {
diff --git a/apex/statsd/tests/libstatspull/src/com/android/internal/os/statsd/libstats/LibStatsPullTests.java b/apex/statsd/tests/libstatspull/src/com/android/internal/os/statsd/libstats/LibStatsPullTests.java
index 3f199e83ceed..240222ea9411 100644
--- a/apex/statsd/tests/libstatspull/src/com/android/internal/os/statsd/libstats/LibStatsPullTests.java
+++ b/apex/statsd/tests/libstatspull/src/com/android/internal/os/statsd/libstats/LibStatsPullTests.java
@@ -29,6 +29,7 @@ import androidx.test.runner.AndroidJUnit4;
import com.android.internal.os.StatsdConfigProto.AtomMatcher;
import com.android.internal.os.StatsdConfigProto.FieldFilter;
import com.android.internal.os.StatsdConfigProto.GaugeMetric;
+import com.android.internal.os.StatsdConfigProto.PullAtomPackages;
import com.android.internal.os.StatsdConfigProto.SimpleAtomMatcher;
import com.android.internal.os.StatsdConfigProto.StatsdConfig;
import com.android.internal.os.StatsdConfigProto.TimeUnit;
@@ -271,6 +272,9 @@ public class LibStatsPullTests {
.setSamplingType(GaugeMetric.SamplingType.FIRST_N_SAMPLES)
.setMaxNumGaugeAtomsPerBucket(1000)
)
+ .addPullAtomPackages(PullAtomPackages.newBuilder()
+ .setAtomId(PULL_ATOM_TAG)
+ .addPackages(LibStatsPullTests.class.getPackage().getName()))
.build();
statsManager.addConfig(sConfigId, config.toByteArray());
assertThat(StatsConfigUtils.verifyValidConfigExists(statsManager, sConfigId)).isTrue();
diff --git a/api/current.txt b/api/current.txt
index b5e4798f0891..785925ebef91 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -277,7 +277,6 @@ package android {
field public static final int activityCloseExitAnimation = 16842939; // 0x10100bb
field public static final int activityOpenEnterAnimation = 16842936; // 0x10100b8
field public static final int activityOpenExitAnimation = 16842937; // 0x10100b9
- field public static final int actor = 16844312; // 0x1010618
field public static final int addPrintersActivity = 16843750; // 0x10103e6
field public static final int addStatesFromChildren = 16842992; // 0x10100f0
field public static final int adjustViewBounds = 16843038; // 0x101011e
@@ -327,7 +326,7 @@ package android {
field public static final int autoLink = 16842928; // 0x10100b0
field public static final int autoMirrored = 16843754; // 0x10103ea
field public static final int autoRemoveFromRecents = 16843847; // 0x1010447
- field public static final int autoRevokePermissions = 16844308; // 0x1010614
+ field public static final int autoRevokePermissions = 16844309; // 0x1010615
field public static final int autoSizeMaxTextSize = 16844102; // 0x1010546
field public static final int autoSizeMinTextSize = 16844088; // 0x1010538
field public static final int autoSizePresetSizes = 16844087; // 0x1010537
@@ -709,7 +708,7 @@ package android {
field public static final int gravity = 16842927; // 0x10100af
field public static final int gridViewStyle = 16842865; // 0x1010071
field public static final int groupIndicator = 16843019; // 0x101010b
- field public static final int gwpAsanMode = 16844311; // 0x1010617
+ field public static final int gwpAsanMode = 16844312; // 0x1010618
field public static final int hand_hour = 16843011; // 0x1010103
field public static final int hand_minute = 16843012; // 0x1010104
field public static final int handle = 16843354; // 0x101025a
@@ -954,7 +953,7 @@ package android {
field public static final int mediaRouteButtonStyle = 16843693; // 0x10103ad
field public static final int mediaRouteTypes = 16843694; // 0x10103ae
field public static final int menuCategory = 16843230; // 0x10101de
- field public static final int mimeGroup = 16844310; // 0x1010616
+ field public static final int mimeGroup = 16844311; // 0x1010617
field public static final int mimeType = 16842790; // 0x1010026
field public static final int min = 16844089; // 0x1010539
field public static final int minAspectRatio = 16844187; // 0x101059b
@@ -1083,7 +1082,7 @@ package android {
field public static final int preferenceScreenStyle = 16842891; // 0x101008b
field public static final int preferenceStyle = 16842894; // 0x101008e
field public static final int presentationTheme = 16843712; // 0x10103c0
- field public static final int preserveLegacyExternalStorage = 16844309; // 0x1010615
+ field public static final int preserveLegacyExternalStorage = 16844310; // 0x1010616
field public static final int previewImage = 16843482; // 0x10102da
field public static final int primaryContentAlpha = 16844114; // 0x1010552
field public static final int priority = 16842780; // 0x101001c
@@ -24357,7 +24356,7 @@ package android.media {
}
public final class AudioMetadata {
- method @NonNull public static android.media.AudioMetadata.Map createMap();
+ method @NonNull public static android.media.AudioMetadataMap createMap();
}
public static class AudioMetadata.Format {
@@ -24375,16 +24374,16 @@ package android.media {
method @NonNull public Class<T> getValueClass();
}
- public static interface AudioMetadata.Map extends android.media.AudioMetadata.ReadMap {
+ public interface AudioMetadataMap extends android.media.AudioMetadataReadMap {
method @Nullable public <T> T remove(@NonNull android.media.AudioMetadata.Key<T>);
method @Nullable public <T> T set(@NonNull android.media.AudioMetadata.Key<T>, @NonNull T);
}
- public static interface AudioMetadata.ReadMap {
+ public interface AudioMetadataReadMap {
method public <T> boolean containsKey(@NonNull android.media.AudioMetadata.Key<T>);
- method @NonNull public android.media.AudioMetadata.Map dup();
+ method @NonNull public android.media.AudioMetadataMap dup();
method @Nullable public <T> T get(@NonNull android.media.AudioMetadata.Key<T>);
- method public int size();
+ method @IntRange(from=0) public int size();
}
public final class AudioPlaybackCaptureConfiguration {
@@ -24699,7 +24698,7 @@ package android.media {
}
public static interface AudioTrack.OnCodecFormatChangedListener {
- method public void onCodecFormatChanged(@NonNull android.media.AudioTrack, @Nullable android.media.AudioMetadata.ReadMap);
+ method public void onCodecFormatChanged(@NonNull android.media.AudioTrack, @Nullable android.media.AudioMetadataReadMap);
}
public static interface AudioTrack.OnPlaybackPositionUpdateListener {
@@ -26400,7 +26399,7 @@ package android.media {
method public boolean advance(@NonNull android.media.MediaParser.SeekableInputReader) throws java.io.IOException;
method @NonNull public static android.media.MediaParser create(@NonNull android.media.MediaParser.OutputConsumer, @NonNull java.lang.String...);
method @NonNull public static android.media.MediaParser createByName(@NonNull String, @NonNull android.media.MediaParser.OutputConsumer);
- method @Nullable public String getParserName();
+ method @NonNull public String getParserName();
method @NonNull public static java.util.List<java.lang.String> getParserNames(@NonNull android.media.MediaFormat);
method public void release();
method public void seek(@NonNull android.media.MediaParser.SeekPoint);
@@ -26436,6 +26435,7 @@ package android.media {
field public static final String PARSER_NAME_OGG = "android.media.mediaparser.OggParser";
field public static final String PARSER_NAME_PS = "android.media.mediaparser.PsParser";
field public static final String PARSER_NAME_TS = "android.media.mediaparser.TsParser";
+ field public static final String PARSER_NAME_UNKNOWN = "android.media.mediaparser.UNKNOWN";
field public static final String PARSER_NAME_WAV = "android.media.mediaparser.WavParser";
}
@@ -30343,6 +30343,7 @@ package android.net {
}
public class NetworkRequest implements android.os.Parcelable {
+ method public boolean canBeSatisfiedBy(@Nullable android.net.NetworkCapabilities);
method public int describeContents();
method @Nullable public android.net.NetworkSpecifier getNetworkSpecifier();
method public boolean hasCapability(int);
@@ -37145,11 +37146,10 @@ package android.os {
field public static final int EFFECT_TICK = 2; // 0x2
}
- public static class VibrationEffect.Composition {
- ctor public VibrationEffect.Composition();
- method @Nullable public android.os.VibrationEffect.Composition addPrimitive(int);
- method @Nullable public android.os.VibrationEffect.Composition addPrimitive(int, @FloatRange(from=0.0f, to=1.0f) float);
- method @Nullable public android.os.VibrationEffect.Composition addPrimitive(int, @FloatRange(from=0.0f, to=1.0f) float, @IntRange(from=0) int);
+ public static final class VibrationEffect.Composition {
+ method @NonNull public android.os.VibrationEffect.Composition addPrimitive(int);
+ method @NonNull public android.os.VibrationEffect.Composition addPrimitive(int, @FloatRange(from=0.0f, to=1.0f) float);
+ method @NonNull public android.os.VibrationEffect.Composition addPrimitive(int, @FloatRange(from=0.0f, to=1.0f) float, @IntRange(from=0) int);
method @NonNull public android.os.VibrationEffect compose();
field public static final int PRIMITIVE_CLICK = 1; // 0x1
field public static final int PRIMITIVE_QUICK_FALL = 6; // 0x6
@@ -37159,9 +37159,9 @@ package android.os {
}
public abstract class Vibrator {
- method @Nullable public Boolean areAllEffectsSupported(@NonNull int...);
- method public boolean areAllPrimitivesSupported(@NonNull int...);
- method @Nullable public boolean[] areEffectsSupported(@NonNull int...);
+ method public final int areAllEffectsSupported(@NonNull int...);
+ method public final boolean areAllPrimitivesSupported(@NonNull int...);
+ method @NonNull public int[] areEffectsSupported(@NonNull int...);
method @NonNull public boolean[] arePrimitivesSupported(@NonNull int...);
method @RequiresPermission(android.Manifest.permission.VIBRATE) public abstract void cancel();
method public abstract boolean hasAmplitudeControl();
@@ -37172,6 +37172,9 @@ package android.os {
method @Deprecated @RequiresPermission(android.Manifest.permission.VIBRATE) public void vibrate(long[], int, android.media.AudioAttributes);
method @RequiresPermission(android.Manifest.permission.VIBRATE) public void vibrate(android.os.VibrationEffect);
method @RequiresPermission(android.Manifest.permission.VIBRATE) public void vibrate(android.os.VibrationEffect, android.media.AudioAttributes);
+ field public static final int VIBRATION_EFFECT_SUPPORT_NO = 2; // 0x2
+ field public static final int VIBRATION_EFFECT_SUPPORT_UNKNOWN = 0; // 0x0
+ field public static final int VIBRATION_EFFECT_SUPPORT_YES = 1; // 0x1
}
public class WorkSource implements android.os.Parcelable {
@@ -55757,7 +55760,7 @@ package android.view {
field public int softInputMode;
field @Deprecated public int systemUiVisibility;
field public android.os.IBinder token;
- field @android.view.ViewDebug.ExportedProperty(mapping={@android.view.ViewDebug.IntToString(from=android.view.WindowManager.LayoutParams.TYPE_BASE_APPLICATION, to="BASE_APPLICATION"), @android.view.ViewDebug.IntToString(from=android.view.WindowManager.LayoutParams.TYPE_APPLICATION, to="APPLICATION"), @android.view.ViewDebug.IntToString(from=android.view.WindowManager.LayoutParams.TYPE_APPLICATION_STARTING, to="APPLICATION_STARTING"), @android.view.ViewDebug.IntToString(from=android.view.WindowManager.LayoutParams.TYPE_DRAWN_APPLICATION, to="DRAWN_APPLICATION"), @android.view.ViewDebug.IntToString(from=android.view.WindowManager.LayoutParams.TYPE_APPLICATION_PANEL, to="APPLICATION_PANEL"), @android.view.ViewDebug.IntToString(from=android.view.WindowManager.LayoutParams.TYPE_APPLICATION_MEDIA, to="APPLICATION_MEDIA"), @android.view.ViewDebug.IntToString(from=android.view.WindowManager.LayoutParams.TYPE_APPLICATION_SUB_PANEL, to="APPLICATION_SUB_PANEL"), @android.view.ViewDebug.IntToString(from=0x3ed, to="APPLICATION_ABOVE_SUB_PANEL"), @android.view.ViewDebug.IntToString(from=android.view.WindowManager.LayoutParams.TYPE_APPLICATION_ATTACHED_DIALOG, to="APPLICATION_ATTACHED_DIALOG"), @android.view.ViewDebug.IntToString(from=0x3ec, to="APPLICATION_MEDIA_OVERLAY"), @android.view.ViewDebug.IntToString(from=android.view.WindowManager.LayoutParams.TYPE_STATUS_BAR, to="STATUS_BAR"), @android.view.ViewDebug.IntToString(from=android.view.WindowManager.LayoutParams.TYPE_SEARCH_BAR, to="SEARCH_BAR"), @android.view.ViewDebug.IntToString(from=android.view.WindowManager.LayoutParams.TYPE_PHONE, to="PHONE"), @android.view.ViewDebug.IntToString(from=android.view.WindowManager.LayoutParams.TYPE_SYSTEM_ALERT, to="SYSTEM_ALERT"), @android.view.ViewDebug.IntToString(from=android.view.WindowManager.LayoutParams.TYPE_TOAST, to="TOAST"), @android.view.ViewDebug.IntToString(from=android.view.WindowManager.LayoutParams.TYPE_SYSTEM_OVERLAY, to="SYSTEM_OVERLAY"), @android.view.ViewDebug.IntToString(from=android.view.WindowManager.LayoutParams.TYPE_PRIORITY_PHONE, to="PRIORITY_PHONE"), @android.view.ViewDebug.IntToString(from=android.view.WindowManager.LayoutParams.TYPE_SYSTEM_DIALOG, to="SYSTEM_DIALOG"), @android.view.ViewDebug.IntToString(from=android.view.WindowManager.LayoutParams.TYPE_KEYGUARD_DIALOG, to="KEYGUARD_DIALOG"), @android.view.ViewDebug.IntToString(from=android.view.WindowManager.LayoutParams.TYPE_SYSTEM_ERROR, to="SYSTEM_ERROR"), @android.view.ViewDebug.IntToString(from=android.view.WindowManager.LayoutParams.TYPE_INPUT_METHOD, to="INPUT_METHOD"), @android.view.ViewDebug.IntToString(from=android.view.WindowManager.LayoutParams.TYPE_INPUT_METHOD_DIALOG, to="INPUT_METHOD_DIALOG"), @android.view.ViewDebug.IntToString(from=android.view.WindowManager.LayoutParams.TYPE_WALLPAPER, to="WALLPAPER"), @android.view.ViewDebug.IntToString(from=android.view.WindowManager.LayoutParams.TYPE_STATUS_BAR_PANEL, to="STATUS_BAR_PANEL"), @android.view.ViewDebug.IntToString(from=0x7df, to="SECURE_SYSTEM_OVERLAY"), @android.view.ViewDebug.IntToString(from=0x7e0, to="DRAG"), @android.view.ViewDebug.IntToString(from=0x7e1, to="STATUS_BAR_SUB_PANEL"), @android.view.ViewDebug.IntToString(from=0x7e2, to="POINTER"), @android.view.ViewDebug.IntToString(from=0x7e3, to="NAVIGATION_BAR"), @android.view.ViewDebug.IntToString(from=0x7e4, to="VOLUME_OVERLAY"), @android.view.ViewDebug.IntToString(from=0x7e5, to="BOOT_PROGRESS"), @android.view.ViewDebug.IntToString(from=0x7e6, to="INPUT_CONSUMER"), @android.view.ViewDebug.IntToString(from=0x7e7, to="DREAM"), @android.view.ViewDebug.IntToString(from=0x7e8, to="NAVIGATION_BAR_PANEL"), @android.view.ViewDebug.IntToString(from=0x7ea, to="DISPLAY_OVERLAY"), @android.view.ViewDebug.IntToString(from=0x7eb, to="MAGNIFICATION_OVERLAY"), @android.view.ViewDebug.IntToString(from=0x7f5, to="PRESENTATION"), @android.view.ViewDebug.IntToString(from=android.view.WindowManager.LayoutParams.TYPE_PRIVATE_PRESENTATION, to="PRIVATE_PRESENTATION"), @android.view.ViewDebug.IntToString(from=0x7ef, to="VOICE_INTERACTION"), @android.view.ViewDebug.IntToString(from=0x7f1, to="VOICE_INTERACTION_STARTING"), @android.view.ViewDebug.IntToString(from=0x7f2, to="DOCK_DIVIDER"), @android.view.ViewDebug.IntToString(from=0x7f3, to="QS_DIALOG"), @android.view.ViewDebug.IntToString(from=0x7f4, to="SCREENSHOT"), @android.view.ViewDebug.IntToString(from=android.view.WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY, to="APPLICATION_OVERLAY")}) public int type;
+ field @android.view.ViewDebug.ExportedProperty(mapping={@android.view.ViewDebug.IntToString(from=android.view.WindowManager.LayoutParams.TYPE_BASE_APPLICATION, to="BASE_APPLICATION"), @android.view.ViewDebug.IntToString(from=android.view.WindowManager.LayoutParams.TYPE_APPLICATION, to="APPLICATION"), @android.view.ViewDebug.IntToString(from=android.view.WindowManager.LayoutParams.TYPE_APPLICATION_STARTING, to="APPLICATION_STARTING"), @android.view.ViewDebug.IntToString(from=android.view.WindowManager.LayoutParams.TYPE_DRAWN_APPLICATION, to="DRAWN_APPLICATION"), @android.view.ViewDebug.IntToString(from=android.view.WindowManager.LayoutParams.TYPE_APPLICATION_PANEL, to="APPLICATION_PANEL"), @android.view.ViewDebug.IntToString(from=android.view.WindowManager.LayoutParams.TYPE_APPLICATION_MEDIA, to="APPLICATION_MEDIA"), @android.view.ViewDebug.IntToString(from=android.view.WindowManager.LayoutParams.TYPE_APPLICATION_SUB_PANEL, to="APPLICATION_SUB_PANEL"), @android.view.ViewDebug.IntToString(from=0x3ed, to="APPLICATION_ABOVE_SUB_PANEL"), @android.view.ViewDebug.IntToString(from=android.view.WindowManager.LayoutParams.TYPE_APPLICATION_ATTACHED_DIALOG, to="APPLICATION_ATTACHED_DIALOG"), @android.view.ViewDebug.IntToString(from=0x3ec, to="APPLICATION_MEDIA_OVERLAY"), @android.view.ViewDebug.IntToString(from=android.view.WindowManager.LayoutParams.TYPE_STATUS_BAR, to="STATUS_BAR"), @android.view.ViewDebug.IntToString(from=android.view.WindowManager.LayoutParams.TYPE_SEARCH_BAR, to="SEARCH_BAR"), @android.view.ViewDebug.IntToString(from=android.view.WindowManager.LayoutParams.TYPE_PHONE, to="PHONE"), @android.view.ViewDebug.IntToString(from=android.view.WindowManager.LayoutParams.TYPE_SYSTEM_ALERT, to="SYSTEM_ALERT"), @android.view.ViewDebug.IntToString(from=android.view.WindowManager.LayoutParams.TYPE_TOAST, to="TOAST"), @android.view.ViewDebug.IntToString(from=android.view.WindowManager.LayoutParams.TYPE_SYSTEM_OVERLAY, to="SYSTEM_OVERLAY"), @android.view.ViewDebug.IntToString(from=android.view.WindowManager.LayoutParams.TYPE_PRIORITY_PHONE, to="PRIORITY_PHONE"), @android.view.ViewDebug.IntToString(from=android.view.WindowManager.LayoutParams.TYPE_SYSTEM_DIALOG, to="SYSTEM_DIALOG"), @android.view.ViewDebug.IntToString(from=android.view.WindowManager.LayoutParams.TYPE_KEYGUARD_DIALOG, to="KEYGUARD_DIALOG"), @android.view.ViewDebug.IntToString(from=android.view.WindowManager.LayoutParams.TYPE_SYSTEM_ERROR, to="SYSTEM_ERROR"), @android.view.ViewDebug.IntToString(from=android.view.WindowManager.LayoutParams.TYPE_INPUT_METHOD, to="INPUT_METHOD"), @android.view.ViewDebug.IntToString(from=android.view.WindowManager.LayoutParams.TYPE_INPUT_METHOD_DIALOG, to="INPUT_METHOD_DIALOG"), @android.view.ViewDebug.IntToString(from=android.view.WindowManager.LayoutParams.TYPE_WALLPAPER, to="WALLPAPER"), @android.view.ViewDebug.IntToString(from=android.view.WindowManager.LayoutParams.TYPE_STATUS_BAR_PANEL, to="STATUS_BAR_PANEL"), @android.view.ViewDebug.IntToString(from=0x7df, to="SECURE_SYSTEM_OVERLAY"), @android.view.ViewDebug.IntToString(from=0x7e0, to="DRAG"), @android.view.ViewDebug.IntToString(from=0x7e1, to="STATUS_BAR_SUB_PANEL"), @android.view.ViewDebug.IntToString(from=0x7e2, to="POINTER"), @android.view.ViewDebug.IntToString(from=0x7e3, to="NAVIGATION_BAR"), @android.view.ViewDebug.IntToString(from=0x7e4, to="VOLUME_OVERLAY"), @android.view.ViewDebug.IntToString(from=0x7e5, to="BOOT_PROGRESS"), @android.view.ViewDebug.IntToString(from=0x7e6, to="INPUT_CONSUMER"), @android.view.ViewDebug.IntToString(from=0x7e8, to="NAVIGATION_BAR_PANEL"), @android.view.ViewDebug.IntToString(from=0x7ea, to="DISPLAY_OVERLAY"), @android.view.ViewDebug.IntToString(from=0x7eb, to="MAGNIFICATION_OVERLAY"), @android.view.ViewDebug.IntToString(from=0x7f5, to="PRESENTATION"), @android.view.ViewDebug.IntToString(from=android.view.WindowManager.LayoutParams.TYPE_PRIVATE_PRESENTATION, to="PRIVATE_PRESENTATION"), @android.view.ViewDebug.IntToString(from=0x7ef, to="VOICE_INTERACTION"), @android.view.ViewDebug.IntToString(from=0x7f1, to="VOICE_INTERACTION_STARTING"), @android.view.ViewDebug.IntToString(from=0x7f2, to="DOCK_DIVIDER"), @android.view.ViewDebug.IntToString(from=0x7f3, to="QS_DIALOG"), @android.view.ViewDebug.IntToString(from=0x7f4, to="SCREENSHOT"), @android.view.ViewDebug.IntToString(from=android.view.WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY, to="APPLICATION_OVERLAY")}) public int type;
field public float verticalMargin;
field @android.view.ViewDebug.ExportedProperty public float verticalWeight;
field public int windowAnimations;
diff --git a/api/system-current.txt b/api/system-current.txt
index b9153d96a56a..eb017b0adc38 100755
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -3575,23 +3575,23 @@ package android.hardware.soundtrigger {
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;
- field public final int id;
- field @NonNull public final java.util.Locale locale;
- field public final int recognitionModes;
- field @NonNull public final String text;
- field @NonNull public final int[] users;
}
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;
- field @NonNull public final android.hardware.soundtrigger.SoundTrigger.Keyphrase[] keyphrases;
}
public static final class SoundTrigger.ModelParamRange implements android.os.Parcelable {
@@ -3603,26 +3603,26 @@ package android.hardware.soundtrigger {
public static final class SoundTrigger.ModuleProperties implements android.os.Parcelable {
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;
- field public final int audioCapabilities;
- field @NonNull public final String description;
- field public final int id;
- field @NonNull public final String implementor;
- field public final int maxBufferMs;
- field public final int maxKeyphrases;
- field public final int maxSoundModels;
- field public final int maxUsers;
- field public final int powerConsumptionMw;
- field public final int recognitionModes;
- field public final boolean returnsTriggerInEvent;
- field @NonNull public final String supportedModelArch;
- field public final boolean supportsCaptureTransition;
- field public final boolean supportsConcurrentCapture;
- field @NonNull public final java.util.UUID uuid;
- field public final int version;
}
public static class SoundTrigger.RecognitionEvent {
@@ -3633,13 +3633,13 @@ package android.hardware.soundtrigger {
}
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
- field @NonNull public final byte[] data;
- field public final int type;
- field @NonNull public final java.util.UUID uuid;
- field @NonNull public final java.util.UUID vendorUuid;
- field public final int version;
}
}
@@ -4178,11 +4178,11 @@ package android.media {
method @RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING) public void addOnPreferredDeviceForStrategyChangedListener(@NonNull java.util.concurrent.Executor, @NonNull android.media.AudioManager.OnPreferredDeviceForStrategyChangedListener) throws java.lang.SecurityException;
method public void clearAudioServerStateCallback();
method @RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING) public int dispatchAudioFocusChange(@NonNull android.media.AudioFocusInfo, int, @NonNull android.media.audiopolicy.AudioPolicy);
- method @IntRange(from=0) public int getAdditionalOutputDeviceDelay(@NonNull android.media.AudioDeviceInfo);
+ method @IntRange(from=0) public long getAdditionalOutputDeviceDelay(@NonNull android.media.AudioDeviceInfo);
method @NonNull @RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING) public static java.util.List<android.media.audiopolicy.AudioProductStrategy> getAudioProductStrategies();
method @NonNull @RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING) public static java.util.List<android.media.audiopolicy.AudioVolumeGroup> getAudioVolumeGroups();
method @NonNull @RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING) public java.util.List<android.media.AudioDeviceAttributes> getDevicesForAttributes(@NonNull android.media.AudioAttributes);
- method @IntRange(from=0) public int getMaxAdditionalOutputDeviceDelay(@NonNull android.media.AudioDeviceInfo);
+ method @IntRange(from=0) public long getMaxAdditionalOutputDeviceDelay(@NonNull android.media.AudioDeviceInfo);
method @IntRange(from=0) @RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING) public int getMaxVolumeIndexForAttributes(@NonNull android.media.AudioAttributes);
method @IntRange(from=0) @RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING) public int getMinVolumeIndexForAttributes(@NonNull android.media.AudioAttributes);
method @Nullable @RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING) public android.media.AudioDeviceAttributes getPreferredDeviceForStrategy(@NonNull android.media.audiopolicy.AudioProductStrategy);
@@ -4197,7 +4197,7 @@ package android.media {
method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public int requestAudioFocus(android.media.AudioManager.OnAudioFocusChangeListener, @NonNull android.media.AudioAttributes, int, int) throws java.lang.IllegalArgumentException;
method @Deprecated @RequiresPermission(anyOf={android.Manifest.permission.MODIFY_PHONE_STATE, android.Manifest.permission.MODIFY_AUDIO_ROUTING}) public int requestAudioFocus(android.media.AudioManager.OnAudioFocusChangeListener, @NonNull android.media.AudioAttributes, int, int, android.media.audiopolicy.AudioPolicy) throws java.lang.IllegalArgumentException;
method @RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING) public int requestAudioFocus(@NonNull android.media.AudioFocusRequest, @Nullable android.media.audiopolicy.AudioPolicy);
- method @RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING) public boolean setAdditionalOutputDeviceDelay(@NonNull android.media.AudioDeviceInfo, @IntRange(from=0) int);
+ method @RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING) public boolean setAdditionalOutputDeviceDelay(@NonNull android.media.AudioDeviceInfo, @IntRange(from=0) long);
method public void setAudioServerStateCallback(@NonNull java.util.concurrent.Executor, @NonNull android.media.AudioManager.AudioServerStateCallback);
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 boolean setPreferredDeviceForStrategy(@NonNull android.media.audiopolicy.AudioProductStrategy, @NonNull android.media.AudioDeviceAttributes);
@@ -4272,17 +4272,11 @@ package android.media {
}
public static class AudioTrack.TunerConfiguration {
+ ctor @RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING) public AudioTrack.TunerConfiguration(@IntRange(from=1) int, @IntRange(from=1) int);
method @IntRange(from=1) @RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING) public int getContentId();
method @IntRange(from=1) @RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING) public int getSyncId();
}
- public static class AudioTrack.TunerConfiguration.Builder {
- ctor public AudioTrack.TunerConfiguration.Builder();
- method @NonNull @RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING) public android.media.AudioTrack.TunerConfiguration build();
- method @NonNull @RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING) public android.media.AudioTrack.TunerConfiguration.Builder setContentId(@IntRange(from=1) int);
- method @NonNull @RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING) public android.media.AudioTrack.TunerConfiguration.Builder setSyncId(@IntRange(from=1) int);
- }
-
public class HwAudioSource {
method public boolean isPlaying();
method public void start();
@@ -6183,7 +6177,6 @@ package android.net {
public final class MatchAllNetworkSpecifier extends android.net.NetworkSpecifier implements android.os.Parcelable {
ctor public MatchAllNetworkSpecifier();
method public int describeContents();
- method public boolean satisfiedBy(android.net.NetworkSpecifier);
method public void writeToParcel(@NonNull android.os.Parcel, int);
field @NonNull public static final android.os.Parcelable.Creator<android.net.MatchAllNetworkSpecifier> CREATOR;
}
@@ -6204,21 +6197,21 @@ package android.net {
public abstract class NetworkAgent {
ctor public NetworkAgent(@NonNull android.content.Context, @NonNull android.os.Looper, @NonNull String, @NonNull android.net.NetworkCapabilities, @NonNull android.net.LinkProperties, int, @NonNull android.net.NetworkAgentConfig, @Nullable android.net.NetworkProvider);
method @Nullable public android.net.Network getNetwork();
+ method public void markConnected();
method public void onAddKeepalivePacketFilter(int, @NonNull android.net.KeepalivePacketData);
method public void onAutomaticReconnectDisabled();
method public void onNetworkUnwanted();
method public void onRemoveKeepalivePacketFilter(int);
method public void onSaveAcceptUnvalidated(boolean);
method public void onSignalStrengthThresholdsUpdated(@NonNull int[]);
- method public void onStartSocketKeepalive(int, int, @NonNull android.net.KeepalivePacketData);
+ method public void onStartSocketKeepalive(int, @NonNull java.time.Duration, @NonNull android.net.KeepalivePacketData);
method public void onStopSocketKeepalive(int);
- method public void onValidationStatus(int, @Nullable String);
+ method public void onValidationStatus(int, @Nullable android.net.Uri);
method @NonNull public android.net.Network register();
- method public void sendLinkProperties(@NonNull android.net.LinkProperties);
- method public void sendNetworkCapabilities(@NonNull android.net.NetworkCapabilities);
- method public void sendNetworkScore(int);
- method public void sendSocketKeepaliveEvent(int, int);
- method public void setConnected();
+ method public final void sendLinkProperties(@NonNull android.net.LinkProperties);
+ method public final void sendNetworkCapabilities(@NonNull android.net.NetworkCapabilities);
+ method public final void sendNetworkScore(@IntRange(from=0, to=99) int);
+ method public final void sendSocketKeepaliveEvent(int, int);
method public void unregister();
field public static final int VALIDATION_STATUS_NOT_VALID = 2; // 0x2
field public static final int VALIDATION_STATUS_VALID = 1; // 0x1
@@ -6235,7 +6228,7 @@ package android.net {
field @NonNull public static final android.os.Parcelable.Creator<android.net.NetworkAgentConfig> CREATOR;
}
- public static class NetworkAgentConfig.Builder {
+ public static final class NetworkAgentConfig.Builder {
ctor public NetworkAgentConfig.Builder();
method @NonNull public android.net.NetworkAgentConfig build();
method @NonNull public android.net.NetworkAgentConfig.Builder setExplicitlySelected(boolean);
@@ -6289,8 +6282,8 @@ package android.net {
ctor public NetworkProvider(@NonNull android.content.Context, @NonNull android.os.Looper, @NonNull String);
method @RequiresPermission(android.Manifest.permission.NETWORK_FACTORY) public void declareNetworkRequestUnfulfillable(@NonNull android.net.NetworkRequest);
method public int getProviderId();
- method public void onNetworkRequested(@NonNull android.net.NetworkRequest, int, int);
- method public void onRequestWithdrawn(@NonNull android.net.NetworkRequest);
+ method public void onNetworkRequestWithdrawn(@NonNull android.net.NetworkRequest);
+ method public void onNetworkRequested(@NonNull android.net.NetworkRequest, @IntRange(from=0, to=99) int, int);
field public static final int ID_NONE = -1; // 0xffffffff
}
@@ -6303,7 +6296,6 @@ package android.net {
public class NetworkRequest implements android.os.Parcelable {
method @Nullable public String getRequestorPackageName();
method public int getRequestorUid();
- method public boolean satisfiedBy(@Nullable android.net.NetworkCapabilities);
}
public static class NetworkRequest.Builder {
@@ -6338,8 +6330,8 @@ package android.net {
}
public abstract class NetworkSpecifier {
+ method public boolean canBeSatisfiedBy(@Nullable android.net.NetworkSpecifier);
method @Nullable public android.net.NetworkSpecifier redact();
- method public abstract boolean satisfiedBy(@Nullable android.net.NetworkSpecifier);
}
public class NetworkStack {
@@ -6442,10 +6434,6 @@ package android.net {
method @NonNull public android.net.StaticIpConfiguration.Builder setIpAddress(@Nullable android.net.LinkAddress);
}
- public final class TelephonyNetworkSpecifier extends android.net.NetworkSpecifier implements android.os.Parcelable {
- method public boolean satisfiedBy(android.net.NetworkSpecifier);
- }
-
public final class TetheredClient implements android.os.Parcelable {
ctor public TetheredClient(@NonNull android.net.MacAddress, @NonNull java.util.Collection<android.net.TetheredClient.AddressInfo>, int);
method public int describeContents();
@@ -7432,10 +7420,6 @@ package android.net.wifi {
field public int numUsage;
}
- public final class WifiNetworkSpecifier extends android.net.NetworkSpecifier implements android.os.Parcelable {
- method public boolean satisfiedBy(android.net.NetworkSpecifier);
- }
-
public final class WifiNetworkSuggestion implements android.os.Parcelable {
method @NonNull public android.net.wifi.WifiConfiguration getWifiConfiguration();
}
@@ -7626,10 +7610,6 @@ package android.net.wifi.aware {
method @Deprecated public android.net.NetworkSpecifier createNetworkSpecifierPmk(@NonNull android.net.wifi.aware.PeerHandle, @NonNull byte[]);
}
- public final class WifiAwareNetworkSpecifier extends android.net.NetworkSpecifier implements android.os.Parcelable {
- method public boolean satisfiedBy(android.net.NetworkSpecifier);
- }
-
public class WifiAwareSession implements java.lang.AutoCloseable {
method public android.net.NetworkSpecifier createNetworkSpecifierPmk(int, @NonNull byte[], @NonNull byte[]);
}
@@ -8394,12 +8374,12 @@ package android.os {
public class RecoverySystem {
method @RequiresPermission(android.Manifest.permission.RECOVERY) public static void cancelScheduledUpdate(android.content.Context) throws java.io.IOException;
- method @RequiresPermission(android.Manifest.permission.RECOVERY) public static boolean clearPrepareForUnattendedUpdate(@NonNull android.content.Context) throws java.io.IOException;
+ method @RequiresPermission(android.Manifest.permission.RECOVERY) public static void clearPrepareForUnattendedUpdate(@NonNull android.content.Context) throws java.io.IOException;
method @RequiresPermission(android.Manifest.permission.RECOVERY) public static void installPackage(android.content.Context, java.io.File, boolean) throws java.io.IOException;
method @RequiresPermission(android.Manifest.permission.RECOVERY) public static void prepareForUnattendedUpdate(@NonNull android.content.Context, @NonNull String, @Nullable android.content.IntentSender) throws java.io.IOException;
method @RequiresPermission(android.Manifest.permission.RECOVERY) public static void processPackage(android.content.Context, java.io.File, android.os.RecoverySystem.ProgressListener, android.os.Handler) throws java.io.IOException;
method @RequiresPermission(android.Manifest.permission.RECOVERY) public static void processPackage(android.content.Context, java.io.File, android.os.RecoverySystem.ProgressListener) throws java.io.IOException;
- method @RequiresPermission(android.Manifest.permission.RECOVERY) public static boolean rebootAndApply(@NonNull android.content.Context, @NonNull String, @NonNull String) throws java.io.IOException;
+ method @RequiresPermission(android.Manifest.permission.RECOVERY) public static void rebootAndApply(@NonNull android.content.Context, @NonNull String, @NonNull String) throws java.io.IOException;
method @RequiresPermission(allOf={android.Manifest.permission.RECOVERY, android.Manifest.permission.REBOOT}) public static void rebootWipeAb(android.content.Context, java.io.File, String) throws java.io.IOException;
method @RequiresPermission(android.Manifest.permission.RECOVERY) public static void scheduleUpdateOnBoot(android.content.Context, java.io.File) throws java.io.IOException;
method public static boolean verifyPackageCompatibility(java.io.File) throws java.io.IOException;
@@ -11340,9 +11320,9 @@ package android.telephony {
method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setVoiceActivationState(int);
method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void shutdownAllRadios();
method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public boolean supplyPin(String);
- method @Deprecated @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public int[] supplyPinReportResult(String);
+ method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public int[] supplyPinReportResult(String);
method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public boolean supplyPuk(String, String);
- method @Deprecated @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public int[] supplyPukReportResult(String, String);
+ method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public int[] supplyPukReportResult(String, String);
method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public boolean switchSlots(int[]);
method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void toggleRadioOnOff();
method @RequiresPermission(android.Manifest.permission.READ_ACTIVE_EMERGENCY_SESSION) public void updateOtaEmergencyNumberDbFilePath(@NonNull android.os.ParcelFileDescriptor);
@@ -12712,9 +12692,6 @@ package android.view.contentcapture {
public final class ContentCaptureManager {
method public boolean isContentCaptureFeatureEnabled();
- }
-
- public abstract class ContentCaptureSession implements java.lang.AutoCloseable {
field public static final int NO_SESSION_ID = 0; // 0x0
}
diff --git a/cmds/screencap/screencap.cpp b/cmds/screencap/screencap.cpp
index 0bb1af13643c..4410f1c4570c 100644
--- a/cmds/screencap/screencap.cpp
+++ b/cmds/screencap/screencap.cpp
@@ -24,6 +24,7 @@
#include <linux/fb.h>
#include <sys/ioctl.h>
#include <sys/mman.h>
+#include <sys/wait.h>
#include <binder/ProcessState.h>
@@ -99,11 +100,38 @@ static uint32_t dataSpaceToInt(ui::Dataspace d)
}
static status_t notifyMediaScanner(const char* fileName) {
- String8 cmd("am broadcast -a android.intent.action.MEDIA_SCANNER_SCAN_FILE -d file://");
- cmd.append(fileName);
- cmd.append(" > /dev/null");
- int result = system(cmd.string());
- if (result < 0) {
+ std::string filePath("file://");
+ filePath.append(fileName);
+ char *cmd[] = {
+ (char*) "am",
+ (char*) "broadcast",
+ (char*) "am",
+ (char*) "android.intent.action.MEDIA_SCANNER_SCAN_FILE",
+ (char*) "-d",
+ &filePath[0],
+ nullptr
+ };
+
+ int status;
+ int pid = fork();
+ if (pid < 0){
+ fprintf(stderr, "Unable to fork in order to send intent for media scanner.\n");
+ return UNKNOWN_ERROR;
+ }
+ if (pid == 0){
+ int fd = open("/dev/null", O_WRONLY);
+ if (fd < 0){
+ fprintf(stderr, "Unable to open /dev/null for media scanner stdout redirection.\n");
+ exit(1);
+ }
+ dup2(fd, 1);
+ int result = execvp(cmd[0], cmd);
+ close(fd);
+ exit(result);
+ }
+ wait(&status);
+
+ if (status < 0) {
fprintf(stderr, "Unable to broadcast intent for media scanner.\n");
return UNKNOWN_ERROR;
}
diff --git a/cmds/statsd/Android.bp b/cmds/statsd/Android.bp
index 45f21ae8e3e1..776593d5c795 100644
--- a/cmds/statsd/Android.bp
+++ b/cmds/statsd/Android.bp
@@ -333,6 +333,7 @@ cc_test {
"tests/external/puller_util_test.cpp",
"tests/external/StatsCallbackPuller_test.cpp",
"tests/external/StatsPuller_test.cpp",
+ "tests/external/StatsPullerManager_test.cpp",
"tests/FieldValue_test.cpp",
"tests/guardrail/StatsdStats_test.cpp",
"tests/indexed_priority_queue_test.cpp",
diff --git a/cmds/statsd/src/StatsLogProcessor.cpp b/cmds/statsd/src/StatsLogProcessor.cpp
index 69b9fc7ad9a0..4966b2e1a018 100644
--- a/cmds/statsd/src/StatsLogProcessor.cpp
+++ b/cmds/statsd/src/StatsLogProcessor.cpp
@@ -536,6 +536,7 @@ void StatsLogProcessor::OnConfigUpdatedLocked(
new MetricsManager(key, config, mTimeBaseNs, timestampNs, mUidMap, mPullerManager,
mAnomalyAlarmMonitor, mPeriodicAlarmMonitor);
if (newMetricsManager->isConfigValid()) {
+ newMetricsManager->init();
mUidMap->OnConfigUpdated(key);
newMetricsManager->refreshTtl(timestampNs);
mMetricsManagers[key] = newMetricsManager;
diff --git a/cmds/statsd/src/StatsService.cpp b/cmds/statsd/src/StatsService.cpp
index 812d10be4bf6..98879a05185d 100644
--- a/cmds/statsd/src/StatsService.cpp
+++ b/cmds/statsd/src/StatsService.cpp
@@ -385,9 +385,11 @@ void StatsService::print_cmd_help(int out) {
dprintf(out, " PKG Optional package name to print the uids of the package\n");
dprintf(out, "\n");
dprintf(out, "\n");
- dprintf(out, "usage: adb shell cmd stats pull-source [int] \n");
+ dprintf(out, "usage: adb shell cmd stats pull-source ATOM_TAG [PACKAGE] \n");
dprintf(out, "\n");
- dprintf(out, " Prints the output of a pulled metrics source (int indicates source)\n");
+ dprintf(out, " Prints the output of a pulled atom\n");
+ dprintf(out, " UID The atom to pull\n");
+ dprintf(out, " PACKAGE The package to pull from. Default is AID_SYSTEM\n");
dprintf(out, "\n");
dprintf(out, "\n");
dprintf(out, "usage: adb shell cmd stats write-to-disk \n");
@@ -806,8 +808,21 @@ status_t StatsService::cmd_log_binary_push(int out, const Vector<String8>& args)
status_t StatsService::cmd_print_pulled_metrics(int out, const Vector<String8>& args) {
int s = atoi(args[1].c_str());
- vector<shared_ptr<LogEvent> > stats;
- if (mPullerManager->Pull(s, &stats)) {
+ vector<int32_t> uids;
+ if (args.size() > 2) {
+ string package = string(args[2].c_str());
+ auto it = UidMap::sAidToUidMapping.find(package);
+ if (it != UidMap::sAidToUidMapping.end()) {
+ uids.push_back(it->second);
+ } else {
+ set<int32_t> uids_set = mUidMap->getAppUid(package);
+ uids.insert(uids.end(), uids_set.begin(), uids_set.end());
+ }
+ } else {
+ uids.push_back(AID_SYSTEM);
+ }
+ vector<shared_ptr<LogEvent>> stats;
+ if (mPullerManager->Pull(s, uids, &stats)) {
for (const auto& it : stats) {
dprintf(out, "Pull from %d: %s\n", s, it->ToString().c_str());
}
diff --git a/cmds/statsd/src/atoms.proto b/cmds/statsd/src/atoms.proto
index 979f950f2770..9bba69c6e2ea 100644
--- a/cmds/statsd/src/atoms.proto
+++ b/cmds/statsd/src/atoms.proto
@@ -1725,7 +1725,7 @@ message BluetoothEnabledStateChanged {
* Logged from:
* packages/apps/Bluetooth/src/com/android/bluetooth/btservice/RemoteDevices.java
*
- * Next Tag: 5
+ * Next Tag: 6
*/
message BluetoothConnectionStateChanged {
// The state of the connection.
@@ -1747,6 +1747,15 @@ message BluetoothConnectionStateChanged {
// Size: 32 byte
// Default: null or empty if the device identifier is not known
optional bytes new_obfuscated_id = 4 [(android.os.statsd.log_mode) = MODE_BYTES];
+ // An identifier that can be used to match events for this device.
+ // The incremental identifier is locally generated and guaranteed not derived
+ // from any globally unique hardware id.
+ // For paired devices, it stays consistent between Bluetooth toggling for the
+ // same remote device.
+ // For unpaired devices, it stays consistent within the same Bluetooth adapter
+ // session for the same remote device.
+ // Default: 0 if the device's metric id is unknown.
+ optional int32 metric_id = 5;
}
/**
@@ -1755,7 +1764,7 @@ message BluetoothConnectionStateChanged {
* Logged from:
* packages/apps/Bluetooth/src/com/android/bluetooth/btservice/AdapterProperties.java
*
- * Next Tag: 3
+ * Next Tag: 4
*/
message BluetoothAclConnectionStateChanged {
// An identifier that can be used to match events for this device.
@@ -1768,6 +1777,15 @@ message BluetoothAclConnectionStateChanged {
// The state of the connection.
// Eg: CONNECTING, CONNECTED, DISCONNECTING, DISCONNECTED.
optional android.bluetooth.ConnectionStateEnum state = 2;
+ // An identifier that can be used to match events for this device.
+ // The incremental identifier is locally generated and guaranteed not derived
+ // from any globally unique hardware id.
+ // For paired devices, it stays consistent between Bluetooth toggling for the
+ // same remote device.
+ // For unpaired devices, it stays consistent within the same Bluetooth adapter
+ // session for the same remote device.
+ // Default: 0 if the device's metric id is unknown.
+ optional int32 metric_id = 3;
}
/**
@@ -1777,7 +1795,7 @@ message BluetoothAclConnectionStateChanged {
* packages/apps/Bluetooth/src/com/android/bluetooth/hfp/HeadsetStateMachine.java
* packages/apps/Bluetooth/src/com/android/bluetooth/hfp/HeadsetClientStateMachine.java
*
- * Next Tag: 4
+ * Next Tag: 5
*/
message BluetoothScoConnectionStateChanged {
// An identifier that can be used to match events for this device.
@@ -1793,6 +1811,15 @@ message BluetoothScoConnectionStateChanged {
// Codec used for this SCO connection
// Default: UNKNOWN
optional android.bluetooth.hfp.ScoCodec codec = 3;
+ // An identifier that can be used to match events for this device.
+ // The incremental identifier is locally generated and guaranteed not derived
+ // from any globally unique hardware id.
+ // For paired devices, it stays consistent between Bluetooth toggling for the
+ // same remote device.
+ // For unpaired devices, it stays consistent within the same Bluetooth adapter
+ // session for the same remote device.
+ // Default: 0 if the device's metric id is unknown.
+ optional int32 metric_id = 4;
}
/**
@@ -1814,6 +1841,15 @@ message BluetoothActiveDeviceChanged {
// Size: 32 byte
// Default: null or empty if there is no active device for this profile
optional bytes obfuscated_id = 2 [(android.os.statsd.log_mode) = MODE_BYTES];
+ // An identifier that can be used to match events for this device.
+ // The incremental identifier is locally generated and guaranteed not derived
+ // from any globally unique hardware id.
+ // For paired devices, it stays consistent between Bluetooth toggling for the
+ // same remote device.
+ // For unpaired devices, it stays consistent within the same Bluetooth adapter
+ // session for the same remote device.
+ // Default: 0 if the device's metric id is unknown.
+ optional int32 metric_id = 3;
}
// Logs when there is an event affecting Bluetooth device's link layer connection.
@@ -1897,6 +1933,15 @@ message BluetoothLinkLayerConnectionEvent {
// HCI reason code associated with this event
// Default: STATUS_UNKNOWN
optional android.bluetooth.hci.StatusEnum reason_code = 9;
+ // An identifier that can be used to match events for this device.
+ // The incremental identifier is locally generated and guaranteed not derived
+ // from any globally unique hardware id.
+ // For paired devices, it stays consistent between Bluetooth toggling for the
+ // same remote device.
+ // For unpaired devices, it stays consistent within the same Bluetooth adapter
+ // session for the same remote device.
+ // Default: 0 if the device's metric id is unknown.
+ optional int32 metric_id = 10;
}
/**
@@ -1955,6 +2000,15 @@ message BluetoothA2dpPlaybackStateChanged {
// Current audio coding mode
// Default: AUDIO_CODING_MODE_UNKNOWN
optional android.bluetooth.a2dp.AudioCodingModeEnum audio_coding_mode = 3;
+ // An identifier that can be used to match events for this device.
+ // The incremental identifier is locally generated and guaranteed not derived
+ // from any globally unique hardware id.
+ // For paired devices, it stays consistent between Bluetooth toggling for the
+ // same remote device.
+ // For unpaired devices, it stays consistent within the same Bluetooth adapter
+ // session for the same remote device.
+ // Default: 0 if the device's metric id is unknown.
+ optional int32 metric_id = 4;
}
/**
@@ -1993,6 +2047,15 @@ message BluetoothA2dpCodecConfigChanged {
optional int64 codec_specific_2 = 8;
optional int64 codec_specific_3 = 9;
optional int64 codec_specific_4 = 10;
+ // An identifier that can be used to match events for this device.
+ // The incremental identifier is locally generated and guaranteed not derived
+ // from any globally unique hardware id.
+ // For paired devices, it stays consistent between Bluetooth toggling for the
+ // same remote device.
+ // For unpaired devices, it stays consistent within the same Bluetooth adapter
+ // session for the same remote device.
+ // Default: 0 if the device's metric id is unknown.
+ optional int32 metric_id = 11;
}
/**
@@ -2035,6 +2098,15 @@ message BluetoothA2dpCodecCapabilityChanged {
optional int64 codec_specific_2 = 8;
optional int64 codec_specific_3 = 9;
optional int64 codec_specific_4 = 10;
+ // An identifier that can be used to match events for this device.
+ // The incremental identifier is locally generated and guaranteed not derived
+ // from any globally unique hardware id.
+ // For paired devices, it stays consistent between Bluetooth toggling for the
+ // same remote device.
+ // For unpaired devices, it stays consistent within the same Bluetooth adapter
+ // session for the same remote device.
+ // Default: 0 if the device's metric id is unknown.
+ optional int32 metric_id = 11;
}
/**
@@ -2058,6 +2130,15 @@ message BluetoothA2dpAudioUnderrunReported {
// Number of bytes of PCM data that could not be read from the source
// Default: 0
optional int32 num_missing_pcm_bytes = 3;
+ // An identifier that can be used to match events for this device.
+ // The incremental identifier is locally generated and guaranteed not derived
+ // from any globally unique hardware id.
+ // For paired devices, it stays consistent between Bluetooth toggling for the
+ // same remote device.
+ // For unpaired devices, it stays consistent within the same Bluetooth adapter
+ // session for the same remote device.
+ // Default: 0 if the device's metric id is unknown.
+ optional int32 metric_id = 4;
}
/**
@@ -2088,6 +2169,15 @@ message BluetoothA2dpAudioOverrunReported {
// Number of encoded bytes dropped in this event
// Default: 0
optional int32 num_dropped_encoded_bytes = 5;
+ // An identifier that can be used to match events for this device.
+ // The incremental identifier is locally generated and guaranteed not derived
+ // from any globally unique hardware id.
+ // For paired devices, it stays consistent between Bluetooth toggling for the
+ // same remote device.
+ // For unpaired devices, it stays consistent within the same Bluetooth adapter
+ // session for the same remote device.
+ // Default: 0 if the device's metric id is unknown.
+ optional int32 metric_id = 6;
}
/**
@@ -2119,6 +2209,15 @@ message BluetoothDeviceRssiReported {
// Units: dBm
// Invalid when an out of range value is reported
optional int32 rssi = 4;
+ // An identifier that can be used to match events for this device.
+ // The incremental identifier is locally generated and guaranteed not derived
+ // from any globally unique hardware id.
+ // For paired devices, it stays consistent between Bluetooth toggling for the
+ // same remote device.
+ // For unpaired devices, it stays consistent within the same Bluetooth adapter
+ // session for the same remote device.
+ // Default: 0 if the device's metric id is unknown.
+ optional int32 metric_id = 5;
}
/**
@@ -2146,6 +2245,15 @@ message BluetoothDeviceFailedContactCounterReported {
// Range: uint16_t, 0-0xFFFF
// Default: 0xFFFFF
optional int32 failed_contact_counter = 4;
+ // An identifier that can be used to match events for this device.
+ // The incremental identifier is locally generated and guaranteed not derived
+ // from any globally unique hardware id.
+ // For paired devices, it stays consistent between Bluetooth toggling for the
+ // same remote device.
+ // For unpaired devices, it stays consistent within the same Bluetooth adapter
+ // session for the same remote device.
+ // Default: 0 if the device's metric id is unknown.
+ optional int32 metric_id = 5;
}
/**
@@ -2173,6 +2281,15 @@ message BluetoothDeviceTxPowerLevelReported {
// Units: dBm
// Invalid when an out of range value is reported
optional int32 transmit_power_level = 4;
+ // An identifier that can be used to match events for this device.
+ // The incremental identifier is locally generated and guaranteed not derived
+ // from any globally unique hardware id.
+ // For paired devices, it stays consistent between Bluetooth toggling for the
+ // same remote device.
+ // For unpaired devices, it stays consistent within the same Bluetooth adapter
+ // session for the same remote device.
+ // Default: 0 if the device's metric id is unknown.
+ optional int32 metric_id = 5;
}
/**
@@ -2302,6 +2419,15 @@ message BluetoothDeviceInfoReported {
optional string hardware_version = 6;
// Software version of this device
optional string software_version = 7;
+ // An identifier that can be used to match events for this device.
+ // The incremental identifier is locally generated and guaranteed not derived
+ // from any globally unique hardware id.
+ // For paired devices, it stays consistent between Bluetooth toggling for the
+ // same remote device.
+ // For unpaired devices, it stays consistent within the same Bluetooth adapter
+ // session for the same remote device.
+ // Default: 0 if the device's metric id is unknown.
+ optional int32 metric_id = 8;
}
/**
@@ -2355,6 +2481,15 @@ message BluetoothSdpAttributeReported {
optional int32 attribute_id = 3;
// Attribute value for the particular attribute
optional bytes attribute_value = 4 [(android.os.statsd.log_mode) = MODE_BYTES];
+ // An identifier that can be used to match events for this device.
+ // The incremental identifier is locally generated and guaranteed not derived
+ // from any globally unique hardware id.
+ // For paired devices, it stays consistent between Bluetooth toggling for the
+ // same remote device.
+ // For unpaired devices, it stays consistent within the same Bluetooth adapter
+ // session for the same remote device.
+ // Default: 0 if the device's metric id is unknown.
+ optional int32 metric_id = 5;
}
/**
@@ -2387,6 +2522,15 @@ message BluetoothBondStateChanged {
// Unbond Reason
// Default: UNBOND_REASON_UNKNOWN
optional android.bluetooth.UnbondReasonEnum unbond_reason = 6;
+ // An identifier that can be used to match events for this device.
+ // The incremental identifier is locally generated and guaranteed not derived
+ // from any globally unique hardware id.
+ // For paired devices, it stays consistent between Bluetooth toggling for the
+ // same remote device.
+ // For unpaired devices, it stays consistent within the same Bluetooth adapter
+ // session for the same remote device.
+ // Default: 0 if the device's metric id is unknown.
+ optional int32 metric_id = 7;
}
/**
@@ -2422,6 +2566,15 @@ message BluetoothClassicPairingEventReported {
// A status value related to this specific event
// Default: 0
optional int64 event_value = 7;
+ // An identifier that can be used to match events for this device.
+ // The incremental identifier is locally generated and guaranteed not derived
+ // from any globally unique hardware id.
+ // For paired devices, it stays consistent between Bluetooth toggling for the
+ // same remote device.
+ // For unpaired devices, it stays consistent within the same Bluetooth adapter
+ // session for the same remote device.
+ // Default: 0 if the device's metric id is unknown.
+ optional int32 metric_id = 8;
}
/**
@@ -2447,6 +2600,15 @@ message BluetoothSmpPairingEventReported {
// SMP failure reason code
// Default: PAIRING_FAIL_REASON_DEFAULT
optional android.bluetooth.smp.PairingFailReasonEnum smp_fail_reason = 4;
+ // An identifier that can be used to match events for this device.
+ // The incremental identifier is locally generated and guaranteed not derived
+ // from any globally unique hardware id.
+ // For paired devices, it stays consistent between Bluetooth toggling for the
+ // same remote device.
+ // For unpaired devices, it stays consistent within the same Bluetooth adapter
+ // session for the same remote device.
+ // Default: 0 if the device's metric id is unknown.
+ optional int32 metric_id = 5;
}
/**
@@ -2485,6 +2647,15 @@ message BluetoothSocketConnectionStateChanged {
optional int32 server_port = 8;
// Whether this is a server listener socket
optional android.bluetooth.SocketRoleEnum is_server = 9;
+ // An identifier that can be used to match events for this device.
+ // The incremental identifier is locally generated and guaranteed not derived
+ // from any globally unique hardware id.
+ // For paired devices, it stays consistent between Bluetooth toggling for the
+ // same remote device.
+ // For unpaired devices, it stays consistent within the same Bluetooth adapter
+ // session for the same remote device.
+ // Default: 0 if the device's metric id is unknown.
+ optional int32 metric_id = 10;
}
/**
@@ -2508,6 +2679,15 @@ message BluetoothClassOfDeviceReported {
// Also defined in: https://developer.android.com/reference/android/bluetooth/BluetoothClass
// Default: 0
optional int32 class_of_device = 2;
+ // An identifier that can be used to match events for this device.
+ // The incremental identifier is locally generated and guaranteed not derived
+ // from any globally unique hardware id.
+ // For paired devices, it stays consistent between Bluetooth toggling for the
+ // same remote device.
+ // For unpaired devices, it stays consistent within the same Bluetooth adapter
+ // session for the same remote device.
+ // Default: 0 if the device's metric id is unknown.
+ optional int32 metric_id = 3;
}
/**
diff --git a/cmds/statsd/src/external/PullUidProvider.h b/cmds/statsd/src/external/PullUidProvider.h
new file mode 100644
index 000000000000..2318c501ea4b
--- /dev/null
+++ b/cmds/statsd/src/external/PullUidProvider.h
@@ -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.
+ */
+#pragma once
+
+#include <utils/RefBase.h>
+
+#include "StatsPuller.h"
+#include "logd/LogEvent.h"
+
+namespace android {
+namespace os {
+namespace statsd {
+
+class PullUidProvider : virtual public RefBase {
+public:
+ virtual ~PullUidProvider() {}
+
+ /**
+ * @param atomId The atom for which to get the uids.
+ */
+ virtual vector<int32_t> getPullAtomUids(int32_t atomId) = 0;
+};
+
+} // namespace statsd
+} // namespace os
+} // namespace android
diff --git a/cmds/statsd/src/external/StatsPullerManager.cpp b/cmds/statsd/src/external/StatsPullerManager.cpp
index 8b6a5a17bc0e..4ffa3d8666af 100644
--- a/cmds/statsd/src/external/StatsPullerManager.cpp
+++ b/cmds/statsd/src/external/StatsPullerManager.cpp
@@ -47,27 +47,73 @@ const int64_t NO_ALARM_UPDATE = INT64_MAX;
StatsPullerManager::StatsPullerManager()
: kAllPullAtomInfo({
// TrainInfo.
- {{.atomTag = util::TRAIN_INFO}, new TrainInfoPuller()},
+ {{.atomTag = util::TRAIN_INFO, .uid = -1}, new TrainInfoPuller()},
}),
mNextPullTimeNs(NO_ALARM_UPDATE) {
}
-bool StatsPullerManager::Pull(int tagId, vector<shared_ptr<LogEvent>>* data) {
- AutoMutex _l(mLock);
- return PullLocked(tagId, data);
+bool StatsPullerManager::Pull(int tagId, const ConfigKey& configKey,
+ vector<shared_ptr<LogEvent>>* data, bool useUids) {
+ std::lock_guard<std::mutex> _l(mLock);
+ return PullLocked(tagId, configKey, data, useUids);
}
-bool StatsPullerManager::PullLocked(int tagId, vector<shared_ptr<LogEvent>>* data) {
- VLOG("Initiating pulling %d", tagId);
+bool StatsPullerManager::Pull(int tagId, const vector<int32_t>& uids,
+ vector<std::shared_ptr<LogEvent>>* data, bool useUids) {
+ std::lock_guard<std::mutex> _l(mLock);
+ return PullLocked(tagId, uids, data, useUids);
+}
+
+bool StatsPullerManager::PullLocked(int tagId, const ConfigKey& configKey,
+ vector<shared_ptr<LogEvent>>* data, bool useUids) {
+ vector<int32_t> uids;
+ if (useUids) {
+ auto uidProviderIt = mPullUidProviders.find(configKey);
+ if (uidProviderIt == mPullUidProviders.end()) {
+ ALOGE("Error pulling tag %d. No pull uid provider for config key %s", tagId,
+ configKey.ToString().c_str());
+ return false;
+ }
+ sp<PullUidProvider> pullUidProvider = uidProviderIt->second.promote();
+ if (pullUidProvider == nullptr) {
+ ALOGE("Error pulling tag %d, pull uid provider for config %s is gone.", tagId,
+ configKey.ToString().c_str());
+ return false;
+ }
+ uids = pullUidProvider->getPullAtomUids(tagId);
+ }
+ return PullLocked(tagId, uids, data, useUids);
+}
- if (kAllPullAtomInfo.find({.atomTag = tagId}) != kAllPullAtomInfo.end()) {
- bool ret = kAllPullAtomInfo.find({.atomTag = tagId})->second->Pull(data);
- VLOG("pulled %d items", (int)data->size());
- if (!ret) {
- StatsdStats::getInstance().notePullFailed(tagId);
+bool StatsPullerManager::PullLocked(int tagId, const vector<int32_t>& uids,
+ vector<shared_ptr<LogEvent>>* data, bool useUids) {
+ VLOG("Initiating pulling %d", tagId);
+ if (useUids) {
+ for (int32_t uid : uids) {
+ PullerKey key = {.atomTag = tagId, .uid = uid};
+ auto pullerIt = kAllPullAtomInfo.find(key);
+ if (pullerIt != kAllPullAtomInfo.end()) {
+ bool ret = pullerIt->second->Pull(data);
+ VLOG("pulled %zu items", data->size());
+ if (!ret) {
+ StatsdStats::getInstance().notePullFailed(tagId);
+ }
+ return ret;
+ }
}
- return ret;
+ ALOGW("StatsPullerManager: Unknown tagId %d", tagId);
+ return false; // Return early since we don't know what to pull.
} else {
+ PullerKey key = {.atomTag = tagId, .uid = -1};
+ auto pullerIt = kAllPullAtomInfo.find(key);
+ if (pullerIt != kAllPullAtomInfo.end()) {
+ bool ret = pullerIt->second->Pull(data);
+ VLOG("pulled %zu items", data->size());
+ if (!ret) {
+ StatsdStats::getInstance().notePullFailed(tagId);
+ }
+ return ret;
+ }
ALOGW("StatsPullerManager: Unknown tagId %d", tagId);
return false; // Return early since we don't know what to pull.
}
@@ -96,7 +142,7 @@ void StatsPullerManager::updateAlarmLocked() {
void StatsPullerManager::SetStatsCompanionService(
shared_ptr<IStatsCompanionService> statsCompanionService) {
- AutoMutex _l(mLock);
+ std::lock_guard<std::mutex> _l(mLock);
shared_ptr<IStatsCompanionService> tmpForLock = mStatsCompanionService;
mStatsCompanionService = statsCompanionService;
for (const auto& pulledAtom : kAllPullAtomInfo) {
@@ -107,10 +153,11 @@ void StatsPullerManager::SetStatsCompanionService(
}
}
-void StatsPullerManager::RegisterReceiver(int tagId, wp<PullDataReceiver> receiver,
- int64_t nextPullTimeNs, int64_t intervalNs) {
- AutoMutex _l(mLock);
- auto& receivers = mReceivers[tagId];
+void StatsPullerManager::RegisterReceiver(int tagId, const ConfigKey& configKey,
+ wp<PullDataReceiver> receiver, int64_t nextPullTimeNs,
+ int64_t intervalNs) {
+ std::lock_guard<std::mutex> _l(mLock);
+ auto& receivers = mReceivers[{.atomTag = tagId, .configKey = configKey}];
for (auto it = receivers.begin(); it != receivers.end(); it++) {
if (it->receiver == receiver) {
VLOG("Receiver already registered of %d", (int)receivers.size());
@@ -142,13 +189,15 @@ void StatsPullerManager::RegisterReceiver(int tagId, wp<PullDataReceiver> receiv
VLOG("Puller for tagId %d registered of %d", tagId, (int)receivers.size());
}
-void StatsPullerManager::UnRegisterReceiver(int tagId, wp<PullDataReceiver> receiver) {
- AutoMutex _l(mLock);
- if (mReceivers.find(tagId) == mReceivers.end()) {
+void StatsPullerManager::UnRegisterReceiver(int tagId, const ConfigKey& configKey,
+ wp<PullDataReceiver> receiver) {
+ std::lock_guard<std::mutex> _l(mLock);
+ auto receiversIt = mReceivers.find({.atomTag = tagId, .configKey = configKey});
+ if (receiversIt == mReceivers.end()) {
VLOG("Unknown pull code or no receivers: %d", tagId);
return;
}
- auto& receivers = mReceivers.find(tagId)->second;
+ std::list<ReceiverInfo>& receivers = receiversIt->second;
for (auto it = receivers.begin(); it != receivers.end(); it++) {
if (receiver == it->receiver) {
receivers.erase(it);
@@ -158,16 +207,26 @@ void StatsPullerManager::UnRegisterReceiver(int tagId, wp<PullDataReceiver> rece
}
}
+void StatsPullerManager::RegisterPullUidProvider(const ConfigKey& configKey,
+ wp<PullUidProvider> provider) {
+ std::lock_guard<std::mutex> _l(mLock);
+ mPullUidProviders[configKey] = provider;
+}
+
+void StatsPullerManager::UnregisterPullUidProvider(const ConfigKey& configKey) {
+ std::lock_guard<std::mutex> _l(mLock);
+ mPullUidProviders.erase(configKey);
+}
+
void StatsPullerManager::OnAlarmFired(int64_t elapsedTimeNs) {
- AutoMutex _l(mLock);
+ std::lock_guard<std::mutex> _l(mLock);
int64_t wallClockNs = getWallClockNs();
int64_t minNextPullTimeNs = NO_ALARM_UPDATE;
- vector<pair<int, vector<ReceiverInfo*>>> needToPull =
- vector<pair<int, vector<ReceiverInfo*>>>();
+ vector<pair<const ReceiverKey*, vector<ReceiverInfo*>>> needToPull;
for (auto& pair : mReceivers) {
- vector<ReceiverInfo*> receivers = vector<ReceiverInfo*>();
+ vector<ReceiverInfo*> receivers;
if (pair.second.size() != 0) {
for (ReceiverInfo& receiverInfo : pair.second) {
if (receiverInfo.nextPullTimeNs <= elapsedTimeNs) {
@@ -179,17 +238,16 @@ void StatsPullerManager::OnAlarmFired(int64_t elapsedTimeNs) {
}
}
if (receivers.size() > 0) {
- needToPull.push_back(make_pair(pair.first, receivers));
+ needToPull.push_back(make_pair(&pair.first, receivers));
}
}
}
-
for (const auto& pullInfo : needToPull) {
vector<shared_ptr<LogEvent>> data;
- bool pullSuccess = PullLocked(pullInfo.first, &data);
+ bool pullSuccess = PullLocked(pullInfo.first->atomTag, pullInfo.first->configKey, &data);
if (pullSuccess) {
- StatsdStats::getInstance().notePullDelay(
- pullInfo.first, getElapsedRealtimeNs() - elapsedTimeNs);
+ StatsdStats::getInstance().notePullDelay(pullInfo.first->atomTag,
+ getElapsedRealtimeNs() - elapsedTimeNs);
} else {
VLOG("pull failed at %lld, will try again later", (long long)elapsedTimeNs);
}
@@ -248,18 +306,19 @@ int StatsPullerManager::ClearPullerCacheIfNecessary(int64_t timestampNs) {
void StatsPullerManager::RegisterPullAtomCallback(const int uid, const int32_t atomTag,
const int64_t coolDownNs, const int64_t timeoutNs,
const vector<int32_t>& additiveFields,
- const shared_ptr<IPullAtomCallback>& callback) {
- AutoMutex _l(mLock);
+ const shared_ptr<IPullAtomCallback>& callback,
+ bool useUid) {
+ std::lock_guard<std::mutex> _l(mLock);
VLOG("RegisterPullerCallback: adding puller for tag %d", atomTag);
// TODO(b/146439412): linkToDeath with the callback so that we can remove it
// and delete the puller.
StatsdStats::getInstance().notePullerCallbackRegistrationChanged(atomTag, /*registered=*/true);
- kAllPullAtomInfo[{.atomTag = atomTag}] =
+ kAllPullAtomInfo[{.atomTag = atomTag, .uid = useUid ? uid : -1}] =
new StatsCallbackPuller(atomTag, callback, coolDownNs, timeoutNs, additiveFields);
}
void StatsPullerManager::UnregisterPullAtomCallback(const int uid, const int32_t atomTag) {
- AutoMutex _l(mLock);
+ std::lock_guard<std::mutex> _l(mLock);
StatsdStats::getInstance().notePullerCallbackRegistrationChanged(atomTag, /*registered=*/false);
kAllPullAtomInfo.erase({.atomTag = atomTag});
}
diff --git a/cmds/statsd/src/external/StatsPullerManager.h b/cmds/statsd/src/external/StatsPullerManager.h
index e06776623455..714b0aebf7ab 100644
--- a/cmds/statsd/src/external/StatsPullerManager.h
+++ b/cmds/statsd/src/external/StatsPullerManager.h
@@ -19,15 +19,16 @@
#include <aidl/android/os/IPullAtomCallback.h>
#include <aidl/android/os/IStatsCompanionService.h>
#include <utils/RefBase.h>
-#include <utils/threads.h>
#include <list>
#include <vector>
#include "PullDataReceiver.h"
+#include "PullUidProvider.h"
#include "StatsPuller.h"
#include "guardrail/StatsdStats.h"
#include "logd/LogEvent.h"
+#include "packages/UidMap.h"
using aidl::android::os::IPullAtomCallback;
using aidl::android::os::IStatsCompanionService;
@@ -67,11 +68,20 @@ public:
// Registers a receiver for tagId. It will be pulled on the nextPullTimeNs
// and then every intervalNs thereafter.
- virtual void RegisterReceiver(int tagId, wp<PullDataReceiver> receiver, int64_t nextPullTimeNs,
+ virtual void RegisterReceiver(int tagId, const ConfigKey& configKey,
+ wp<PullDataReceiver> receiver, int64_t nextPullTimeNs,
int64_t intervalNs);
// Stop listening on a tagId.
- virtual void UnRegisterReceiver(int tagId, wp<PullDataReceiver> receiver);
+ virtual void UnRegisterReceiver(int tagId, const ConfigKey& configKey,
+ wp<PullDataReceiver> receiver);
+
+ // Registers a pull uid provider for the config key. When pulling atoms, it will be used to
+ // determine which atoms to pull from.
+ virtual void RegisterPullUidProvider(const ConfigKey& configKey, wp<PullUidProvider> provider);
+
+ // Unregister a pull uid provider.
+ virtual void UnregisterPullUidProvider(const ConfigKey& configKey);
// Verify if we know how to pull for this matcher
bool PullerForMatcherExists(int tagId) const;
@@ -85,9 +95,16 @@ public:
// Returns false when
// 1) the pull fails
// 2) pull takes longer than mPullTimeoutNs (intrinsic to puller)
+ // 3) Either a PullUidProvider was not registered for the config, or the there was no puller
+ // registered for any of the uids for this atom.
// If the metric wants to make any change to the data, like timestamps, they
// should make a copy as this data may be shared with multiple metrics.
- virtual bool Pull(int tagId, vector<std::shared_ptr<LogEvent>>* data);
+ virtual bool Pull(int tagId, const ConfigKey& configKey,
+ vector<std::shared_ptr<LogEvent>>* data, bool useUids = false);
+
+ // Same as above, but directly specify the allowed uids to pull from.
+ virtual bool Pull(int tagId, const vector<int32_t>& uids,
+ vector<std::shared_ptr<LogEvent>>* data, bool useUids = false);
// Clear pull data cache immediately.
int ForceClearPullerCache();
@@ -99,7 +116,8 @@ public:
void RegisterPullAtomCallback(const int uid, const int32_t atomTag, const int64_t coolDownNs,
const int64_t timeoutNs, const vector<int32_t>& additiveFields,
- const shared_ptr<IPullAtomCallback>& callback);
+ const shared_ptr<IPullAtomCallback>& callback,
+ bool useUid = false);
void UnregisterPullAtomCallback(const int uid, const int32_t atomTag);
@@ -108,19 +126,36 @@ public:
private:
shared_ptr<IStatsCompanionService> mStatsCompanionService = nullptr;
+ // A struct containing an atom id and a Config Key
+ typedef struct ReceiverKey {
+ const int atomTag;
+ const ConfigKey configKey;
+
+ inline bool operator<(const ReceiverKey& that) const {
+ return atomTag == that.atomTag ? configKey < that.configKey : atomTag < that.atomTag;
+ }
+ } ReceiverKey;
+
typedef struct {
int64_t nextPullTimeNs;
int64_t intervalNs;
wp<PullDataReceiver> receiver;
} ReceiverInfo;
- // mapping from simple matcher tagId to receivers
- std::map<int, std::list<ReceiverInfo>> mReceivers;
+ // mapping from Receiver Key to receivers
+ std::map<ReceiverKey, std::list<ReceiverInfo>> mReceivers;
+
+ // mapping from Config Key to the PullUidProvider for that config
+ std::map<ConfigKey, wp<PullUidProvider>> mPullUidProviders;
+
+ bool PullLocked(int tagId, const ConfigKey& configKey, vector<std::shared_ptr<LogEvent>>* data,
+ bool useUids = false);
- bool PullLocked(int tagId, vector<std::shared_ptr<LogEvent>>* data);
+ bool PullLocked(int tagId, const vector<int32_t>& uids, vector<std::shared_ptr<LogEvent>>* data,
+ bool useUids);
// locks for data receiver and StatsCompanionService changes
- Mutex mLock;
+ std::mutex mLock;
void updateAlarmLocked();
diff --git a/cmds/statsd/src/guardrail/StatsdStats.h b/cmds/statsd/src/guardrail/StatsdStats.h
index df810aa03958..25794c843230 100644
--- a/cmds/statsd/src/guardrail/StatsdStats.h
+++ b/cmds/statsd/src/guardrail/StatsdStats.h
@@ -119,6 +119,8 @@ public:
const static int kMaxLogSourceCount = 50;
+ const static int kMaxPullAtomPackages = 100;
+
// Max memory allowed for storing metrics per configuration. If this limit is exceeded, statsd
// drops the metrics data in memory.
static const size_t kMaxMetricsBytesPerConfig = 2 * 1024 * 1024;
diff --git a/cmds/statsd/src/logd/LogEvent.cpp b/cmds/statsd/src/logd/LogEvent.cpp
index b515d0a5b72f..3b3d0b64bfb3 100644
--- a/cmds/statsd/src/logd/LogEvent.cpp
+++ b/cmds/statsd/src/logd/LogEvent.cpp
@@ -504,12 +504,12 @@ bool LogEvent::parseBuffer(uint8_t* buf, size_t len) {
typeInfo = readNextValue<uint8_t>();
if (getTypeId(typeInfo) != INT64_TYPE) mValid = false;
mElapsedTimestampNs = readNextValue<int64_t>();
- parseAnnotations(getNumAnnotations(typeInfo)); // atom-level annotations
numElements--;
typeInfo = readNextValue<uint8_t>();
if (getTypeId(typeInfo) != INT32_TYPE) mValid = false;
mTagId = readNextValue<int32_t>();
+ parseAnnotations(getNumAnnotations(typeInfo)); // atom-level annotations
numElements--;
diff --git a/cmds/statsd/src/metrics/GaugeMetricProducer.cpp b/cmds/statsd/src/metrics/GaugeMetricProducer.cpp
index 5c606bc98235..42bbd8eb4d35 100644
--- a/cmds/statsd/src/metrics/GaugeMetricProducer.cpp
+++ b/cmds/statsd/src/metrics/GaugeMetricProducer.cpp
@@ -75,11 +75,9 @@ GaugeMetricProducer::GaugeMetricProducer(
const int atomId, const int64_t timeBaseNs, const int64_t startTimeNs,
const sp<StatsPullerManager>& pullerManager,
const unordered_map<int, shared_ptr<Activation>>& eventActivationMap,
- const unordered_map<int, vector<shared_ptr<Activation>>>& eventDeactivationMap,
- const vector<int>& slicedStateAtoms,
- const unordered_map<int, unordered_map<int, int64_t>>& stateGroupMap)
+ const unordered_map<int, vector<shared_ptr<Activation>>>& eventDeactivationMap)
: MetricProducer(metric.id(), key, timeBaseNs, conditionIndex, wizard, eventActivationMap,
- eventDeactivationMap, slicedStateAtoms, stateGroupMap),
+ eventDeactivationMap, /*slicedStateAtoms=*/{}, /*stateGroupMap=*/{}),
mWhatMatcherIndex(whatMatcherIndex),
mEventMatcherWizard(matcherWizard),
mPullerManager(pullerManager),
@@ -135,15 +133,12 @@ GaugeMetricProducer::GaugeMetricProducer(
flushIfNeededLocked(startTimeNs);
// Kicks off the puller immediately.
if (mIsPulled && mSamplingType == GaugeMetric::RANDOM_ONE_SAMPLE) {
- mPullerManager->RegisterReceiver(mPullTagId, this, getCurrentBucketEndTimeNs(),
+ mPullerManager->RegisterReceiver(mPullTagId, mConfigKey, this, getCurrentBucketEndTimeNs(),
mBucketSizeNs);
}
// Adjust start for partial first bucket and then pull if needed
mCurrentBucketStartTimeNs = startTimeNs;
- if (mIsActive && mIsPulled && mSamplingType == GaugeMetric::RANDOM_ONE_SAMPLE) {
- pullAndMatchEventsLocked(mCurrentBucketStartTimeNs);
- }
VLOG("Gauge metric %lld created. bucket size %lld start_time: %lld sliced %d",
(long long)metric.id(), (long long)mBucketSizeNs, (long long)mTimeBaseNs,
@@ -153,7 +148,7 @@ GaugeMetricProducer::GaugeMetricProducer(
GaugeMetricProducer::~GaugeMetricProducer() {
VLOG("~GaugeMetricProducer() called");
if (mIsPulled && mSamplingType == GaugeMetric::RANDOM_ONE_SAMPLE) {
- mPullerManager->UnRegisterReceiver(mPullTagId, this);
+ mPullerManager->UnRegisterReceiver(mPullTagId, mConfigKey, this);
}
}
@@ -298,6 +293,11 @@ void GaugeMetricProducer::onDumpReportLocked(const int64_t dumpTimeNs,
}
}
+void GaugeMetricProducer::prepareFirstBucketLocked() {
+ if (mIsActive && mIsPulled && mSamplingType == GaugeMetric::RANDOM_ONE_SAMPLE) {
+ pullAndMatchEventsLocked(mCurrentBucketStartTimeNs);
+ }
+}
void GaugeMetricProducer::pullAndMatchEventsLocked(const int64_t timestampNs) {
bool triggerPuller = false;
@@ -323,7 +323,7 @@ void GaugeMetricProducer::pullAndMatchEventsLocked(const int64_t timestampNs) {
return;
}
vector<std::shared_ptr<LogEvent>> allData;
- if (!mPullerManager->Pull(mPullTagId, &allData)) {
+ if (!mPullerManager->Pull(mPullTagId, mConfigKey, &allData)) {
ALOGE("Gauge Stats puller failed for tag: %d at %lld", mPullTagId, (long long)timestampNs);
return;
}
diff --git a/cmds/statsd/src/metrics/GaugeMetricProducer.h b/cmds/statsd/src/metrics/GaugeMetricProducer.h
index 284bcc5d10aa..79ec71120f18 100644
--- a/cmds/statsd/src/metrics/GaugeMetricProducer.h
+++ b/cmds/statsd/src/metrics/GaugeMetricProducer.h
@@ -64,9 +64,7 @@ public:
const int64_t startTimeNs, const sp<StatsPullerManager>& pullerManager,
const std::unordered_map<int, std::shared_ptr<Activation>>& eventActivationMap = {},
const std::unordered_map<int, std::vector<std::shared_ptr<Activation>>>&
- eventDeactivationMap = {},
- const vector<int>& slicedStateAtoms = {},
- const unordered_map<int, unordered_map<int, int64_t>>& stateGroupMap = {});
+ eventDeactivationMap = {});
virtual ~GaugeMetricProducer();
@@ -129,6 +127,8 @@ private:
void flushCurrentBucketLocked(const int64_t& eventTimeNs,
const int64_t& nextBucketStartTimeNs) override;
+ void prepareFirstBucketLocked() override;
+
void pullAndMatchEventsLocked(const int64_t timestampNs);
const int mWhatMatcherIndex;
diff --git a/cmds/statsd/src/metrics/MetricProducer.h b/cmds/statsd/src/metrics/MetricProducer.h
index d721514ed1f0..4c4cd8940b24 100644
--- a/cmds/statsd/src/metrics/MetricProducer.h
+++ b/cmds/statsd/src/metrics/MetricProducer.h
@@ -207,6 +207,11 @@ public:
return clearPastBucketsLocked(dumpTimeNs);
}
+ void prepareFirstBucket() {
+ std::lock_guard<std::mutex> lock(mMutex);
+ prepareFirstBucketLocked();
+ }
+
// Returns the memory in bytes currently used to store this metric's data. Does not change
// state.
size_t byteSize() const {
@@ -344,6 +349,7 @@ protected:
std::set<string> *str_set,
android::util::ProtoOutputStream* protoOutput) = 0;
virtual void clearPastBucketsLocked(const int64_t dumpTimeNs) = 0;
+ virtual void prepareFirstBucketLocked(){};
virtual size_t byteSizeLocked() const = 0;
virtual void dumpStatesLocked(FILE* out, bool verbose) const = 0;
virtual void dropDataLocked(const int64_t dropTimeNs) = 0;
diff --git a/cmds/statsd/src/metrics/MetricsManager.cpp b/cmds/statsd/src/metrics/MetricsManager.cpp
index fca48f96f56d..8ed0cbc36779 100644
--- a/cmds/statsd/src/metrics/MetricsManager.cpp
+++ b/cmds/statsd/src/metrics/MetricsManager.cpp
@@ -70,6 +70,7 @@ MetricsManager::MetricsManager(const ConfigKey& key, const StatsdConfig& config,
mTtlEndNs(-1),
mLastReportTimeNs(currentTimeNs),
mLastReportWallClockNs(getWallClockNs()),
+ mPullerManager(pullerManager),
mShouldPersistHistory(config.persist_locally()) {
// Init the ttl end timestamp.
refreshTtl(timeBaseNs);
@@ -86,6 +87,7 @@ MetricsManager::MetricsManager(const ConfigKey& key, const StatsdConfig& config,
mVersionStringsInReport = config.version_strings_in_metric_report();
mInstallerInReport = config.installer_in_metric_report();
+ // Init allowed pushed atom uids.
if (config.allowed_log_source_size() == 0) {
mConfigValid = false;
ALOGE("Log source whitelist is empty! This config won't get any data. Suggest adding at "
@@ -108,6 +110,40 @@ MetricsManager::MetricsManager(const ConfigKey& key, const StatsdConfig& config,
}
}
+ // Init default allowed pull atom uids.
+ int numPullPackages = 0;
+ for (const string& pullSource : config.default_pull_packages()) {
+ auto it = UidMap::sAidToUidMapping.find(pullSource);
+ if (it != UidMap::sAidToUidMapping.end()) {
+ numPullPackages++;
+ mDefaultPullUids.insert(it->second);
+ } else {
+ ALOGE("Default pull atom packages must be in sAidToUidMapping");
+ mConfigValid = false;
+ }
+ }
+ // Init per-atom pull atom packages.
+ for (const PullAtomPackages& pullAtomPackages : config.pull_atom_packages()) {
+ int32_t atomId = pullAtomPackages.atom_id();
+ for (const string& pullPackage : pullAtomPackages.packages()) {
+ numPullPackages++;
+ auto it = UidMap::sAidToUidMapping.find(pullPackage);
+ if (it != UidMap::sAidToUidMapping.end()) {
+ mPullAtomUids[atomId].insert(it->second);
+ } else {
+ mPullAtomPackages[atomId].insert(pullPackage);
+ }
+ }
+ }
+ if (numPullPackages > StatsdStats::kMaxPullAtomPackages) {
+ ALOGE("Too many sources in default_pull_packages and pull_atom_packages. This is likely to "
+ "be an error in the config");
+ mConfigValid = false;
+ } else {
+ initPullAtomSources();
+ }
+ mPullerManager->RegisterPullUidProvider(mConfigKey, this);
+
// Store the sub-configs used.
for (const auto& annotation : config.annotation()) {
mAnnotations.emplace_back(annotation.field_int64(), annotation.field_int32());
@@ -153,6 +189,7 @@ MetricsManager::~MetricsManager() {
StateManager::getInstance().unregisterListener(atomId, it);
}
}
+ mPullerManager->UnregisterPullUidProvider(mConfigKey);
VLOG("~MetricsManager()");
}
@@ -173,6 +210,20 @@ void MetricsManager::initLogSourceWhiteList() {
}
}
+void MetricsManager::initPullAtomSources() {
+ std::lock_guard<std::mutex> lock(mAllowedLogSourcesMutex);
+ mCombinedPullAtomUids.clear();
+ for (const auto& [atomId, uids] : mPullAtomUids) {
+ mCombinedPullAtomUids[atomId].insert(uids.begin(), uids.end());
+ }
+ for (const auto& [atomId, packages] : mPullAtomPackages) {
+ for (const string& pkg : packages) {
+ set<int32_t> uids = mUidMap->getAppUid(pkg);
+ mCombinedPullAtomUids[atomId].insert(uids.begin(), uids.end());
+ }
+ }
+}
+
bool MetricsManager::isConfigValid() const {
return mConfigValid;
}
@@ -184,12 +235,18 @@ void MetricsManager::notifyAppUpgrade(const int64_t& eventTimeNs, const string&
it->notifyAppUpgrade(eventTimeNs, apk, uid, version);
}
// check if we care this package
- if (std::find(mAllowedPkg.begin(), mAllowedPkg.end(), apk) == mAllowedPkg.end()) {
- return;
+ if (std::find(mAllowedPkg.begin(), mAllowedPkg.end(), apk) != mAllowedPkg.end()) {
+ // We will re-initialize the whole list because we don't want to keep the multi mapping of
+ // UID<->pkg inside MetricsManager to reduce the memory usage.
+ initLogSourceWhiteList();
+ }
+
+ for (const auto& it : mPullAtomPackages) {
+ if (it.second.find(apk) != it.second.end()) {
+ initPullAtomSources();
+ return;
+ }
}
- // We will re-initialize the whole list because we don't want to keep the multi mapping of
- // UID<->pkg inside MetricsManager to reduce the memory usage.
- initLogSourceWhiteList();
}
void MetricsManager::notifyAppRemoved(const int64_t& eventTimeNs, const string& apk,
@@ -199,24 +256,49 @@ void MetricsManager::notifyAppRemoved(const int64_t& eventTimeNs, const string&
it->notifyAppRemoved(eventTimeNs, apk, uid);
}
// check if we care this package
- if (std::find(mAllowedPkg.begin(), mAllowedPkg.end(), apk) == mAllowedPkg.end()) {
- return;
+ if (std::find(mAllowedPkg.begin(), mAllowedPkg.end(), apk) != mAllowedPkg.end()) {
+ // We will re-initialize the whole list because we don't want to keep the multi mapping of
+ // UID<->pkg inside MetricsManager to reduce the memory usage.
+ initLogSourceWhiteList();
+ }
+
+ for (const auto& it : mPullAtomPackages) {
+ if (it.second.find(apk) != it.second.end()) {
+ initPullAtomSources();
+ return;
+ }
}
- // We will re-initialize the whole list because we don't want to keep the multi mapping of
- // UID<->pkg inside MetricsManager to reduce the memory usage.
- initLogSourceWhiteList();
}
void MetricsManager::onUidMapReceived(const int64_t& eventTimeNs) {
// Purposefully don't inform metric producers on a new snapshot
// because we don't need to flush partial buckets.
// This occurs if a new user is added/removed or statsd crashes.
+ initPullAtomSources();
+
if (mAllowedPkg.size() == 0) {
return;
}
initLogSourceWhiteList();
}
+void MetricsManager::init() {
+ for (const auto& producer : mAllMetricProducers) {
+ producer->prepareFirstBucket();
+ }
+}
+
+vector<int32_t> MetricsManager::getPullAtomUids(int32_t atomId) {
+ std::lock_guard<std::mutex> lock(mAllowedLogSourcesMutex);
+ vector<int32_t> uids;
+ const auto& it = mCombinedPullAtomUids.find(atomId);
+ if (it != mCombinedPullAtomUids.end()) {
+ uids.insert(uids.end(), it->second.begin(), it->second.end());
+ }
+ uids.insert(uids.end(), mDefaultPullUids.begin(), mDefaultPullUids.end());
+ return uids;
+}
+
void MetricsManager::dumpStates(FILE* out, bool verbose) {
fprintf(out, "ConfigKey %s, allowed source:", mConfigKey.ToString().c_str());
{
diff --git a/cmds/statsd/src/metrics/MetricsManager.h b/cmds/statsd/src/metrics/MetricsManager.h
index 7500ec91ce30..291f97ba03b4 100644
--- a/cmds/statsd/src/metrics/MetricsManager.h
+++ b/cmds/statsd/src/metrics/MetricsManager.h
@@ -35,7 +35,7 @@ namespace os {
namespace statsd {
// A MetricsManager is responsible for managing metrics from one single config source.
-class MetricsManager : public virtual android::RefBase {
+class MetricsManager : public virtual android::RefBase, public virtual PullUidProvider {
public:
MetricsManager(const ConfigKey& configKey, const StatsdConfig& config, const int64_t timeBaseNs,
const int64_t currentTimeNs, const sp<UidMap>& uidMap,
@@ -69,6 +69,10 @@ public:
void onUidMapReceived(const int64_t& eventTimeNs);
+ void init();
+
+ vector<int32_t> getPullAtomUids(int32_t atomId) override;
+
bool shouldWriteToDisk() const {
return mNoReportMetricIds.size() != mAllMetricProducers.size();
}
@@ -159,6 +163,8 @@ private:
int64_t mLastReportTimeNs;
int64_t mLastReportWallClockNs;
+ sp<StatsPullerManager> mPullerManager;
+
// The uid log sources from StatsdConfig.
std::vector<int32_t> mAllowedUid;
@@ -169,13 +175,27 @@ private:
// Logs from uids that are not in the list will be ignored to avoid spamming.
std::set<int32_t> mAllowedLogSources;
+ // To guard access to mAllowedLogSources
+ mutable std::mutex mAllowedLogSourcesMutex;
+
+ // We can pull any atom from these uids.
+ std::set<int32_t> mDefaultPullUids;
+
+ // Uids that specific atoms can pull from.
+ // This is a map<atom id, set<uids>>
+ std::map<int32_t, std::set<int32_t>> mPullAtomUids;
+
+ // Packages that specific atoms can be pulled from.
+ std::map<int32_t, std::set<std::string>> mPullAtomPackages;
+
+ // All uids to pull for this atom. NOTE: Does not include the default uids for memory.
+ std::map<int32_t, std::set<int32_t>> mCombinedPullAtomUids;
+
// Contains the annotations passed in with StatsdConfig.
std::list<std::pair<const int64_t, const int32_t>> mAnnotations;
const bool mShouldPersistHistory;
- // To guard access to mAllowedLogSources
- mutable std::mutex mAllowedLogSourcesMutex;
// All event tags that are interesting to my metrics.
std::set<int> mTagIds;
@@ -238,6 +258,8 @@ private:
void initLogSourceWhiteList();
+ void initPullAtomSources();
+
// The metrics that don't need to be uploaded or even reported.
std::set<int64_t> mNoReportMetricIds;
@@ -275,6 +297,8 @@ private:
FRIEND_TEST(MetricActivationE2eTest, TestCountMetricWithSameDeactivation);
FRIEND_TEST(MetricActivationE2eTest, TestCountMetricWithTwoMetricsTwoDeactivations);
+ FRIEND_TEST(MetricsManagerTest, TestLogSources);
+
FRIEND_TEST(StatsLogProcessorTest, TestActiveConfigMetricDiskWriteRead);
FRIEND_TEST(StatsLogProcessorTest, TestActivationOnBoot);
FRIEND_TEST(StatsLogProcessorTest, TestActivationOnBootMultipleActivations);
diff --git a/cmds/statsd/src/metrics/ValueMetricProducer.cpp b/cmds/statsd/src/metrics/ValueMetricProducer.cpp
index dc9b41303894..f34423a27aff 100644
--- a/cmds/statsd/src/metrics/ValueMetricProducer.cpp
+++ b/cmds/statsd/src/metrics/ValueMetricProducer.cpp
@@ -156,7 +156,7 @@ ValueMetricProducer::ValueMetricProducer(
flushIfNeededLocked(startTimeNs);
if (mIsPulled) {
- mPullerManager->RegisterReceiver(mPullTagId, this, getCurrentBucketEndTimeNs(),
+ mPullerManager->RegisterReceiver(mPullTagId, mConfigKey, this, getCurrentBucketEndTimeNs(),
mBucketSizeNs);
}
@@ -166,10 +166,6 @@ ValueMetricProducer::ValueMetricProducer(
mCurrentBucketStartTimeNs = startTimeNs;
mConditionTimer.newBucketStart(mCurrentBucketStartTimeNs);
- // Kicks off the puller immediately if condition is true and diff based.
- if (mIsActive && mIsPulled && mCondition == ConditionState::kTrue && mUseDiff) {
- pullAndMatchEventsLocked(mCurrentBucketStartTimeNs);
- }
// Now that activations are processed, start the condition timer if needed.
mConditionTimer.onConditionChanged(mIsActive && mCondition == ConditionState::kTrue,
mCurrentBucketStartTimeNs);
@@ -181,7 +177,7 @@ ValueMetricProducer::ValueMetricProducer(
ValueMetricProducer::~ValueMetricProducer() {
VLOG("~ValueMetricProducer() called");
if (mIsPulled) {
- mPullerManager->UnRegisterReceiver(mPullTagId, this);
+ mPullerManager->UnRegisterReceiver(mPullTagId, mConfigKey, this);
}
}
@@ -503,9 +499,16 @@ void ValueMetricProducer::onConditionChangedLocked(const bool condition,
mConditionTimer.onConditionChanged(mCondition, eventTimeNs);
}
+void ValueMetricProducer::prepareFirstBucketLocked() {
+ // Kicks off the puller immediately if condition is true and diff based.
+ if (mIsActive && mIsPulled && mCondition == ConditionState::kTrue && mUseDiff) {
+ pullAndMatchEventsLocked(mCurrentBucketStartTimeNs);
+ }
+}
+
void ValueMetricProducer::pullAndMatchEventsLocked(const int64_t timestampNs) {
vector<std::shared_ptr<LogEvent>> allData;
- if (!mPullerManager->Pull(mPullTagId, &allData)) {
+ if (!mPullerManager->Pull(mPullTagId, mConfigKey, &allData)) {
ALOGE("Stats puller failed for tag: %d at %lld", mPullTagId, (long long)timestampNs);
invalidateCurrentBucket(timestampNs, BucketDropReason::PULL_FAILED);
return;
diff --git a/cmds/statsd/src/metrics/ValueMetricProducer.h b/cmds/statsd/src/metrics/ValueMetricProducer.h
index 50317b341843..e9273dc54424 100644
--- a/cmds/statsd/src/metrics/ValueMetricProducer.h
+++ b/cmds/statsd/src/metrics/ValueMetricProducer.h
@@ -122,6 +122,8 @@ private:
void flushCurrentBucketLocked(const int64_t& eventTimeNs,
const int64_t& nextBucketStartTimeNs) override;
+ void prepareFirstBucketLocked() override;
+
void dropDataLocked(const int64_t dropTimeNs) override;
// Calculate previous bucket end time based on current time.
diff --git a/cmds/statsd/src/metrics/metrics_manager_util.cpp b/cmds/statsd/src/metrics/metrics_manager_util.cpp
index e5fe87acc720..3810c486cf88 100644
--- a/cmds/statsd/src/metrics/metrics_manager_util.cpp
+++ b/cmds/statsd/src/metrics/metrics_manager_util.cpp
@@ -803,9 +803,8 @@ bool initMetrics(const ConfigKey& key, const StatsdConfig& config, const int64_t
if (!success) return false;
sp<MetricProducer> gaugeProducer = new GaugeMetricProducer(
- key, metric, conditionIndex, wizard,
- trackerIndex, matcherWizard, pullTagId, triggerAtomId, atomTagId,
- timeBaseTimeNs, currentTimeNs, pullerManager,
+ key, metric, conditionIndex, wizard, trackerIndex, matcherWizard, pullTagId,
+ triggerAtomId, atomTagId, timeBaseTimeNs, currentTimeNs, pullerManager,
eventActivationMap, eventDeactivationMap);
allMetricProducers.push_back(gaugeProducer);
}
@@ -964,6 +963,7 @@ bool initStatsdConfig(const ConfigKey& key, const StatsdConfig& config, UidMap&
ALOGE("initConditionTrackers failed");
return false;
}
+
if (!initStates(config, stateAtomIdMap, allStateGroupMaps)) {
ALOGE("initStates failed");
return false;
diff --git a/cmds/statsd/src/packages/UidMap.cpp b/cmds/statsd/src/packages/UidMap.cpp
index ab0e86e24b02..acf40c88a00d 100644
--- a/cmds/statsd/src/packages/UidMap.cpp
+++ b/cmds/statsd/src/packages/UidMap.cpp
@@ -545,7 +545,15 @@ const std::map<string, uint32_t> UidMap::sAidToUidMapping = {{"AID_ROOT", 0},
{"AID_LMKD", 1069},
{"AID_LLKD", 1070},
{"AID_IORAPD", 1071},
+ {"AID_GPU_SERVICE", 1072},
{"AID_NETWORK_STACK", 1073},
+ {"AID_GSID", 1074},
+ {"AID_FSVERITY_CERT", 1075},
+ {"AID_CREDSTORE", 1076},
+ {"AID_EXTERNAL_STORAGE", 1077},
+ {"AID_EXT_DATA_RW", 1078},
+ {"AID_EXT_OBB_RW", 1079},
+ {"AID_CONTEXT_HUB", 1080},
{"AID_SHELL", 2000},
{"AID_CACHE", 2001},
{"AID_DIAG", 2002}};
diff --git a/cmds/statsd/src/packages/UidMap.h b/cmds/statsd/src/packages/UidMap.h
index 02fe7b1f5003..22250aee402e 100644
--- a/cmds/statsd/src/packages/UidMap.h
+++ b/cmds/statsd/src/packages/UidMap.h
@@ -149,7 +149,7 @@ public:
// Get currently cached value of memory used by UID map.
size_t getBytesUsed() const;
- std::set<int32_t> getAppUid(const string& package) const;
+ virtual std::set<int32_t> getAppUid(const string& package) const;
// Write current PackageInfoSnapshot to ProtoOutputStream.
// interestingUids: If not empty, only write the package info for these uids. If empty, write
diff --git a/cmds/statsd/src/shell/ShellSubscriber.cpp b/cmds/statsd/src/shell/ShellSubscriber.cpp
index c677222f31eb..1cee4d9babdc 100644
--- a/cmds/statsd/src/shell/ShellSubscriber.cpp
+++ b/cmds/statsd/src/shell/ShellSubscriber.cpp
@@ -108,7 +108,21 @@ bool ShellSubscriber::readConfig(shared_ptr<SubscriptionInfo> subscriptionInfo)
if (minInterval < 0 || pulled.freq_millis() < minInterval) {
minInterval = pulled.freq_millis();
}
- subscriptionInfo->mPulledInfo.emplace_back(pulled.matcher(), pulled.freq_millis());
+
+ vector<string> packages;
+ vector<int32_t> uids;
+ for (const string& pkg : pulled.packages()) {
+ auto it = UidMap::sAidToUidMapping.find(pkg);
+ if (it != UidMap::sAidToUidMapping.end()) {
+ uids.push_back(it->second);
+ } else {
+ packages.push_back(pkg);
+ }
+ }
+
+ subscriptionInfo->mPulledInfo.emplace_back(pulled.matcher(), pulled.freq_millis(), packages,
+ uids);
+ VLOG("adding matcher for pulled atom %d", pulled.matcher().atom_id());
}
subscriptionInfo->mPullIntervalMin = minInterval;
@@ -127,7 +141,15 @@ void ShellSubscriber::startPull(int64_t myToken) {
for (auto& pullInfo : mSubscriptionInfo->mPulledInfo) {
if (pullInfo.mPrevPullElapsedRealtimeMs + pullInfo.mInterval < nowMillis) {
vector<std::shared_ptr<LogEvent>> data;
- mPullerMgr->Pull(pullInfo.mPullerMatcher.atom_id(), &data);
+ vector<int32_t> uids;
+ uids.insert(uids.end(), pullInfo.mPullUids.begin(), pullInfo.mPullUids.end());
+ // This is slow. Consider storing the uids per app and listening to uidmap updates.
+ for (const string& pkg : pullInfo.mPullPackages) {
+ set<int32_t> uidsForPkg = mUidMap->getAppUid(pkg);
+ uids.insert(uids.end(), uidsForPkg.begin(), uidsForPkg.end());
+ }
+ uids.push_back(DEFAULT_PULL_UID);
+ mPullerMgr->Pull(pullInfo.mPullerMatcher.atom_id(), uids, &data);
VLOG("pulled %zu atoms with id %d", data.size(), pullInfo.mPullerMatcher.atom_id());
// TODO(b/150969574): Don't write to a pipe while holding a lock.
diff --git a/cmds/statsd/src/shell/ShellSubscriber.h b/cmds/statsd/src/shell/ShellSubscriber.h
index 2f9b61a257a8..61457d89f224 100644
--- a/cmds/statsd/src/shell/ShellSubscriber.h
+++ b/cmds/statsd/src/shell/ShellSubscriber.h
@@ -16,15 +16,17 @@
#pragma once
-#include "logd/LogEvent.h"
-
#include <android/util/ProtoOutputStream.h>
+#include <private/android_filesystem_config.h>
+
#include <condition_variable>
#include <mutex>
#include <thread>
+
#include "external/StatsPullerManager.h"
#include "frameworks/base/cmds/statsd/src/shell/shell_config.pb.h"
#include "frameworks/base/cmds/statsd/src/statsd_config.pb.h"
+#include "logd/LogEvent.h"
#include "packages/UidMap.h"
namespace android {
@@ -66,12 +68,19 @@ public:
private:
struct PullInfo {
- PullInfo(const SimpleAtomMatcher& matcher, int64_t interval)
- : mPullerMatcher(matcher), mInterval(interval), mPrevPullElapsedRealtimeMs(0) {
+ PullInfo(const SimpleAtomMatcher& matcher, int64_t interval,
+ const std::vector<std::string>& packages, const std::vector<int32_t>& uids)
+ : mPullerMatcher(matcher),
+ mInterval(interval),
+ mPrevPullElapsedRealtimeMs(0),
+ mPullPackages(packages),
+ mPullUids(uids) {
}
SimpleAtomMatcher mPullerMatcher;
int64_t mInterval;
int64_t mPrevPullElapsedRealtimeMs;
+ std::vector<std::string> mPullPackages;
+ std::vector<int32_t> mPullUids;
};
struct SubscriptionInfo {
@@ -109,6 +118,8 @@ private:
std::shared_ptr<SubscriptionInfo> mSubscriptionInfo = nullptr;
int mToken = 0;
+
+ const int32_t DEFAULT_PULL_UID = AID_SYSTEM;
};
} // namespace statsd
diff --git a/cmds/statsd/src/shell/shell_config.proto b/cmds/statsd/src/shell/shell_config.proto
index 73cb49a61821..07d0310ef2dd 100644
--- a/cmds/statsd/src/shell/shell_config.proto
+++ b/cmds/statsd/src/shell/shell_config.proto
@@ -28,6 +28,9 @@ message PulledAtomSubscription {
/* gap between two pulls in milliseconds */
optional int32 freq_millis = 2;
+
+ /* Packages that the pull is requested from */
+ repeated string packages = 3;
}
message ShellSubscription {
diff --git a/cmds/statsd/src/statsd_config.proto b/cmds/statsd/src/statsd_config.proto
index 736aa9be2fdb..83d9484c77ba 100644
--- a/cmds/statsd/src/statsd_config.proto
+++ b/cmds/statsd/src/statsd_config.proto
@@ -428,6 +428,12 @@ message MetricActivation {
repeated EventActivation event_activation = 2;
}
+message PullAtomPackages {
+ optional int32 atom_id = 1;
+
+ repeated string packages = 2;
+}
+
message StatsdConfig {
optional int64 id = 1;
@@ -475,6 +481,10 @@ message StatsdConfig {
repeated State state = 21;
+ repeated string default_pull_packages = 22;
+
+ repeated PullAtomPackages pull_atom_packages = 23;
+
// Field number 1000 is reserved for later use.
reserved 1000;
}
diff --git a/cmds/statsd/tests/MetricsManager_test.cpp b/cmds/statsd/tests/MetricsManager_test.cpp
index 356e40b9b99d..1075fe4f9ce1 100644
--- a/cmds/statsd/tests/MetricsManager_test.cpp
+++ b/cmds/statsd/tests/MetricsManager_test.cpp
@@ -13,7 +13,15 @@
// limitations under the License.
#include <gtest/gtest.h>
+#include <private/android_filesystem_config.h>
+#include <stdio.h>
+#include <set>
+#include <unordered_map>
+#include <vector>
+
+#include "frameworks/base/cmds/statsd/src/statsd_config.pb.h"
+#include "metrics/metrics_test_helper.h"
#include "src/condition/ConditionTracker.h"
#include "src/matchers/LogMatchingTracker.h"
#include "src/metrics/CountMetricProducer.h"
@@ -23,22 +31,21 @@
#include "src/metrics/metrics_manager_util.h"
#include "statsd_test_util.h"
-#include "frameworks/base/cmds/statsd/src/statsd_config.pb.h"
-
-#include <stdio.h>
-#include <set>
-#include <unordered_map>
-#include <vector>
-
-using namespace android::os::statsd;
+using namespace testing;
using android::sp;
+using android::os::statsd::Predicate;
+using std::map;
using std::set;
using std::unordered_map;
using std::vector;
-using android::os::statsd::Predicate;
#ifdef __ANDROID__
+namespace android {
+namespace os {
+namespace statsd {
+
+namespace {
const ConfigKey kConfigKey(0, 12345);
const long kAlertId = 3;
@@ -268,6 +275,11 @@ StatsdConfig buildCirclePredicates() {
return config;
}
+bool isSubset(const set<int32_t>& set1, const set<int32_t>& set2) {
+ return std::includes(set2.begin(), set2.end(), set1.begin(), set1.end());
+}
+} // anonymous namespace
+
TEST(MetricsManagerTest, TestGoodConfig) {
UidMap uidMap;
sp<StatsPullerManager> pullerManager = new StatsPullerManager();
@@ -488,6 +500,101 @@ TEST(MetricsManagerTest, testAlertWithUnknownMetric) {
noReportMetricIds));
}
+TEST(MetricsManagerTest, TestLogSources) {
+ string app1 = "app1";
+ set<int32_t> app1Uids = {1111, 11111};
+ string app2 = "app2";
+ set<int32_t> app2Uids = {2222};
+ string app3 = "app3";
+ set<int32_t> app3Uids = {3333, 1111};
+
+ map<string, set<int32_t>> pkgToUids;
+ pkgToUids[app1] = app1Uids;
+ pkgToUids[app2] = app2Uids;
+ pkgToUids[app3] = app3Uids;
+
+ int32_t atom1 = 10;
+ int32_t atom2 = 20;
+ int32_t atom3 = 30;
+ sp<MockUidMap> uidMap = new StrictMock<MockUidMap>();
+ EXPECT_CALL(*uidMap, getAppUid(_))
+ .Times(4)
+ .WillRepeatedly(Invoke([&pkgToUids](const string& pkg) {
+ const auto& it = pkgToUids.find(pkg);
+ if (it != pkgToUids.end()) {
+ return it->second;
+ }
+ return set<int32_t>();
+ }));
+ sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
+ EXPECT_CALL(*pullerManager, RegisterPullUidProvider(kConfigKey, _)).Times(1);
+ EXPECT_CALL(*pullerManager, UnregisterPullUidProvider(kConfigKey)).Times(1);
+
+ sp<AlarmMonitor> anomalyAlarmMonitor;
+ sp<AlarmMonitor> periodicAlarmMonitor;
+
+ StatsdConfig config = buildGoodConfig();
+ config.add_allowed_log_source("AID_SYSTEM");
+ config.add_allowed_log_source(app1);
+ config.add_default_pull_packages("AID_SYSTEM");
+ config.add_default_pull_packages("AID_ROOT");
+
+ const set<int32_t> defaultPullUids = {AID_SYSTEM, AID_ROOT};
+
+ PullAtomPackages* pullAtomPackages = config.add_pull_atom_packages();
+ pullAtomPackages->set_atom_id(atom1);
+ pullAtomPackages->add_packages(app1);
+ pullAtomPackages->add_packages(app3);
+
+ pullAtomPackages = config.add_pull_atom_packages();
+ pullAtomPackages->set_atom_id(atom2);
+ pullAtomPackages->add_packages(app2);
+ pullAtomPackages->add_packages("AID_STATSD");
+
+ MetricsManager metricsManager(kConfigKey, config, timeBaseSec, timeBaseSec, uidMap,
+ pullerManager, anomalyAlarmMonitor, periodicAlarmMonitor);
+
+ EXPECT_TRUE(metricsManager.isConfigValid());
+
+ ASSERT_EQ(metricsManager.mAllowedUid.size(), 1);
+ EXPECT_EQ(metricsManager.mAllowedUid[0], AID_SYSTEM);
+
+ ASSERT_EQ(metricsManager.mAllowedPkg.size(), 1);
+ EXPECT_EQ(metricsManager.mAllowedPkg[0], app1);
+
+ ASSERT_EQ(metricsManager.mAllowedLogSources.size(), 3);
+ EXPECT_TRUE(isSubset({AID_SYSTEM}, metricsManager.mAllowedLogSources));
+ EXPECT_TRUE(isSubset(app1Uids, metricsManager.mAllowedLogSources));
+
+ ASSERT_EQ(metricsManager.mDefaultPullUids.size(), 2);
+ EXPECT_TRUE(isSubset(defaultPullUids, metricsManager.mDefaultPullUids));
+ ;
+
+ vector<int32_t> atom1Uids = metricsManager.getPullAtomUids(atom1);
+ ASSERT_EQ(atom1Uids.size(), 5);
+ set<int32_t> expectedAtom1Uids;
+ expectedAtom1Uids.insert(defaultPullUids.begin(), defaultPullUids.end());
+ expectedAtom1Uids.insert(app1Uids.begin(), app1Uids.end());
+ expectedAtom1Uids.insert(app3Uids.begin(), app3Uids.end());
+ EXPECT_TRUE(isSubset(expectedAtom1Uids, set<int32_t>(atom1Uids.begin(), atom1Uids.end())));
+
+ vector<int32_t> atom2Uids = metricsManager.getPullAtomUids(atom2);
+ ASSERT_EQ(atom2Uids.size(), 4);
+ set<int32_t> expectedAtom2Uids;
+ expectedAtom1Uids.insert(defaultPullUids.begin(), defaultPullUids.end());
+ expectedAtom1Uids.insert(app2Uids.begin(), app2Uids.end());
+ expectedAtom1Uids.insert(AID_STATSD);
+ EXPECT_TRUE(isSubset(expectedAtom2Uids, set<int32_t>(atom2Uids.begin(), atom2Uids.end())));
+
+ vector<int32_t> atom3Uids = metricsManager.getPullAtomUids(atom3);
+ ASSERT_EQ(atom3Uids.size(), 2);
+ EXPECT_TRUE(isSubset(defaultPullUids, set<int32_t>(atom3Uids.begin(), atom3Uids.end())));
+}
+
+} // namespace statsd
+} // namespace os
+} // namespace android
+
#else
GTEST_LOG_(INFO) << "This test does nothing.\n";
#endif
diff --git a/cmds/statsd/tests/e2e/GaugeMetric_e2e_pull_test.cpp b/cmds/statsd/tests/e2e/GaugeMetric_e2e_pull_test.cpp
index ca4de6d49fb1..c234b14f12d0 100644
--- a/cmds/statsd/tests/e2e/GaugeMetric_e2e_pull_test.cpp
+++ b/cmds/statsd/tests/e2e/GaugeMetric_e2e_pull_test.cpp
@@ -38,6 +38,7 @@ StatsdConfig CreateStatsdConfig(const GaugeMetric::SamplingType sampling_type,
bool useCondition = true) {
StatsdConfig config;
config.add_allowed_log_source("AID_ROOT"); // LogEvent defaults to UID of root.
+ config.add_default_pull_packages("AID_ROOT"); // Fake puller is registered with root.
auto atomMatcher = CreateSimpleAtomMatcher("TestMatcher", ATOM_TAG);
*config.add_atom_matcher() = atomMatcher;
*config.add_atom_matcher() = CreateScreenTurnedOnAtomMatcher();
diff --git a/cmds/statsd/tests/e2e/PartialBucket_e2e_test.cpp b/cmds/statsd/tests/e2e/PartialBucket_e2e_test.cpp
index 371a34625b79..b173ee0334a7 100644
--- a/cmds/statsd/tests/e2e/PartialBucket_e2e_test.cpp
+++ b/cmds/statsd/tests/e2e/PartialBucket_e2e_test.cpp
@@ -71,6 +71,7 @@ StatsdConfig MakeConfig() {
StatsdConfig MakeValueMetricConfig(int64_t minTime) {
StatsdConfig config;
config.add_allowed_log_source("AID_ROOT"); // LogEvent defaults to UID of root.
+ config.add_default_pull_packages("AID_ROOT"); // Fake puller is registered with root.
auto pulledAtomMatcher =
CreateSimpleAtomMatcher("TestMatcher", util::SUBSYSTEM_SLEEP_STATE);
@@ -94,6 +95,7 @@ StatsdConfig MakeValueMetricConfig(int64_t minTime) {
StatsdConfig MakeGaugeMetricConfig(int64_t minTime) {
StatsdConfig config;
config.add_allowed_log_source("AID_ROOT"); // LogEvent defaults to UID of root.
+ config.add_default_pull_packages("AID_ROOT"); // Fake puller is registered with root.
auto pulledAtomMatcher =
CreateSimpleAtomMatcher("TestMatcher", util::SUBSYSTEM_SLEEP_STATE);
diff --git a/cmds/statsd/tests/e2e/ValueMetric_pull_e2e_test.cpp b/cmds/statsd/tests/e2e/ValueMetric_pull_e2e_test.cpp
index a5ef733b0287..0c4a7c69c8e7 100644
--- a/cmds/statsd/tests/e2e/ValueMetric_pull_e2e_test.cpp
+++ b/cmds/statsd/tests/e2e/ValueMetric_pull_e2e_test.cpp
@@ -36,6 +36,7 @@ const int64_t metricId = 123456;
StatsdConfig CreateStatsdConfig(bool useCondition = true) {
StatsdConfig config;
config.add_allowed_log_source("AID_ROOT"); // LogEvent defaults to UID of root.
+ config.add_default_pull_packages("AID_ROOT"); // Fake puller is registered with root.
auto pulledAtomMatcher =
CreateSimpleAtomMatcher("TestMatcher", util::SUBSYSTEM_SLEEP_STATE);
*config.add_atom_matcher() = pulledAtomMatcher;
diff --git a/cmds/statsd/tests/external/StatsCallbackPuller_test.cpp b/cmds/statsd/tests/external/StatsCallbackPuller_test.cpp
index 1ff66218f22c..6aff9ef80a71 100644
--- a/cmds/statsd/tests/external/StatsCallbackPuller_test.cpp
+++ b/cmds/statsd/tests/external/StatsCallbackPuller_test.cpp
@@ -187,15 +187,16 @@ TEST_F(StatsCallbackPullerTest, RegisterAndTimeout) {
pullDelayNs = 500000000; // 500 ms.
pullTimeoutNs = 10000; // 10 microsseconds.
int64_t value = 4321;
+ int32_t uid = 123;
values.push_back(value);
StatsPullerManager pullerManager;
- pullerManager.RegisterPullAtomCallback(/*uid=*/-1, pullTagId, pullCoolDownNs, pullTimeoutNs,
+ pullerManager.RegisterPullAtomCallback(uid, pullTagId, pullCoolDownNs, pullTimeoutNs,
vector<int32_t>(), cb);
vector<shared_ptr<LogEvent>> dataHolder;
int64_t startTimeNs = getElapsedRealtimeNs();
// Returns false, since StatsPuller code will evaluate the timeout.
- EXPECT_FALSE(pullerManager.Pull(pullTagId, &dataHolder));
+ EXPECT_FALSE(pullerManager.Pull(pullTagId, {uid}, &dataHolder));
int64_t endTimeNs = getElapsedRealtimeNs();
int64_t actualPullDurationNs = endTimeNs - startTimeNs;
diff --git a/cmds/statsd/tests/external/StatsPullerManager_test.cpp b/cmds/statsd/tests/external/StatsPullerManager_test.cpp
new file mode 100644
index 000000000000..6b3f4cccb95b
--- /dev/null
+++ b/cmds/statsd/tests/external/StatsPullerManager_test.cpp
@@ -0,0 +1,150 @@
+// 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 "src/external/StatsPullerManager.h"
+
+#include <aidl/android/os/IPullAtomResultReceiver.h>
+#include <aidl/android/util/StatsEventParcel.h>
+#include <gmock/gmock.h>
+#include <gtest/gtest.h>
+
+#include "stats_event.h"
+#include "tests/statsd_test_util.h"
+
+using aidl::android::util::StatsEventParcel;
+using ::ndk::SharedRefBase;
+using std::make_shared;
+using std::shared_ptr;
+using std::vector;
+
+namespace android {
+namespace os {
+namespace statsd {
+
+namespace {
+
+int pullTagId1 = 10101;
+int pullTagId2 = 10102;
+int uid1 = 9999;
+int uid2 = 8888;
+ConfigKey configKey(50, 12345);
+ConfigKey badConfigKey(60, 54321);
+int unregisteredUid = 98765;
+int64_t coolDownNs = NS_PER_SEC;
+int64_t timeoutNs = NS_PER_SEC / 2;
+
+AStatsEvent* createSimpleEvent(int32_t atomId, int32_t value) {
+ AStatsEvent* event = AStatsEvent_obtain();
+ AStatsEvent_setAtomId(event, atomId);
+ AStatsEvent_writeInt32(event, value);
+ AStatsEvent_build(event);
+ return event;
+}
+
+class FakePullAtomCallback : public BnPullAtomCallback {
+public:
+ FakePullAtomCallback(int32_t uid) : mUid(uid){};
+ Status onPullAtom(int atomTag,
+ const shared_ptr<IPullAtomResultReceiver>& resultReceiver) override {
+ vector<StatsEventParcel> parcels;
+ AStatsEvent* event = createSimpleEvent(atomTag, mUid);
+ size_t size;
+ uint8_t* buffer = AStatsEvent_getBuffer(event, &size);
+
+ StatsEventParcel p;
+ // vector.assign() creates a copy, but this is inevitable unless
+ // stats_event.h/c uses a vector as opposed to a buffer.
+ p.buffer.assign(buffer, buffer + size);
+ parcels.push_back(std::move(p));
+ AStatsEvent_release(event);
+ resultReceiver->pullFinished(atomTag, /*success*/ true, parcels);
+ return Status::ok();
+ }
+ int32_t mUid;
+};
+
+class FakePullUidProvider : public PullUidProvider {
+public:
+ vector<int32_t> getPullAtomUids(int atomId) override {
+ if (atomId == pullTagId1) {
+ return {uid2, uid1};
+ } else if (atomId == pullTagId2) {
+ return {uid2};
+ }
+ return {};
+ }
+};
+
+sp<StatsPullerManager> createPullerManagerAndRegister() {
+ sp<StatsPullerManager> pullerManager = new StatsPullerManager();
+ shared_ptr<FakePullAtomCallback> cb1 = SharedRefBase::make<FakePullAtomCallback>(uid1);
+ pullerManager->RegisterPullAtomCallback(uid1, pullTagId1, coolDownNs, timeoutNs, {}, cb1, true);
+ shared_ptr<FakePullAtomCallback> cb2 = SharedRefBase::make<FakePullAtomCallback>(uid2);
+ pullerManager->RegisterPullAtomCallback(uid2, pullTagId1, coolDownNs, timeoutNs, {}, cb2, true);
+ pullerManager->RegisterPullAtomCallback(uid1, pullTagId2, coolDownNs, timeoutNs, {}, cb1, true);
+ return pullerManager;
+}
+} // anonymous namespace
+
+TEST(StatsPullerManagerTest, TestPullInvalidUid) {
+ sp<StatsPullerManager> pullerManager = createPullerManagerAndRegister();
+
+ vector<shared_ptr<LogEvent>> data;
+ EXPECT_FALSE(pullerManager->Pull(pullTagId1, {unregisteredUid}, &data, true));
+}
+
+TEST(StatsPullerManagerTest, TestPullChoosesCorrectUid) {
+ sp<StatsPullerManager> pullerManager = createPullerManagerAndRegister();
+
+ vector<shared_ptr<LogEvent>> data;
+ EXPECT_TRUE(pullerManager->Pull(pullTagId1, {uid1}, &data, true));
+ ASSERT_EQ(data.size(), 1);
+ EXPECT_EQ(data[0]->GetTagId(), pullTagId1);
+ ASSERT_EQ(data[0]->getValues().size(), 1);
+ EXPECT_EQ(data[0]->getValues()[0].mValue.int_value, uid1);
+}
+
+TEST(StatsPullerManagerTest, TestPullInvalidConfigKey) {
+ sp<StatsPullerManager> pullerManager = createPullerManagerAndRegister();
+ sp<FakePullUidProvider> uidProvider = new FakePullUidProvider();
+ pullerManager->RegisterPullUidProvider(configKey, uidProvider);
+
+ vector<shared_ptr<LogEvent>> data;
+ EXPECT_FALSE(pullerManager->Pull(pullTagId1, badConfigKey, &data, true));
+}
+
+TEST(StatsPullerManagerTest, TestPullConfigKeyGood) {
+ sp<StatsPullerManager> pullerManager = createPullerManagerAndRegister();
+ sp<FakePullUidProvider> uidProvider = new FakePullUidProvider();
+ pullerManager->RegisterPullUidProvider(configKey, uidProvider);
+
+ vector<shared_ptr<LogEvent>> data;
+ EXPECT_TRUE(pullerManager->Pull(pullTagId1, configKey, &data, true));
+ EXPECT_EQ(data[0]->GetTagId(), pullTagId1);
+ ASSERT_EQ(data[0]->getValues().size(), 1);
+ EXPECT_EQ(data[0]->getValues()[0].mValue.int_value, uid2);
+}
+
+TEST(StatsPullerManagerTest, TestPullConfigKeyNoPullerWithUid) {
+ sp<StatsPullerManager> pullerManager = createPullerManagerAndRegister();
+ sp<FakePullUidProvider> uidProvider = new FakePullUidProvider();
+ pullerManager->RegisterPullUidProvider(configKey, uidProvider);
+
+ vector<shared_ptr<LogEvent>> data;
+ EXPECT_FALSE(pullerManager->Pull(pullTagId2, configKey, &data, true));
+}
+
+} // namespace statsd
+} // namespace os
+} // namespace android \ No newline at end of file
diff --git a/cmds/statsd/tests/metrics/GaugeMetricProducer_test.cpp b/cmds/statsd/tests/metrics/GaugeMetricProducer_test.cpp
index d372ffd7e689..2fe05a4430c3 100644
--- a/cmds/statsd/tests/metrics/GaugeMetricProducer_test.cpp
+++ b/cmds/statsd/tests/metrics/GaugeMetricProducer_test.cpp
@@ -105,6 +105,7 @@ TEST(GaugeMetricProducerTest, TestFirstBucket) {
logEventMatcherIndex, eventMatcherWizard,
-1, -1, tagId, 5, 600 * NS_PER_SEC + NS_PER_SEC / 2,
pullerManager);
+ gaugeProducer.prepareFirstBucket();
EXPECT_EQ(600500000000, gaugeProducer.mCurrentBucketStartTimeNs);
EXPECT_EQ(10, gaugeProducer.mCurrentBucketNum);
@@ -132,10 +133,11 @@ TEST(GaugeMetricProducerTest, TestPulledEventsNoCondition) {
atomMatcherId, logEventMatcherIndex, atomMatcher, uidMap)});
sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
- EXPECT_CALL(*pullerManager, RegisterReceiver(tagId, _, _, _)).WillOnce(Return());
- EXPECT_CALL(*pullerManager, UnRegisterReceiver(tagId, _)).WillOnce(Return());
- EXPECT_CALL(*pullerManager, Pull(tagId, _))
- .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
+ EXPECT_CALL(*pullerManager, RegisterReceiver(tagId, kConfigKey, _, _, _)).WillOnce(Return());
+ EXPECT_CALL(*pullerManager, UnRegisterReceiver(tagId, kConfigKey, _)).WillOnce(Return());
+ EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, _, _))
+ .WillOnce(Invoke([](int tagId, const ConfigKey&,
+ vector<std::shared_ptr<LogEvent>>* data, bool) {
data->clear();
data->push_back(makeLogEvent(tagId, bucketStartTimeNs + 10, 3, "some value", 11));
return true;
@@ -144,6 +146,7 @@ TEST(GaugeMetricProducerTest, TestPulledEventsNoCondition) {
GaugeMetricProducer gaugeProducer(kConfigKey, metric, -1 /*-1 meaning no condition*/, wizard,
logEventMatcherIndex, eventMatcherWizard, tagId, -1, tagId,
bucketStartTimeNs, bucketStartTimeNs, pullerManager);
+ gaugeProducer.prepareFirstBucket();
vector<shared_ptr<LogEvent>> allData;
allData.clear();
@@ -222,6 +225,7 @@ TEST(GaugeMetricProducerTest, TestPushedEventsWithUpgrade) {
logEventMatcherIndex, eventMatcherWizard,
-1 /* -1 means no pulling */, -1, tagId, bucketStartTimeNs,
bucketStartTimeNs, pullerManager);
+ gaugeProducer.prepareFirstBucket();
sp<AnomalyTracker> anomalyTracker = gaugeProducer.addAnomalyTracker(alert, alarmMonitor);
EXPECT_TRUE(anomalyTracker != nullptr);
@@ -287,19 +291,21 @@ TEST(GaugeMetricProducerTest, TestPulledWithUpgrade) {
atomMatcherId, logEventMatcherIndex, atomMatcher, uidMap)});
sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
- EXPECT_CALL(*pullerManager, RegisterReceiver(tagId, _, _, _)).WillOnce(Return());
- EXPECT_CALL(*pullerManager, UnRegisterReceiver(tagId, _)).WillOnce(Return());
- EXPECT_CALL(*pullerManager, Pull(tagId, _))
+ EXPECT_CALL(*pullerManager, RegisterReceiver(tagId, kConfigKey, _, _, _)).WillOnce(Return());
+ EXPECT_CALL(*pullerManager, UnRegisterReceiver(tagId, kConfigKey, _)).WillOnce(Return());
+ EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, _, _))
.WillOnce(Return(false))
- .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
- data->clear();
- data->push_back(CreateRepeatedValueLogEvent(tagId, eventUpgradeTimeNs, 2));
- return true;
- }));
+ .WillOnce(Invoke(
+ [](int tagId, const ConfigKey&, vector<std::shared_ptr<LogEvent>>* data, bool) {
+ data->clear();
+ data->push_back(CreateRepeatedValueLogEvent(tagId, eventUpgradeTimeNs, 2));
+ return true;
+ }));
GaugeMetricProducer gaugeProducer(kConfigKey, metric, -1 /*-1 meaning no condition*/, wizard,
logEventMatcherIndex, eventMatcherWizard, tagId, -1, tagId,
bucketStartTimeNs, bucketStartTimeNs, pullerManager);
+ gaugeProducer.prepareFirstBucket();
vector<shared_ptr<LogEvent>> allData;
allData.push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs + 1, 1));
@@ -351,13 +357,14 @@ TEST(GaugeMetricProducerTest, TestPulledWithAppUpgradeDisabled) {
atomMatcherId, logEventMatcherIndex, atomMatcher, uidMap)});
sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
- EXPECT_CALL(*pullerManager, RegisterReceiver(tagId, _, _, _)).WillOnce(Return());
- EXPECT_CALL(*pullerManager, UnRegisterReceiver(tagId, _)).WillOnce(Return());
- EXPECT_CALL(*pullerManager, Pull(tagId, _)).WillOnce(Return(false));
+ EXPECT_CALL(*pullerManager, RegisterReceiver(tagId, kConfigKey, _, _, _)).WillOnce(Return());
+ EXPECT_CALL(*pullerManager, UnRegisterReceiver(tagId, kConfigKey, _)).WillOnce(Return());
+ EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, _, _)).WillOnce(Return(false));
GaugeMetricProducer gaugeProducer(kConfigKey, metric, -1 /*-1 meaning no condition*/, wizard,
logEventMatcherIndex, eventMatcherWizard, tagId, -1, tagId,
bucketStartTimeNs, bucketStartTimeNs, pullerManager);
+ gaugeProducer.prepareFirstBucket();
vector<shared_ptr<LogEvent>> allData;
allData.push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs + 1, 1));
@@ -399,10 +406,11 @@ TEST(GaugeMetricProducerTest, TestPulledEventsWithCondition) {
atomMatcherId, logEventMatcherIndex, atomMatcher, uidMap)});
sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
- EXPECT_CALL(*pullerManager, RegisterReceiver(tagId, _, _, _)).WillOnce(Return());
- EXPECT_CALL(*pullerManager, UnRegisterReceiver(tagId, _)).WillOnce(Return());
- EXPECT_CALL(*pullerManager, Pull(tagId, _))
- .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
+ EXPECT_CALL(*pullerManager, RegisterReceiver(tagId, kConfigKey, _, _, _)).WillOnce(Return());
+ EXPECT_CALL(*pullerManager, UnRegisterReceiver(tagId, kConfigKey, _)).WillOnce(Return());
+ EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, _, _))
+ .WillOnce(Invoke([](int tagId, const ConfigKey&,
+ vector<std::shared_ptr<LogEvent>>* data, bool) {
data->clear();
data->push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs + 10, 100));
return true;
@@ -411,6 +419,7 @@ TEST(GaugeMetricProducerTest, TestPulledEventsWithCondition) {
GaugeMetricProducer gaugeProducer(kConfigKey, metric, 1, wizard, logEventMatcherIndex,
eventMatcherWizard, tagId, -1, tagId, bucketStartTimeNs,
bucketStartTimeNs, pullerManager);
+ gaugeProducer.prepareFirstBucket();
gaugeProducer.onConditionChanged(true, bucketStartTimeNs + 8);
EXPECT_EQ(1UL, gaugeProducer.mCurrentSlicedBucket->size());
@@ -481,10 +490,11 @@ TEST(GaugeMetricProducerTest, TestPulledEventsWithSlicedCondition) {
}));
sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
- EXPECT_CALL(*pullerManager, RegisterReceiver(tagId, _, _, _)).WillOnce(Return());
- EXPECT_CALL(*pullerManager, UnRegisterReceiver(tagId, _)).WillOnce(Return());
- EXPECT_CALL(*pullerManager, Pull(tagId, _))
- .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
+ EXPECT_CALL(*pullerManager, RegisterReceiver(tagId, kConfigKey, _, _, _)).WillOnce(Return());
+ EXPECT_CALL(*pullerManager, UnRegisterReceiver(tagId, kConfigKey, _)).WillOnce(Return());
+ EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, _, _))
+ .WillOnce(Invoke([](int tagId, const ConfigKey&,
+ vector<std::shared_ptr<LogEvent>>* data, bool) {
data->clear();
data->push_back(CreateTwoValueLogEvent(tagId, bucketStartTimeNs + 10, 1000, 100));
return true;
@@ -493,6 +503,7 @@ TEST(GaugeMetricProducerTest, TestPulledEventsWithSlicedCondition) {
GaugeMetricProducer gaugeProducer(kConfigKey, metric, 1, wizard, logEventMatcherIndex,
eventMatcherWizard, tagId, -1, tagId, bucketStartTimeNs,
bucketStartTimeNs, pullerManager);
+ gaugeProducer.prepareFirstBucket();
gaugeProducer.onSlicedConditionMayChange(true, bucketStartTimeNs + 8);
@@ -517,9 +528,9 @@ TEST(GaugeMetricProducerTest, TestPulledEventsAnomalyDetection) {
sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
- EXPECT_CALL(*pullerManager, RegisterReceiver(tagId, _, _, _)).WillOnce(Return());
- EXPECT_CALL(*pullerManager, UnRegisterReceiver(tagId, _)).WillOnce(Return());
- EXPECT_CALL(*pullerManager, Pull(tagId, _)).WillOnce(Return(false));
+ EXPECT_CALL(*pullerManager, RegisterReceiver(tagId, kConfigKey, _, _, _)).WillOnce(Return());
+ EXPECT_CALL(*pullerManager, UnRegisterReceiver(tagId, kConfigKey, _)).WillOnce(Return());
+ EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, _, _)).WillOnce(Return(false));
GaugeMetric metric;
metric.set_id(metricId);
@@ -539,6 +550,7 @@ TEST(GaugeMetricProducerTest, TestPulledEventsAnomalyDetection) {
GaugeMetricProducer gaugeProducer(kConfigKey, metric, -1 /*-1 meaning no condition*/, wizard,
logEventMatcherIndex, eventMatcherWizard, tagId, -1, tagId,
bucketStartTimeNs, bucketStartTimeNs, pullerManager);
+ gaugeProducer.prepareFirstBucket();
Alert alert;
alert.set_id(101);
@@ -616,13 +628,15 @@ TEST(GaugeMetricProducerTest, TestPullOnTrigger) {
atomMatcherId, logEventMatcherIndex, atomMatcher, uidMap)});
sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
- EXPECT_CALL(*pullerManager, Pull(tagId, _))
- .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
+ EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, _, _))
+ .WillOnce(Invoke([](int tagId, const ConfigKey&,
+ vector<std::shared_ptr<LogEvent>>* data, bool) {
data->clear();
data->push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs + 10, 4));
return true;
}))
- .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
+ .WillOnce(Invoke([](int tagId, const ConfigKey&,
+ vector<std::shared_ptr<LogEvent>>* data, bool) {
data->clear();
data->push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs + 20, 5));
return true;
@@ -633,6 +647,7 @@ TEST(GaugeMetricProducerTest, TestPullOnTrigger) {
GaugeMetricProducer gaugeProducer(kConfigKey, metric, -1 /*-1 meaning no condition*/, wizard,
logEventMatcherIndex, eventMatcherWizard, tagId, triggerId,
tagId, bucketStartTimeNs, bucketStartTimeNs, pullerManager);
+ gaugeProducer.prepareFirstBucket();
EXPECT_EQ(0UL, gaugeProducer.mCurrentSlicedBucket->size());
@@ -682,18 +697,21 @@ TEST(GaugeMetricProducerTest, TestRemoveDimensionInOutput) {
atomMatcherId, logEventMatcherIndex, atomMatcher, uidMap)});
sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
- EXPECT_CALL(*pullerManager, Pull(tagId, _))
- .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
- data->clear();
- data->push_back(CreateTwoValueLogEvent(tagId, bucketStartTimeNs + 3, 3, 4));
- return true;
- }))
- .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
+ EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, _, _))
+ .WillOnce(Invoke(
+ [](int tagId, const ConfigKey&, vector<std::shared_ptr<LogEvent>>* data, bool) {
+ data->clear();
+ data->push_back(CreateTwoValueLogEvent(tagId, bucketStartTimeNs + 3, 3, 4));
+ return true;
+ }))
+ .WillOnce(Invoke([](int tagId, const ConfigKey&,
+ vector<std::shared_ptr<LogEvent>>* data, bool) {
data->clear();
data->push_back(CreateTwoValueLogEvent(tagId, bucketStartTimeNs + 10, 4, 5));
return true;
}))
- .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
+ .WillOnce(Invoke([](int tagId, const ConfigKey&,
+ vector<std::shared_ptr<LogEvent>>* data, bool) {
data->clear();
data->push_back(CreateTwoValueLogEvent(tagId, bucketStartTimeNs + 20, 4, 6));
return true;
@@ -704,6 +722,7 @@ TEST(GaugeMetricProducerTest, TestRemoveDimensionInOutput) {
GaugeMetricProducer gaugeProducer(kConfigKey, metric, -1 /*-1 meaning no condition*/, wizard,
logEventMatcherIndex, eventMatcherWizard, tagId, triggerId,
tagId, bucketStartTimeNs, bucketStartTimeNs, pullerManager);
+ gaugeProducer.prepareFirstBucket();
LogEvent triggerEvent(/*uid=*/0, /*pid=*/0);
CreateNoValuesLogEvent(&triggerEvent, triggerId, bucketStartTimeNs + 3);
@@ -752,18 +771,20 @@ TEST(GaugeMetricProducerTest_BucketDrop, TestBucketDropWhenBucketTooSmall) {
atomMatcherId, logEventMatcherIndex, atomMatcher, uidMap)});
sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
- EXPECT_CALL(*pullerManager, Pull(tagId, _))
+ EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, _, _))
// Bucket start.
- .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
- data->clear();
- data->push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs, 10));
- return true;
- }));
+ .WillOnce(Invoke(
+ [](int tagId, const ConfigKey&, vector<std::shared_ptr<LogEvent>>* data, bool) {
+ data->clear();
+ data->push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs, 10));
+ return true;
+ }));
int triggerId = 5;
GaugeMetricProducer gaugeProducer(kConfigKey, metric, -1 /*-1 meaning no condition*/, wizard,
logEventMatcherIndex, eventMatcherWizard, tagId, triggerId,
tagId, bucketStartTimeNs, bucketStartTimeNs, pullerManager);
+ gaugeProducer.prepareFirstBucket();
LogEvent triggerEvent(/*uid=*/0, /*pid=*/0);
CreateNoValuesLogEvent(&triggerEvent, triggerId, bucketStartTimeNs + 3);
diff --git a/cmds/statsd/tests/metrics/ValueMetricProducer_test.cpp b/cmds/statsd/tests/metrics/ValueMetricProducer_test.cpp
index c1d4693ce01c..b623a0978f18 100644
--- a/cmds/statsd/tests/metrics/ValueMetricProducer_test.cpp
+++ b/cmds/statsd/tests/metrics/ValueMetricProducer_test.cpp
@@ -90,12 +90,15 @@ public:
new EventMatcherWizard({new SimpleLogMatchingTracker(
atomMatcherId, logEventMatcherIndex, atomMatcher, uidMap)});
sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
- EXPECT_CALL(*pullerManager, RegisterReceiver(tagId, _, _, _)).WillOnce(Return());
- EXPECT_CALL(*pullerManager, UnRegisterReceiver(tagId, _)).WillRepeatedly(Return());
+ EXPECT_CALL(*pullerManager, RegisterReceiver(tagId, kConfigKey, _, _, _))
+ .WillOnce(Return());
+ EXPECT_CALL(*pullerManager, UnRegisterReceiver(tagId, kConfigKey, _))
+ .WillRepeatedly(Return());
sp<ValueMetricProducer> valueProducer = new ValueMetricProducer(
kConfigKey, metric, -1 /*-1 meaning no condition*/, wizard, logEventMatcherIndex,
eventMatcherWizard, tagId, bucketStartTimeNs, bucketStartTimeNs, pullerManager);
+ valueProducer->prepareFirstBucket();
return valueProducer;
}
@@ -108,12 +111,15 @@ public:
new EventMatcherWizard({new SimpleLogMatchingTracker(
atomMatcherId, logEventMatcherIndex, atomMatcher, uidMap)});
sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
- EXPECT_CALL(*pullerManager, RegisterReceiver(tagId, _, _, _)).WillOnce(Return());
- EXPECT_CALL(*pullerManager, UnRegisterReceiver(tagId, _)).WillRepeatedly(Return());
+ EXPECT_CALL(*pullerManager, RegisterReceiver(tagId, kConfigKey, _, _, _))
+ .WillOnce(Return());
+ EXPECT_CALL(*pullerManager, UnRegisterReceiver(tagId, kConfigKey, _))
+ .WillRepeatedly(Return());
sp<ValueMetricProducer> valueProducer = new ValueMetricProducer(
kConfigKey, metric, 1, wizard, logEventMatcherIndex, eventMatcherWizard, tagId,
bucketStartTimeNs, bucketStartTimeNs, pullerManager);
+ valueProducer->prepareFirstBucket();
valueProducer->mCondition = ConditionState::kFalse;
return valueProducer;
}
@@ -127,12 +133,15 @@ public:
new EventMatcherWizard({new SimpleLogMatchingTracker(
atomMatcherId, logEventMatcherIndex, atomMatcher, uidMap)});
sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
- EXPECT_CALL(*pullerManager, RegisterReceiver(tagId, _, _, _)).WillOnce(Return());
- EXPECT_CALL(*pullerManager, UnRegisterReceiver(tagId, _)).WillRepeatedly(Return());
+ EXPECT_CALL(*pullerManager, RegisterReceiver(tagId, kConfigKey, _, _, _))
+ .WillOnce(Return());
+ EXPECT_CALL(*pullerManager, UnRegisterReceiver(tagId, kConfigKey, _))
+ .WillRepeatedly(Return());
sp<ValueMetricProducer> valueProducer = new ValueMetricProducer(
kConfigKey, metric, 1, wizard, logEventMatcherIndex, eventMatcherWizard, tagId,
bucketStartTimeNs, bucketStartTimeNs, pullerManager);
+ valueProducer->prepareFirstBucket();
return valueProducer;
}
@@ -147,12 +156,15 @@ public:
new EventMatcherWizard({new SimpleLogMatchingTracker(
atomMatcherId, logEventMatcherIndex, atomMatcher, uidMap)});
sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
- EXPECT_CALL(*pullerManager, RegisterReceiver(tagId, _, _, _)).WillOnce(Return());
- EXPECT_CALL(*pullerManager, UnRegisterReceiver(tagId, _)).WillRepeatedly(Return());
+ EXPECT_CALL(*pullerManager, RegisterReceiver(tagId, kConfigKey, _, _, _))
+ .WillOnce(Return());
+ EXPECT_CALL(*pullerManager, UnRegisterReceiver(tagId, kConfigKey, _))
+ .WillRepeatedly(Return());
sp<ValueMetricProducer> valueProducer = new ValueMetricProducer(
kConfigKey, metric, -1 /* no condition */, wizard, logEventMatcherIndex,
eventMatcherWizard, tagId, bucketStartTimeNs, bucketStartTimeNs, pullerManager, {},
{}, slicedStateAtoms, stateGroupMap);
+ valueProducer->prepareFirstBucket();
return valueProducer;
}
@@ -200,6 +212,7 @@ TEST(ValueMetricProducerTest, TestCalcPreviousBucketEndTime) {
ValueMetricProducer valueProducer(kConfigKey, metric, -1 /*-1 meaning no condition*/, wizard,
logEventMatcherIndex, eventMatcherWizard, -1, startTimeBase,
22, pullerManager);
+ valueProducer.prepareFirstBucket();
EXPECT_EQ(startTimeBase, valueProducer.calcPreviousBucketEndTime(60 * NS_PER_SEC + 10));
EXPECT_EQ(startTimeBase, valueProducer.calcPreviousBucketEndTime(60 * NS_PER_SEC + 10));
@@ -229,6 +242,7 @@ TEST(ValueMetricProducerTest, TestFirstBucket) {
ValueMetricProducer valueProducer(kConfigKey, metric, -1 /*-1 meaning no condition*/, wizard,
logEventMatcherIndex, eventMatcherWizard, -1, 5,
600 * NS_PER_SEC + NS_PER_SEC / 2, pullerManager);
+ valueProducer.prepareFirstBucket();
EXPECT_EQ(600500000000, valueProducer.mCurrentBucketStartTimeNs);
EXPECT_EQ(10, valueProducer.mCurrentBucketNum);
@@ -241,12 +255,13 @@ TEST(ValueMetricProducerTest, TestFirstBucket) {
TEST(ValueMetricProducerTest, TestPulledEventsNoCondition) {
ValueMetric metric = ValueMetricProducerTestHelper::createMetric();
sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
- EXPECT_CALL(*pullerManager, Pull(tagId, _))
- .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
- data->clear();
- data->push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs, 3));
- return true;
- }));
+ EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, _, _))
+ .WillOnce(Invoke(
+ [](int tagId, const ConfigKey&, vector<std::shared_ptr<LogEvent>>* data, bool) {
+ data->clear();
+ data->push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs, 3));
+ return true;
+ }));
sp<ValueMetricProducer> valueProducer =
ValueMetricProducerTestHelper::createValueProducerNoConditions(pullerManager, metric);
@@ -313,15 +328,17 @@ TEST(ValueMetricProducerTest, TestPulledEventsNoCondition) {
TEST(ValueMetricProducerTest, TestPartialBucketCreated) {
ValueMetric metric = ValueMetricProducerTestHelper::createMetric();
sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
- EXPECT_CALL(*pullerManager, Pull(tagId, _))
+ EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, _, _))
// Initialize bucket.
- .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
+ .WillOnce(Invoke([](int tagId, const ConfigKey&,
+ vector<std::shared_ptr<LogEvent>>* data, bool) {
data->clear();
data->push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs + 1, 1));
return true;
}))
// Partial bucket.
- .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
+ .WillOnce(Invoke([](int tagId, const ConfigKey&,
+ vector<std::shared_ptr<LogEvent>>* data, bool) {
data->clear();
data->push_back(CreateRepeatedValueLogEvent(tagId, bucket2StartTimeNs + 10, 5));
return true;
@@ -369,18 +386,20 @@ TEST(ValueMetricProducerTest, TestPulledEventsWithFiltering) {
atomMatcherId, logEventMatcherIndex, atomMatcher, uidMap)});
sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
- EXPECT_CALL(*pullerManager, RegisterReceiver(tagId, _, _, _)).WillOnce(Return());
- EXPECT_CALL(*pullerManager, UnRegisterReceiver(tagId, _)).WillOnce(Return());
- EXPECT_CALL(*pullerManager, Pull(tagId, _))
- .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
- data->clear();
- data->push_back(CreateTwoValueLogEvent(tagId, bucketStartTimeNs, 3, 3));
- return true;
- }));
+ EXPECT_CALL(*pullerManager, RegisterReceiver(tagId, kConfigKey, _, _, _)).WillOnce(Return());
+ EXPECT_CALL(*pullerManager, UnRegisterReceiver(tagId, kConfigKey, _)).WillOnce(Return());
+ EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, _, _))
+ .WillOnce(Invoke(
+ [](int tagId, const ConfigKey&, vector<std::shared_ptr<LogEvent>>* data, bool) {
+ data->clear();
+ data->push_back(CreateTwoValueLogEvent(tagId, bucketStartTimeNs, 3, 3));
+ return true;
+ }));
sp<ValueMetricProducer> valueProducer = new ValueMetricProducer(
kConfigKey, metric, -1 /*-1 meaning no condition*/, wizard, logEventMatcherIndex,
eventMatcherWizard, tagId, bucketStartTimeNs, bucketStartTimeNs, pullerManager);
+ valueProducer->prepareFirstBucket();
vector<shared_ptr<LogEvent>> allData;
allData.clear();
@@ -440,7 +459,7 @@ TEST(ValueMetricProducerTest, TestPulledEventsTakeAbsoluteValueOnReset) {
metric.set_use_absolute_value_on_reset(true);
sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
- EXPECT_CALL(*pullerManager, Pull(tagId, _)).WillOnce(Return(true));
+ EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, _, _)).WillOnce(Return(true));
sp<ValueMetricProducer> valueProducer =
ValueMetricProducerTestHelper::createValueProducerNoConditions(pullerManager, metric);
@@ -499,7 +518,7 @@ TEST(ValueMetricProducerTest, TestPulledEventsTakeAbsoluteValueOnReset) {
TEST(ValueMetricProducerTest, TestPulledEventsTakeZeroOnReset) {
ValueMetric metric = ValueMetricProducerTestHelper::createMetric();
sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
- EXPECT_CALL(*pullerManager, Pull(tagId, _)).WillOnce(Return(false));
+ EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, _, _)).WillOnce(Return(false));
sp<ValueMetricProducer> valueProducer =
ValueMetricProducerTestHelper::createValueProducerNoConditions(pullerManager, metric);
@@ -554,18 +573,21 @@ TEST(ValueMetricProducerTest, TestEventsWithNonSlicedCondition) {
sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
- EXPECT_CALL(*pullerManager, Pull(tagId, _))
- .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
+ EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, _, _))
+ .WillOnce(Invoke([](int tagId, const ConfigKey&,
+ vector<std::shared_ptr<LogEvent>>* data, bool) {
data->clear();
data->push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs + 8, 100));
return true;
}))
- .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
+ .WillOnce(Invoke([](int tagId, const ConfigKey&,
+ vector<std::shared_ptr<LogEvent>>* data, bool) {
data->clear();
data->push_back(CreateRepeatedValueLogEvent(tagId, bucket2StartTimeNs + 1, 130));
return true;
}))
- .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
+ .WillOnce(Invoke([](int tagId, const ConfigKey&,
+ vector<std::shared_ptr<LogEvent>>* data, bool) {
data->clear();
data->push_back(CreateRepeatedValueLogEvent(tagId, bucket3StartTimeNs + 1, 180));
return true;
@@ -631,6 +653,7 @@ TEST(ValueMetricProducerTest, TestPushedEventsWithUpgrade) {
ValueMetricProducer valueProducer(kConfigKey, metric, -1, wizard, logEventMatcherIndex,
eventMatcherWizard, -1, bucketStartTimeNs, bucketStartTimeNs,
pullerManager);
+ valueProducer.prepareFirstBucket();
LogEvent event1(/*uid=*/0, /*pid=*/0);
CreateTwoValueLogEvent(&event1, tagId, bucketStartTimeNs + 10, 1, 10);
@@ -666,11 +689,12 @@ TEST(ValueMetricProducerTest, TestPulledValueWithUpgrade) {
atomMatcherId, logEventMatcherIndex, atomMatcher, uidMap)});
sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
- EXPECT_CALL(*pullerManager, RegisterReceiver(tagId, _, _, _)).WillOnce(Return());
- EXPECT_CALL(*pullerManager, UnRegisterReceiver(tagId, _)).WillOnce(Return());
- EXPECT_CALL(*pullerManager, Pull(tagId, _))
+ EXPECT_CALL(*pullerManager, RegisterReceiver(tagId, kConfigKey, _, _, _)).WillOnce(Return());
+ EXPECT_CALL(*pullerManager, UnRegisterReceiver(tagId, kConfigKey, _)).WillOnce(Return());
+ EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, _, _))
.WillOnce(Return(true))
- .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
+ .WillOnce(Invoke([](int tagId, const ConfigKey&,
+ vector<std::shared_ptr<LogEvent>>* data, bool) {
data->clear();
data->push_back(CreateRepeatedValueLogEvent(tagId, bucket2StartTimeNs + 149, 120));
return true;
@@ -678,6 +702,7 @@ TEST(ValueMetricProducerTest, TestPulledValueWithUpgrade) {
ValueMetricProducer valueProducer(kConfigKey, metric, -1, wizard, logEventMatcherIndex,
eventMatcherWizard, tagId, bucketStartTimeNs,
bucketStartTimeNs, pullerManager);
+ valueProducer.prepareFirstBucket();
vector<shared_ptr<LogEvent>> allData;
allData.clear();
@@ -714,12 +739,13 @@ TEST(ValueMetricProducerTest, TestPulledWithAppUpgradeDisabled) {
atomMatcherId, logEventMatcherIndex, atomMatcher, uidMap)});
sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
- EXPECT_CALL(*pullerManager, RegisterReceiver(tagId, _, _, _)).WillOnce(Return());
- EXPECT_CALL(*pullerManager, UnRegisterReceiver(tagId, _)).WillOnce(Return());
- EXPECT_CALL(*pullerManager, Pull(tagId, _)).WillOnce(Return(true));
+ EXPECT_CALL(*pullerManager, RegisterReceiver(tagId, kConfigKey, _, _, _)).WillOnce(Return());
+ EXPECT_CALL(*pullerManager, UnRegisterReceiver(tagId, kConfigKey, _)).WillOnce(Return());
+ EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, _, _)).WillOnce(Return(true));
ValueMetricProducer valueProducer(kConfigKey, metric, -1, wizard, logEventMatcherIndex,
eventMatcherWizard, tagId, bucketStartTimeNs,
bucketStartTimeNs, pullerManager);
+ valueProducer.prepareFirstBucket();
vector<shared_ptr<LogEvent>> allData;
allData.clear();
@@ -737,13 +763,15 @@ TEST(ValueMetricProducerTest, TestPulledValueWithUpgradeWhileConditionFalse) {
ValueMetric metric = ValueMetricProducerTestHelper::createMetricWithCondition();
sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
- EXPECT_CALL(*pullerManager, Pull(tagId, _))
- .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
+ EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, _, _))
+ .WillOnce(Invoke([](int tagId, const ConfigKey&,
+ vector<std::shared_ptr<LogEvent>>* data, bool) {
data->clear();
data->push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs + 1, 100));
return true;
}))
- .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
+ .WillOnce(Invoke([](int tagId, const ConfigKey&,
+ vector<std::shared_ptr<LogEvent>>* data, bool) {
data->clear();
data->push_back(CreateRepeatedValueLogEvent(tagId, bucket2StartTimeNs - 100, 120));
return true;
@@ -781,6 +809,7 @@ TEST(ValueMetricProducerTest, TestPushedEventsWithoutCondition) {
ValueMetricProducer valueProducer(kConfigKey, metric, -1, wizard, logEventMatcherIndex,
eventMatcherWizard, -1, bucketStartTimeNs, bucketStartTimeNs,
pullerManager);
+ valueProducer.prepareFirstBucket();
LogEvent event1(/*uid=*/0, /*pid=*/0);
CreateTwoValueLogEvent(&event1, tagId, bucketStartTimeNs + 10, 1, 10);
@@ -823,6 +852,7 @@ TEST(ValueMetricProducerTest, TestPushedEventsWithCondition) {
ValueMetricProducer valueProducer(kConfigKey, metric, 1, wizard, logEventMatcherIndex,
eventMatcherWizard, -1, bucketStartTimeNs, bucketStartTimeNs,
pullerManager);
+ valueProducer.prepareFirstBucket();
valueProducer.mCondition = ConditionState::kFalse;
LogEvent event1(/*uid=*/0, /*pid=*/0);
@@ -891,6 +921,7 @@ TEST(ValueMetricProducerTest, TestAnomalyDetection) {
ValueMetricProducer valueProducer(kConfigKey, metric, -1 /*-1 meaning no condition*/, wizard,
logEventMatcherIndex, eventMatcherWizard, -1 /*not pulled*/,
bucketStartTimeNs, bucketStartTimeNs, pullerManager);
+ valueProducer.prepareFirstBucket();
sp<AnomalyTracker> anomalyTracker = valueProducer.addAnomalyTracker(alert, alarmMonitor);
@@ -947,7 +978,7 @@ TEST(ValueMetricProducerTest, TestAnomalyDetection) {
TEST(ValueMetricProducerTest, TestBucketBoundaryNoCondition) {
ValueMetric metric = ValueMetricProducerTestHelper::createMetric();
sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
- EXPECT_CALL(*pullerManager, Pull(tagId, _)).WillOnce(Return(true));
+ EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, _, _)).WillOnce(Return(true));
sp<ValueMetricProducer> valueProducer =
ValueMetricProducerTestHelper::createValueProducerNoConditions(pullerManager, metric);
@@ -1008,15 +1039,17 @@ TEST(ValueMetricProducerTest, TestBucketBoundaryWithCondition) {
ValueMetric metric = ValueMetricProducerTestHelper::createMetricWithCondition();
sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
- EXPECT_CALL(*pullerManager, Pull(tagId, _))
+ EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, _, _))
// condition becomes true
- .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
+ .WillOnce(Invoke([](int tagId, const ConfigKey&,
+ vector<std::shared_ptr<LogEvent>>* data, bool) {
data->clear();
data->push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs + 8, 100));
return true;
}))
// condition becomes false
- .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
+ .WillOnce(Invoke([](int tagId, const ConfigKey&,
+ vector<std::shared_ptr<LogEvent>>* data, bool) {
data->clear();
data->push_back(CreateRepeatedValueLogEvent(tagId, bucket2StartTimeNs + 1, 120));
return true;
@@ -1065,21 +1098,24 @@ TEST(ValueMetricProducerTest, TestBucketBoundaryWithCondition2) {
ValueMetric metric = ValueMetricProducerTestHelper::createMetricWithCondition();
sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
- EXPECT_CALL(*pullerManager, Pull(tagId, _))
+ EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, _, _))
// condition becomes true
- .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
+ .WillOnce(Invoke([](int tagId, const ConfigKey&,
+ vector<std::shared_ptr<LogEvent>>* data, bool) {
data->clear();
data->push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs + 8, 100));
return true;
}))
// condition becomes false
- .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
+ .WillOnce(Invoke([](int tagId, const ConfigKey&,
+ vector<std::shared_ptr<LogEvent>>* data, bool) {
data->clear();
data->push_back(CreateRepeatedValueLogEvent(tagId, bucket2StartTimeNs + 1, 120));
return true;
}))
// condition becomes true again
- .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
+ .WillOnce(Invoke([](int tagId, const ConfigKey&,
+ vector<std::shared_ptr<LogEvent>>* data, bool) {
data->clear();
data->push_back(CreateRepeatedValueLogEvent(tagId, bucket2StartTimeNs + 25, 130));
return true;
@@ -1156,6 +1192,7 @@ TEST(ValueMetricProducerTest, TestPushedAggregateMin) {
ValueMetricProducer valueProducer(kConfigKey, metric, -1, wizard, logEventMatcherIndex,
eventMatcherWizard, -1, bucketStartTimeNs, bucketStartTimeNs,
pullerManager);
+ valueProducer.prepareFirstBucket();
LogEvent event1(/*uid=*/0, /*pid=*/0);
CreateTwoValueLogEvent(&event1, tagId, bucketStartTimeNs + 10, 1, 10);
@@ -1198,6 +1235,7 @@ TEST(ValueMetricProducerTest, TestPushedAggregateMax) {
ValueMetricProducer valueProducer(kConfigKey, metric, -1, wizard, logEventMatcherIndex,
eventMatcherWizard, -1, bucketStartTimeNs, bucketStartTimeNs,
pullerManager);
+ valueProducer.prepareFirstBucket();
LogEvent event1(/*uid=*/0, /*pid=*/0);
CreateTwoValueLogEvent(&event1, tagId, bucketStartTimeNs + 10, 1, 10);
@@ -1242,6 +1280,7 @@ TEST(ValueMetricProducerTest, TestPushedAggregateAvg) {
ValueMetricProducer valueProducer(kConfigKey, metric, -1, wizard, logEventMatcherIndex,
eventMatcherWizard, -1, bucketStartTimeNs, bucketStartTimeNs,
pullerManager);
+ valueProducer.prepareFirstBucket();
LogEvent event1(/*uid=*/0, /*pid=*/0);
CreateTwoValueLogEvent(&event1, tagId, bucketStartTimeNs + 10, 1, 10);
@@ -1289,6 +1328,7 @@ TEST(ValueMetricProducerTest, TestPushedAggregateSum) {
ValueMetricProducer valueProducer(kConfigKey, metric, -1, wizard, logEventMatcherIndex,
eventMatcherWizard, -1, bucketStartTimeNs, bucketStartTimeNs,
pullerManager);
+ valueProducer.prepareFirstBucket();
LogEvent event1(/*uid=*/0, /*pid=*/0);
CreateTwoValueLogEvent(&event1, tagId, bucketStartTimeNs + 10, 1, 10);
@@ -1331,6 +1371,7 @@ TEST(ValueMetricProducerTest, TestSkipZeroDiffOutput) {
ValueMetricProducer valueProducer(kConfigKey, metric, -1, wizard, logEventMatcherIndex,
eventMatcherWizard, -1, bucketStartTimeNs, bucketStartTimeNs,
pullerManager);
+ valueProducer.prepareFirstBucket();
LogEvent event1(/*uid=*/0, /*pid=*/0);
CreateTwoValueLogEvent(&event1, tagId, bucketStartTimeNs + 10, 1, 10);
@@ -1400,6 +1441,7 @@ TEST(ValueMetricProducerTest, TestSkipZeroDiffOutputMultiValue) {
ValueMetricProducer valueProducer(kConfigKey, metric, -1, wizard, logEventMatcherIndex,
eventMatcherWizard, -1, bucketStartTimeNs, bucketStartTimeNs,
pullerManager);
+ valueProducer.prepareFirstBucket();
LogEvent event1(/*uid=*/0, /*pid=*/0);
CreateThreeValueLogEvent(&event1, tagId, bucketStartTimeNs + 10, 1, 10, 20);
@@ -1496,12 +1538,13 @@ TEST(ValueMetricProducerTest, TestUseZeroDefaultBase) {
metric.set_use_zero_default_base(true);
sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
- EXPECT_CALL(*pullerManager, Pull(tagId, _))
- .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
- data->clear();
- data->push_back(CreateTwoValueLogEvent(tagId, bucketStartTimeNs, 1, 3));
- return true;
- }));
+ EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, _, _))
+ .WillOnce(Invoke(
+ [](int tagId, const ConfigKey&, vector<std::shared_ptr<LogEvent>>* data, bool) {
+ data->clear();
+ data->push_back(CreateTwoValueLogEvent(tagId, bucketStartTimeNs, 1, 3));
+ return true;
+ }));
sp<ValueMetricProducer> valueProducer =
ValueMetricProducerTestHelper::createValueProducerNoConditions(pullerManager, metric);
@@ -1571,12 +1614,13 @@ TEST(ValueMetricProducerTest, TestUseZeroDefaultBaseWithPullFailures) {
metric.set_use_zero_default_base(true);
sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
- EXPECT_CALL(*pullerManager, Pull(tagId, _))
- .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
- data->clear();
- data->push_back(CreateTwoValueLogEvent(tagId, bucketStartTimeNs, 1, 3));
- return true;
- }));
+ EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, _, _))
+ .WillOnce(Invoke(
+ [](int tagId, const ConfigKey&, vector<std::shared_ptr<LogEvent>>* data, bool) {
+ data->clear();
+ data->push_back(CreateTwoValueLogEvent(tagId, bucketStartTimeNs, 1, 3));
+ return true;
+ }));
sp<ValueMetricProducer> valueProducer =
ValueMetricProducerTestHelper::createValueProducerNoConditions(pullerManager, metric);
@@ -1675,12 +1719,13 @@ TEST(ValueMetricProducerTest, TestTrimUnusedDimensionKey) {
metric.mutable_dimensions_in_what()->add_child()->set_field(1);
sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
- EXPECT_CALL(*pullerManager, Pull(tagId, _))
- .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
- data->clear();
- data->push_back(CreateTwoValueLogEvent(tagId, bucketStartTimeNs, 1, 3));
- return true;
- }));
+ EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, _, _))
+ .WillOnce(Invoke(
+ [](int tagId, const ConfigKey&, vector<std::shared_ptr<LogEvent>>* data, bool) {
+ data->clear();
+ data->push_back(CreateTwoValueLogEvent(tagId, bucketStartTimeNs, 1, 3));
+ return true;
+ }));
sp<ValueMetricProducer> valueProducer =
ValueMetricProducerTestHelper::createValueProducerNoConditions(pullerManager, metric);
@@ -1772,8 +1817,9 @@ TEST(ValueMetricProducerTest, TestResetBaseOnPullFailAfterConditionChange_EndOfB
sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
// Used by onConditionChanged.
- EXPECT_CALL(*pullerManager, Pull(tagId, _))
- .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
+ EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, _, _))
+ .WillOnce(Invoke([](int tagId, const ConfigKey&,
+ vector<std::shared_ptr<LogEvent>>* data, bool) {
data->clear();
data->push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs + 8, 100));
return true;
@@ -1804,8 +1850,9 @@ TEST(ValueMetricProducerTest, TestResetBaseOnPullFailAfterConditionChange) {
ValueMetric metric = ValueMetricProducerTestHelper::createMetricWithCondition();
sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
- EXPECT_CALL(*pullerManager, Pull(tagId, _))
- .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
+ EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, _, _))
+ .WillOnce(Invoke([](int tagId, const ConfigKey&,
+ vector<std::shared_ptr<LogEvent>>* data, bool) {
data->clear();
data->push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs + 8, 100));
return true;
@@ -1840,13 +1887,15 @@ TEST(ValueMetricProducerTest, TestResetBaseOnPullFailBeforeConditionChange) {
ValueMetric metric = ValueMetricProducerTestHelper::createMetricWithCondition();
sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
- EXPECT_CALL(*pullerManager, Pull(tagId, _))
- .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
- data->clear();
- data->push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs, 50));
- return false;
- }))
- .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
+ EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, _, _))
+ .WillOnce(Invoke(
+ [](int tagId, const ConfigKey&, vector<std::shared_ptr<LogEvent>>* data, bool) {
+ data->clear();
+ data->push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs, 50));
+ return false;
+ }))
+ .WillOnce(Invoke([](int tagId, const ConfigKey&,
+ vector<std::shared_ptr<LogEvent>>* data, bool) {
data->clear();
data->push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs + 8, 100));
return true;
@@ -1878,8 +1927,9 @@ TEST(ValueMetricProducerTest, TestResetBaseOnPullDelayExceeded) {
metric.set_max_pull_delay_sec(0);
sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
- EXPECT_CALL(*pullerManager, Pull(tagId, _))
- .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
+ EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, _, _))
+ .WillOnce(Invoke([](int tagId, const ConfigKey&,
+ vector<std::shared_ptr<LogEvent>>* data, bool) {
data->clear();
data->push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs + 1, 120));
return true;
@@ -1906,12 +1956,13 @@ TEST(ValueMetricProducerTest, TestResetBaseOnPullTooLate) {
atomMatcherId, logEventMatcherIndex, atomMatcher, uidMap)});
sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
- EXPECT_CALL(*pullerManager, RegisterReceiver(tagId, _, _, _)).WillOnce(Return());
- EXPECT_CALL(*pullerManager, UnRegisterReceiver(tagId, _)).WillRepeatedly(Return());
+ EXPECT_CALL(*pullerManager, RegisterReceiver(tagId, kConfigKey, _, _, _)).WillOnce(Return());
+ EXPECT_CALL(*pullerManager, UnRegisterReceiver(tagId, kConfigKey, _)).WillRepeatedly(Return());
ValueMetricProducer valueProducer(kConfigKey, metric, 1, wizard, logEventMatcherIndex,
eventMatcherWizard, tagId, bucket2StartTimeNs,
bucket2StartTimeNs, pullerManager);
+ valueProducer.prepareFirstBucket();
valueProducer.mCondition = ConditionState::kFalse;
// Event should be skipped since it is from previous bucket.
@@ -1924,8 +1975,9 @@ TEST(ValueMetricProducerTest, TestBaseSetOnConditionChange) {
ValueMetric metric = ValueMetricProducerTestHelper::createMetricWithCondition();
sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
- EXPECT_CALL(*pullerManager, Pull(tagId, _))
- .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
+ EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, _, _))
+ .WillOnce(Invoke([](int tagId, const ConfigKey&,
+ vector<std::shared_ptr<LogEvent>>* data, bool) {
data->clear();
data->push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs + 1, 100));
return true;
@@ -1956,11 +2008,12 @@ TEST(ValueMetricProducerTest_BucketDrop, TestInvalidBucketWhenOneConditionFailed
ValueMetric metric = ValueMetricProducerTestHelper::createMetricWithCondition();
sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
- EXPECT_CALL(*pullerManager, Pull(tagId, _))
+ EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, _, _))
// First onConditionChanged
.WillOnce(Return(false))
// Second onConditionChanged
- .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
+ .WillOnce(Invoke([](int tagId, const ConfigKey&,
+ vector<std::shared_ptr<LogEvent>>* data, bool) {
data->clear();
data->push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs + 8, 130));
return true;
@@ -2032,9 +2085,10 @@ TEST(ValueMetricProducerTest_BucketDrop, TestInvalidBucketWhenGuardRailHit) {
metric.set_condition(StringToId("SCREEN_ON"));
sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
- EXPECT_CALL(*pullerManager, Pull(tagId, _))
+ EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, _, _))
// First onConditionChanged
- .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
+ .WillOnce(Invoke([](int tagId, const ConfigKey&,
+ vector<std::shared_ptr<LogEvent>>* data, bool) {
for (int i = 0; i < 2000; i++) {
data->push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs + 1, i));
}
@@ -2088,15 +2142,17 @@ TEST(ValueMetricProducerTest_BucketDrop, TestInvalidBucketWhenInitialPullFailed)
ValueMetric metric = ValueMetricProducerTestHelper::createMetricWithCondition();
sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
- EXPECT_CALL(*pullerManager, Pull(tagId, _))
+ EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, _, _))
// First onConditionChanged
- .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
+ .WillOnce(Invoke([](int tagId, const ConfigKey&,
+ vector<std::shared_ptr<LogEvent>>* data, bool) {
data->clear();
data->push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs + 8, 120));
return true;
}))
// Second onConditionChanged
- .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
+ .WillOnce(Invoke([](int tagId, const ConfigKey&,
+ vector<std::shared_ptr<LogEvent>>* data, bool) {
data->clear();
data->push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs + 8, 130));
return true;
@@ -2164,15 +2220,17 @@ TEST(ValueMetricProducerTest_BucketDrop, TestInvalidBucketWhenLastPullFailed) {
ValueMetric metric = ValueMetricProducerTestHelper::createMetricWithCondition();
sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
- EXPECT_CALL(*pullerManager, Pull(tagId, _))
+ EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, _, _))
// First onConditionChanged
- .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
+ .WillOnce(Invoke([](int tagId, const ConfigKey&,
+ vector<std::shared_ptr<LogEvent>>* data, bool) {
data->clear();
data->push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs + 8, 120));
return true;
}))
// Second onConditionChanged
- .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
+ .WillOnce(Invoke([](int tagId, const ConfigKey&,
+ vector<std::shared_ptr<LogEvent>>* data, bool) {
data->clear();
data->push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs + 8, 130));
return true;
@@ -2234,13 +2292,14 @@ TEST(ValueMetricProducerTest_BucketDrop, TestInvalidBucketWhenLastPullFailed) {
TEST(ValueMetricProducerTest, TestEmptyDataResetsBase_onDataPulled) {
ValueMetric metric = ValueMetricProducerTestHelper::createMetric();
sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
- EXPECT_CALL(*pullerManager, Pull(tagId, _))
+ EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, _, _))
// Start bucket.
- .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
- data->clear();
- data->push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs, 3));
- return true;
- }));
+ .WillOnce(Invoke(
+ [](int tagId, const ConfigKey&, vector<std::shared_ptr<LogEvent>>* data, bool) {
+ data->clear();
+ data->push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs, 3));
+ return true;
+ }));
sp<ValueMetricProducer> valueProducer =
ValueMetricProducerTestHelper::createValueProducerNoConditions(pullerManager, metric);
@@ -2266,17 +2325,19 @@ TEST(ValueMetricProducerTest, TestEmptyDataResetsBase_onConditionChanged) {
ValueMetric metric = ValueMetricProducerTestHelper::createMetricWithCondition();
sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
- EXPECT_CALL(*pullerManager, Pull(tagId, _))
+ EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, _, _))
// First onConditionChanged
- .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
- data->clear();
- data->push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs, 3));
- return true;
- }))
- .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
- data->clear();
- return true;
- }));
+ .WillOnce(Invoke(
+ [](int tagId, const ConfigKey&, vector<std::shared_ptr<LogEvent>>* data, bool) {
+ data->clear();
+ data->push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs, 3));
+ return true;
+ }))
+ .WillOnce(Invoke(
+ [](int tagId, const ConfigKey&, vector<std::shared_ptr<LogEvent>>* data, bool) {
+ data->clear();
+ return true;
+ }));
sp<ValueMetricProducer> valueProducer =
ValueMetricProducerTestHelper::createValueProducerWithCondition(pullerManager, metric);
@@ -2304,23 +2365,26 @@ TEST(ValueMetricProducerTest, TestEmptyDataResetsBase_onBucketBoundary) {
ValueMetric metric = ValueMetricProducerTestHelper::createMetricWithCondition();
sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
- EXPECT_CALL(*pullerManager, Pull(tagId, _))
+ EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, _, _))
// First onConditionChanged
- .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
- data->clear();
- data->push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs, 1));
- return true;
- }))
- .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
- data->clear();
- data->push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs, 2));
- return true;
- }))
- .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
- data->clear();
- data->push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs, 5));
- return true;
- }));
+ .WillOnce(Invoke(
+ [](int tagId, const ConfigKey&, vector<std::shared_ptr<LogEvent>>* data, bool) {
+ data->clear();
+ data->push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs, 1));
+ return true;
+ }))
+ .WillOnce(Invoke(
+ [](int tagId, const ConfigKey&, vector<std::shared_ptr<LogEvent>>* data, bool) {
+ data->clear();
+ data->push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs, 2));
+ return true;
+ }))
+ .WillOnce(Invoke(
+ [](int tagId, const ConfigKey&, vector<std::shared_ptr<LogEvent>>* data, bool) {
+ data->clear();
+ data->push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs, 5));
+ return true;
+ }));
sp<ValueMetricProducer> valueProducer =
ValueMetricProducerTestHelper::createValueProducerWithCondition(pullerManager, metric);
@@ -2360,13 +2424,14 @@ TEST(ValueMetricProducerTest, TestPartialResetOnBucketBoundaries) {
metric.set_condition(StringToId("SCREEN_ON"));
sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
- EXPECT_CALL(*pullerManager, Pull(tagId, _))
+ EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, _, _))
// First onConditionChanged
- .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
- data->clear();
- data->push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs, 1));
- return true;
- }));
+ .WillOnce(Invoke(
+ [](int tagId, const ConfigKey&, vector<std::shared_ptr<LogEvent>>* data, bool) {
+ data->clear();
+ data->push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs, 1));
+ return true;
+ }));
sp<ValueMetricProducer> valueProducer =
ValueMetricProducerTestHelper::createValueProducerWithCondition(pullerManager, metric);
@@ -2400,15 +2465,17 @@ TEST(ValueMetricProducerTest, TestFullBucketResetWhenLastBucketInvalid) {
ValueMetric metric = ValueMetricProducerTestHelper::createMetric();
sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
- EXPECT_CALL(*pullerManager, Pull(tagId, _))
+ EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, _, _))
// Initialization.
- .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
- data->clear();
- data->push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs, 1));
- return true;
- }))
+ .WillOnce(Invoke(
+ [](int tagId, const ConfigKey&, vector<std::shared_ptr<LogEvent>>* data, bool) {
+ data->clear();
+ data->push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs, 1));
+ return true;
+ }))
// notifyAppUpgrade.
- .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
+ .WillOnce(Invoke([](int tagId, const ConfigKey&,
+ vector<std::shared_ptr<LogEvent>>* data, bool) {
data->clear();
data->push_back(CreateRepeatedValueLogEvent(
tagId, bucketStartTimeNs + bucketSizeNs / 2, 10));
@@ -2430,15 +2497,17 @@ TEST(ValueMetricProducerTest, TestFullBucketResetWhenLastBucketInvalid) {
TEST(ValueMetricProducerTest, TestBucketBoundariesOnConditionChange) {
ValueMetric metric = ValueMetricProducerTestHelper::createMetricWithCondition();
sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
- EXPECT_CALL(*pullerManager, Pull(tagId, _))
+ EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, _, _))
// Second onConditionChanged.
- .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
+ .WillOnce(Invoke([](int tagId, const ConfigKey&,
+ vector<std::shared_ptr<LogEvent>>* data, bool) {
data->clear();
data->push_back(CreateRepeatedValueLogEvent(tagId, bucket2StartTimeNs + 10, 5));
return true;
}))
// Third onConditionChanged.
- .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
+ .WillOnce(Invoke([](int tagId, const ConfigKey&,
+ vector<std::shared_ptr<LogEvent>>* data, bool) {
data->clear();
data->push_back(CreateRepeatedValueLogEvent(tagId, bucket3StartTimeNs + 10, 7));
return true;
@@ -2495,13 +2564,14 @@ TEST(ValueMetricProducerTest, TestLateOnDataPulledWithDiff) {
ValueMetric metric = ValueMetricProducerTestHelper::createMetric();
sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
- EXPECT_CALL(*pullerManager, Pull(tagId, _))
+ EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, _, _))
// Initialization.
- .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
- data->clear();
- data->push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs, 1));
- return true;
- }));
+ .WillOnce(Invoke(
+ [](int tagId, const ConfigKey&, vector<std::shared_ptr<LogEvent>>* data, bool) {
+ data->clear();
+ data->push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs, 1));
+ return true;
+ }));
sp<ValueMetricProducer> valueProducer =
ValueMetricProducerTestHelper::createValueProducerNoConditions(pullerManager, metric);
@@ -2522,15 +2592,17 @@ TEST(ValueMetricProducerTest, TestBucketBoundariesOnAppUpgrade) {
ValueMetric metric = ValueMetricProducerTestHelper::createMetric();
sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
- EXPECT_CALL(*pullerManager, Pull(tagId, _))
+ EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, _, _))
// Initialization.
- .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
- data->clear();
- data->push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs, 1));
- return true;
- }))
+ .WillOnce(Invoke(
+ [](int tagId, const ConfigKey&, vector<std::shared_ptr<LogEvent>>* data, bool) {
+ data->clear();
+ data->push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs, 1));
+ return true;
+ }))
// notifyAppUpgrade.
- .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
+ .WillOnce(Invoke([](int tagId, const ConfigKey&,
+ vector<std::shared_ptr<LogEvent>>* data, bool) {
data->clear();
data->push_back(CreateRepeatedValueLogEvent(tagId, bucket2StartTimeNs + 2, 10));
return true;
@@ -2549,19 +2621,21 @@ TEST(ValueMetricProducerTest, TestDataIsNotUpdatedWhenNoConditionChanged) {
ValueMetric metric = ValueMetricProducerTestHelper::createMetricWithCondition();
sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
- EXPECT_CALL(*pullerManager, Pull(tagId, _))
+ EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, _, _))
// First on condition changed.
- .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
- data->clear();
- data->push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs, 1));
- return true;
- }))
+ .WillOnce(Invoke(
+ [](int tagId, const ConfigKey&, vector<std::shared_ptr<LogEvent>>* data, bool) {
+ data->clear();
+ data->push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs, 1));
+ return true;
+ }))
// Second on condition changed.
- .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
- data->clear();
- data->push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs, 3));
- return true;
- }));
+ .WillOnce(Invoke(
+ [](int tagId, const ConfigKey&, vector<std::shared_ptr<LogEvent>>* data, bool) {
+ data->clear();
+ data->push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs, 3));
+ return true;
+ }));
sp<ValueMetricProducer> valueProducer =
ValueMetricProducerTestHelper::createValueProducerWithCondition(pullerManager, metric);
@@ -2588,25 +2662,28 @@ TEST(ValueMetricProducerTest, TestBucketInvalidIfGlobalBaseIsNotSet) {
ValueMetric metric = ValueMetricProducerTestHelper::createMetricWithCondition();
sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
- EXPECT_CALL(*pullerManager, Pull(tagId, _))
+ EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, _, _))
// First condition change.
- .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
- data->clear();
- data->push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs, 1));
- return true;
- }))
+ .WillOnce(Invoke(
+ [](int tagId, const ConfigKey&, vector<std::shared_ptr<LogEvent>>* data, bool) {
+ data->clear();
+ data->push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs, 1));
+ return true;
+ }))
// 2nd condition change.
- .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
- data->clear();
- data->push_back(CreateRepeatedValueLogEvent(tagId, bucket2StartTimeNs, 1));
- return true;
- }))
+ .WillOnce(Invoke(
+ [](int tagId, const ConfigKey&, vector<std::shared_ptr<LogEvent>>* data, bool) {
+ data->clear();
+ data->push_back(CreateRepeatedValueLogEvent(tagId, bucket2StartTimeNs, 1));
+ return true;
+ }))
// 3rd condition change.
- .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
- data->clear();
- data->push_back(CreateRepeatedValueLogEvent(tagId, bucket2StartTimeNs, 1));
- return true;
- }));
+ .WillOnce(Invoke(
+ [](int tagId, const ConfigKey&, vector<std::shared_ptr<LogEvent>>* data, bool) {
+ data->clear();
+ data->push_back(CreateRepeatedValueLogEvent(tagId, bucket2StartTimeNs, 1));
+ return true;
+ }));
sp<ValueMetricProducer> valueProducer =
ValueMetricProducerTestHelper::createValueProducerWithCondition(pullerManager, metric);
@@ -2642,12 +2719,13 @@ TEST(ValueMetricProducerTest, TestPullNeededFastDump) {
atomMatcherId, logEventMatcherIndex, atomMatcher, uidMap)});
sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
- EXPECT_CALL(*pullerManager, RegisterReceiver(tagId, _, _, _)).WillOnce(Return());
- EXPECT_CALL(*pullerManager, UnRegisterReceiver(tagId, _)).WillRepeatedly(Return());
+ EXPECT_CALL(*pullerManager, RegisterReceiver(tagId, kConfigKey, _, _, _)).WillOnce(Return());
+ EXPECT_CALL(*pullerManager, UnRegisterReceiver(tagId, kConfigKey, _)).WillRepeatedly(Return());
- EXPECT_CALL(*pullerManager, Pull(tagId, _))
+ EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, _, _))
// Initial pull.
- .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
+ .WillOnce(Invoke([](int tagId, const ConfigKey&,
+ vector<std::shared_ptr<LogEvent>>* data, bool) {
data->clear();
data->push_back(CreateThreeValueLogEvent(tagId, bucketStartTimeNs, tagId, 1, 1));
return true;
@@ -2656,6 +2734,7 @@ TEST(ValueMetricProducerTest, TestPullNeededFastDump) {
ValueMetricProducer valueProducer(kConfigKey, metric, -1, wizard, logEventMatcherIndex,
eventMatcherWizard, tagId, bucketStartTimeNs,
bucketStartTimeNs, pullerManager);
+ valueProducer.prepareFirstBucket();
ProtoOutputStream output;
std::set<string> strSet;
@@ -2678,12 +2757,13 @@ TEST(ValueMetricProducerTest, TestFastDumpWithoutCurrentBucket) {
atomMatcherId, logEventMatcherIndex, atomMatcher, uidMap)});
sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
- EXPECT_CALL(*pullerManager, RegisterReceiver(tagId, _, _, _)).WillOnce(Return());
- EXPECT_CALL(*pullerManager, UnRegisterReceiver(tagId, _)).WillRepeatedly(Return());
+ EXPECT_CALL(*pullerManager, RegisterReceiver(tagId, kConfigKey, _, _, _)).WillOnce(Return());
+ EXPECT_CALL(*pullerManager, UnRegisterReceiver(tagId, kConfigKey, _)).WillRepeatedly(Return());
- EXPECT_CALL(*pullerManager, Pull(tagId, _))
+ EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, _, _))
// Initial pull.
- .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
+ .WillOnce(Invoke([](int tagId, const ConfigKey&,
+ vector<std::shared_ptr<LogEvent>>* data, bool) {
data->clear();
data->push_back(CreateThreeValueLogEvent(tagId, bucketStartTimeNs, tagId, 1, 1));
return true;
@@ -2692,6 +2772,7 @@ TEST(ValueMetricProducerTest, TestFastDumpWithoutCurrentBucket) {
ValueMetricProducer valueProducer(kConfigKey, metric, -1, wizard, logEventMatcherIndex,
eventMatcherWizard, tagId, bucketStartTimeNs,
bucketStartTimeNs, pullerManager);
+ valueProducer.prepareFirstBucket();
vector<shared_ptr<LogEvent>> allData;
allData.clear();
@@ -2720,17 +2801,19 @@ TEST(ValueMetricProducerTest, TestPullNeededNoTimeConstraints) {
atomMatcherId, logEventMatcherIndex, atomMatcher, uidMap)});
sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
- EXPECT_CALL(*pullerManager, RegisterReceiver(tagId, _, _, _)).WillOnce(Return());
- EXPECT_CALL(*pullerManager, UnRegisterReceiver(tagId, _)).WillRepeatedly(Return());
+ EXPECT_CALL(*pullerManager, RegisterReceiver(tagId, kConfigKey, _, _, _)).WillOnce(Return());
+ EXPECT_CALL(*pullerManager, UnRegisterReceiver(tagId, kConfigKey, _)).WillRepeatedly(Return());
- EXPECT_CALL(*pullerManager, Pull(tagId, _))
+ EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, _, _))
// Initial pull.
- .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
+ .WillOnce(Invoke([](int tagId, const ConfigKey&,
+ vector<std::shared_ptr<LogEvent>>* data, bool) {
data->clear();
data->push_back(CreateThreeValueLogEvent(tagId, bucketStartTimeNs, tagId, 1, 1));
return true;
}))
- .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
+ .WillOnce(Invoke([](int tagId, const ConfigKey&,
+ vector<std::shared_ptr<LogEvent>>* data, bool) {
data->clear();
data->push_back(
CreateThreeValueLogEvent(tagId, bucketStartTimeNs + 10, tagId, 3, 3));
@@ -2740,6 +2823,7 @@ TEST(ValueMetricProducerTest, TestPullNeededNoTimeConstraints) {
ValueMetricProducer valueProducer(kConfigKey, metric, -1, wizard, logEventMatcherIndex,
eventMatcherWizard, tagId, bucketStartTimeNs,
bucketStartTimeNs, pullerManager);
+ valueProducer.prepareFirstBucket();
ProtoOutputStream output;
std::set<string> strSet;
@@ -2773,15 +2857,17 @@ TEST(ValueMetricProducerTest, TestPulledData_noDiff_withMultipleConditionChanges
metric.set_use_diff(false);
sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
- EXPECT_CALL(*pullerManager, Pull(tagId, _))
+ EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, _, _))
// condition becomes true
- .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
+ .WillOnce(Invoke([](int tagId, const ConfigKey&,
+ vector<std::shared_ptr<LogEvent>>* data, bool) {
data->clear();
data->push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs + 30, 10));
return true;
}))
// condition becomes false
- .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
+ .WillOnce(Invoke([](int tagId, const ConfigKey&,
+ vector<std::shared_ptr<LogEvent>>* data, bool) {
data->clear();
data->push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs + 50, 20));
return true;
@@ -2818,9 +2904,10 @@ TEST(ValueMetricProducerTest, TestPulledData_noDiff_bucketBoundaryTrue) {
metric.set_use_diff(false);
sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
- EXPECT_CALL(*pullerManager, Pull(tagId, _))
+ EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, _, _))
// condition becomes true
- .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
+ .WillOnce(Invoke([](int tagId, const ConfigKey&,
+ vector<std::shared_ptr<LogEvent>>* data, bool) {
data->clear();
data->push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs + 30, 10));
return true;
@@ -2867,9 +2954,10 @@ TEST(ValueMetricProducerTest, TestPulledData_noDiff_withFailure) {
metric.set_use_diff(false);
sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
- EXPECT_CALL(*pullerManager, Pull(tagId, _))
+ EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, _, _))
// condition becomes true
- .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
+ .WillOnce(Invoke([](int tagId, const ConfigKey&,
+ vector<std::shared_ptr<LogEvent>>* data, bool) {
data->clear();
data->push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs + 30, 10));
return true;
@@ -2905,9 +2993,10 @@ TEST(ValueMetricProducerTest_BucketDrop, TestInvalidBucketWhenDumpReportRequeste
ValueMetric metric = ValueMetricProducerTestHelper::createMetricWithCondition();
sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
- EXPECT_CALL(*pullerManager, Pull(tagId, _))
+ EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, _, _))
// Condition change to true.
- .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
+ .WillOnce(Invoke([](int tagId, const ConfigKey&,
+ vector<std::shared_ptr<LogEvent>>* data, bool) {
data->clear();
data->push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs + 20, 10));
return true;
@@ -2949,9 +3038,10 @@ TEST(ValueMetricProducerTest_BucketDrop, TestInvalidBucketWhenConditionEventWron
ValueMetric metric = ValueMetricProducerTestHelper::createMetricWithCondition();
sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
- EXPECT_CALL(*pullerManager, Pull(tagId, _))
+ EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, _, _))
// Condition change to true.
- .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
+ .WillOnce(Invoke([](int tagId, const ConfigKey&,
+ vector<std::shared_ptr<LogEvent>>* data, bool) {
data->clear();
data->push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs + 50, 10));
return true;
@@ -3001,15 +3091,17 @@ TEST(ValueMetricProducerTest_BucketDrop, TestInvalidBucketWhenAccumulateEventWro
ValueMetric metric = ValueMetricProducerTestHelper::createMetricWithCondition();
sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
- EXPECT_CALL(*pullerManager, Pull(tagId, _))
+ EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, _, _))
// Condition change to true.
- .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
+ .WillOnce(Invoke([](int tagId, const ConfigKey&,
+ vector<std::shared_ptr<LogEvent>>* data, bool) {
data->clear();
data->push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs + 50, 10));
return true;
}))
// Dump report requested.
- .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
+ .WillOnce(Invoke([](int tagId, const ConfigKey&,
+ vector<std::shared_ptr<LogEvent>>* data, bool) {
data->clear();
data->push_back(CreateRepeatedValueLogEvent(tagId, bucket2StartTimeNs + 100, 15));
return true;
@@ -3062,15 +3154,17 @@ TEST(ValueMetricProducerTest_BucketDrop, TestInvalidBucketWhenConditionUnknown)
ValueMetric metric = ValueMetricProducerTestHelper::createMetricWithCondition();
sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
- EXPECT_CALL(*pullerManager, Pull(tagId, _))
+ EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, _, _))
// Condition change to true.
- .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
+ .WillOnce(Invoke([](int tagId, const ConfigKey&,
+ vector<std::shared_ptr<LogEvent>>* data, bool) {
data->clear();
data->push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs + 50, 10));
return true;
}))
// Dump report requested.
- .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
+ .WillOnce(Invoke([](int tagId, const ConfigKey&,
+ vector<std::shared_ptr<LogEvent>>* data, bool) {
data->clear();
data->push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs + 100, 15));
return true;
@@ -3114,9 +3208,10 @@ TEST(ValueMetricProducerTest_BucketDrop, TestInvalidBucketWhenPullFailed) {
ValueMetric metric = ValueMetricProducerTestHelper::createMetricWithCondition();
sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
- EXPECT_CALL(*pullerManager, Pull(tagId, _))
+ EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, _, _))
// Condition change to true.
- .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
+ .WillOnce(Invoke([](int tagId, const ConfigKey&,
+ vector<std::shared_ptr<LogEvent>>* data, bool) {
data->clear();
data->push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs + 50, 10));
return true;
@@ -3161,15 +3256,17 @@ TEST(ValueMetricProducerTest_BucketDrop, TestInvalidBucketWhenMultipleBucketsSki
ValueMetric metric = ValueMetricProducerTestHelper::createMetricWithCondition();
sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
- EXPECT_CALL(*pullerManager, Pull(tagId, _))
+ EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, _, _))
// Condition change to true.
- .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
+ .WillOnce(Invoke([](int tagId, const ConfigKey&,
+ vector<std::shared_ptr<LogEvent>>* data, bool) {
data->clear();
data->push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs + 10, 10));
return true;
}))
// Dump report requested.
- .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
+ .WillOnce(Invoke([](int tagId, const ConfigKey&,
+ vector<std::shared_ptr<LogEvent>>* data, bool) {
data->clear();
data->push_back(CreateRepeatedValueLogEvent(tagId, bucket4StartTimeNs + 1000, 15));
return true;
@@ -3215,15 +3312,17 @@ TEST(ValueMetricProducerTest_BucketDrop, TestBucketDropWhenBucketTooSmall) {
metric.set_min_bucket_size_nanos(10000000000); // 10 seconds
sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
- EXPECT_CALL(*pullerManager, Pull(tagId, _))
+ EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, _, _))
// Condition change to true.
- .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
+ .WillOnce(Invoke([](int tagId, const ConfigKey&,
+ vector<std::shared_ptr<LogEvent>>* data, bool) {
data->clear();
data->push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs + 10, 10));
return true;
}))
// Dump report requested.
- .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
+ .WillOnce(Invoke([](int tagId, const ConfigKey&,
+ vector<std::shared_ptr<LogEvent>>* data, bool) {
data->clear();
data->push_back(
CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs + 9000000, 15));
@@ -3266,9 +3365,10 @@ TEST(ValueMetricProducerTest_BucketDrop, TestMultipleBucketDropEvents) {
ValueMetric metric = ValueMetricProducerTestHelper::createMetricWithCondition();
sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
- EXPECT_CALL(*pullerManager, Pull(tagId, _))
+ EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, _, _))
// Condition change to true.
- .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
+ .WillOnce(Invoke([](int tagId, const ConfigKey&,
+ vector<std::shared_ptr<LogEvent>>* data, bool) {
data->clear();
data->push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs + 10, 10));
return true;
@@ -3316,9 +3416,10 @@ TEST(ValueMetricProducerTest_BucketDrop, TestMaxBucketDropEvents) {
ValueMetric metric = ValueMetricProducerTestHelper::createMetricWithCondition();
sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
- EXPECT_CALL(*pullerManager, Pull(tagId, _))
+ EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, _, _))
// First condition change event.
- .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
+ .WillOnce(Invoke([](int tagId, const ConfigKey&,
+ vector<std::shared_ptr<LogEvent>>* data, bool) {
for (int i = 0; i < 2000; i++) {
data->push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs + 1, i));
}
@@ -3333,7 +3434,8 @@ TEST(ValueMetricProducerTest_BucketDrop, TestMaxBucketDropEvents) {
.WillOnce(Return(false))
.WillOnce(Return(false))
.WillOnce(Return(false))
- .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
+ .WillOnce(Invoke([](int tagId, const ConfigKey&,
+ vector<std::shared_ptr<LogEvent>>* data, bool) {
data->clear();
data->push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs + 220, 10));
return true;
@@ -3431,33 +3533,38 @@ TEST(ValueMetricProducerTest, TestSlicedState) {
// Set up ValueMetricProducer.
ValueMetric metric = ValueMetricProducerTestHelper::createMetricWithState("SCREEN_STATE");
sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
- EXPECT_CALL(*pullerManager, Pull(tagId, _))
+ EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, _, _))
// ValueMetricProducer initialized.
- .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
- data->clear();
- data->push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs, 3));
- return true;
- }))
+ .WillOnce(Invoke(
+ [](int tagId, const ConfigKey&, vector<std::shared_ptr<LogEvent>>* data, bool) {
+ data->clear();
+ data->push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs, 3));
+ return true;
+ }))
// Screen state change to ON.
- .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
+ .WillOnce(Invoke([](int tagId, const ConfigKey&,
+ vector<std::shared_ptr<LogEvent>>* data, bool) {
data->clear();
data->push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs + 5, 5));
return true;
}))
// Screen state change to OFF.
- .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
+ .WillOnce(Invoke([](int tagId, const ConfigKey&,
+ vector<std::shared_ptr<LogEvent>>* data, bool) {
data->clear();
data->push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs + 10, 9));
return true;
}))
// Screen state change to ON.
- .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
+ .WillOnce(Invoke([](int tagId, const ConfigKey&,
+ vector<std::shared_ptr<LogEvent>>* data, bool) {
data->clear();
data->push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs + 15, 21));
return true;
}))
// Dump report requested.
- .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
+ .WillOnce(Invoke([](int tagId, const ConfigKey&,
+ vector<std::shared_ptr<LogEvent>>* data, bool) {
data->clear();
data->push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs + 50, 30));
return true;
@@ -3582,33 +3689,38 @@ TEST(ValueMetricProducerTest, TestSlicedStateWithMap) {
// Set up ValueMetricProducer.
ValueMetric metric = ValueMetricProducerTestHelper::createMetricWithState("SCREEN_STATE_ONOFF");
sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
- EXPECT_CALL(*pullerManager, Pull(tagId, _))
+ EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, _, _))
// ValueMetricProducer initialized.
- .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
- data->clear();
- data->push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs, 3));
- return true;
- }))
+ .WillOnce(Invoke(
+ [](int tagId, const ConfigKey&, vector<std::shared_ptr<LogEvent>>* data, bool) {
+ data->clear();
+ data->push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs, 3));
+ return true;
+ }))
// Screen state change to ON.
- .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
+ .WillOnce(Invoke([](int tagId, const ConfigKey&,
+ vector<std::shared_ptr<LogEvent>>* data, bool) {
data->clear();
data->push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs + 5, 5));
return true;
}))
// Screen state change to VR.
- .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
+ .WillOnce(Invoke([](int tagId, const ConfigKey&,
+ vector<std::shared_ptr<LogEvent>>* data, bool) {
data->clear();
data->push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs + 10, 9));
return true;
}))
// Screen state change to OFF.
- .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
+ .WillOnce(Invoke([](int tagId, const ConfigKey&,
+ vector<std::shared_ptr<LogEvent>>* data, bool) {
data->clear();
data->push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs + 15, 21));
return true;
}))
// Dump report requested.
- .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
+ .WillOnce(Invoke([](int tagId, const ConfigKey&,
+ vector<std::shared_ptr<LogEvent>>* data, bool) {
data->clear();
data->push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs + 50, 30));
return true;
@@ -3748,16 +3860,18 @@ TEST(ValueMetricProducerTest, TestSlicedStateWithPrimaryField_WithDimensions) {
*fieldsInState = CreateDimensions(UID_PROCESS_STATE_ATOM_ID, {1 /* uid */});
sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
- EXPECT_CALL(*pullerManager, Pull(tagId, _))
+ EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, _, _))
// ValueMetricProducer initialized.
- .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
+ .WillOnce(Invoke([](int tagId, const ConfigKey&,
+ vector<std::shared_ptr<LogEvent>>* data, bool) {
data->clear();
data->push_back(CreateTwoValueLogEvent(tagId, bucketStartTimeNs, 2 /*uid*/, 7));
data->push_back(CreateTwoValueLogEvent(tagId, bucketStartTimeNs, 1 /*uid*/, 3));
return true;
}))
// Uid 1 process state change from kStateUnknown -> Foreground
- .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
+ .WillOnce(Invoke([](int tagId, const ConfigKey&,
+ vector<std::shared_ptr<LogEvent>>* data, bool) {
data->clear();
data->push_back(
CreateTwoValueLogEvent(tagId, bucketStartTimeNs + 20, 1 /*uid*/, 6));
@@ -3768,7 +3882,8 @@ TEST(ValueMetricProducerTest, TestSlicedStateWithPrimaryField_WithDimensions) {
return true;
}))
// Uid 2 process state change from kStateUnknown -> Background
- .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
+ .WillOnce(Invoke([](int tagId, const ConfigKey&,
+ vector<std::shared_ptr<LogEvent>>* data, bool) {
data->clear();
data->push_back(
CreateTwoValueLogEvent(tagId, bucketStartTimeNs + 40, 2 /*uid*/, 9));
@@ -3779,7 +3894,8 @@ TEST(ValueMetricProducerTest, TestSlicedStateWithPrimaryField_WithDimensions) {
return true;
}))
// Uid 1 process state change from Foreground -> Background
- .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
+ .WillOnce(Invoke([](int tagId, const ConfigKey&,
+ vector<std::shared_ptr<LogEvent>>* data, bool) {
data->clear();
data->push_back(
CreateTwoValueLogEvent(tagId, bucket2StartTimeNs + 20, 1 /*uid*/, 13));
@@ -3790,7 +3906,8 @@ TEST(ValueMetricProducerTest, TestSlicedStateWithPrimaryField_WithDimensions) {
return true;
}))
// Uid 1 process state change from Background -> Foreground
- .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
+ .WillOnce(Invoke([](int tagId, const ConfigKey&,
+ vector<std::shared_ptr<LogEvent>>* data, bool) {
data->clear();
data->push_back(
CreateTwoValueLogEvent(tagId, bucket2StartTimeNs + 40, 1 /*uid*/, 17));
@@ -3801,7 +3918,8 @@ TEST(ValueMetricProducerTest, TestSlicedStateWithPrimaryField_WithDimensions) {
return true;
}))
// Dump report pull.
- .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
+ .WillOnce(Invoke([](int tagId, const ConfigKey&,
+ vector<std::shared_ptr<LogEvent>>* data, bool) {
data->clear();
data->push_back(
CreateTwoValueLogEvent(tagId, bucket2StartTimeNs + 50, 2 /*uid*/, 20));
diff --git a/cmds/statsd/tests/metrics/metrics_test_helper.h b/cmds/statsd/tests/metrics/metrics_test_helper.h
index 09c4d9e41fc2..69f7e3f49792 100644
--- a/cmds/statsd/tests/metrics/metrics_test_helper.h
+++ b/cmds/statsd/tests/metrics/metrics_test_helper.h
@@ -33,15 +33,24 @@ public:
class MockStatsPullerManager : public StatsPullerManager {
public:
- MOCK_METHOD4(RegisterReceiver, void(int tagId, wp<PullDataReceiver> receiver,
- int64_t nextPulltimeNs, int64_t intervalNs));
- MOCK_METHOD2(UnRegisterReceiver, void(int tagId, wp<PullDataReceiver> receiver));
- MOCK_METHOD2(Pull, bool(const int pullCode, vector<std::shared_ptr<LogEvent>>* data));
+ MOCK_METHOD5(RegisterReceiver,
+ void(int tagId, const ConfigKey& key, wp<PullDataReceiver> receiver,
+ int64_t nextPulltimeNs, int64_t intervalNs));
+ MOCK_METHOD3(UnRegisterReceiver,
+ void(int tagId, const ConfigKey& key, wp<PullDataReceiver> receiver));
+ MOCK_METHOD4(Pull, bool(const int pullCode, const ConfigKey& key,
+ vector<std::shared_ptr<LogEvent>>* data, bool useUids));
+ MOCK_METHOD4(Pull, bool(const int pullCode, const vector<int32_t>& uids,
+ vector<std::shared_ptr<LogEvent>>* data, bool useUids));
+ MOCK_METHOD2(RegisterPullUidProvider,
+ void(const ConfigKey& configKey, wp<PullUidProvider> provider));
+ MOCK_METHOD1(UnregisterPullUidProvider, void(const ConfigKey& configKey));
};
class MockUidMap : public UidMap {
public:
MOCK_CONST_METHOD1(getHostUidOrSelf, int(int uid));
+ MOCK_CONST_METHOD1(getAppUid, std::set<int32_t>(const string& package));
};
HashableDimensionKey getMockedDimensionKey(int tagId, int key, std::string value);
diff --git a/cmds/statsd/tests/shell/ShellSubscriber_test.cpp b/cmds/statsd/tests/shell/ShellSubscriber_test.cpp
index 5eef92e12ba9..ac3ad690f81e 100644
--- a/cmds/statsd/tests/shell/ShellSubscriber_test.cpp
+++ b/cmds/statsd/tests/shell/ShellSubscriber_test.cpp
@@ -187,8 +187,10 @@ TEST(ShellSubscriberTest, testPulledSubscription) {
sp<MockUidMap> uidMap = new NaggyMock<MockUidMap>();
sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
- EXPECT_CALL(*pullerManager, Pull(10016, _))
- .WillRepeatedly(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
+ const vector<int32_t> uids = {AID_SYSTEM};
+ EXPECT_CALL(*pullerManager, Pull(10016, uids, _, _))
+ .WillRepeatedly(Invoke([](int tagId, const vector<int32_t>&,
+ vector<std::shared_ptr<LogEvent>>* data, bool) {
data->clear();
data->push_back(makeCpuActiveTimeAtom(/*uid=*/kUid1, /*timeMillis=*/kCpuTime1));
data->push_back(makeCpuActiveTimeAtom(/*uid=*/kUid2, /*timeMillis=*/kCpuTime2));
diff --git a/cmds/statsd/tools/localtools/src/com/android/statsd/shelltools/testdrive/TestDrive.java b/cmds/statsd/tools/localtools/src/com/android/statsd/shelltools/testdrive/TestDrive.java
index c97f03562857..75518a3ea56f 100644
--- a/cmds/statsd/tools/localtools/src/com/android/statsd/shelltools/testdrive/TestDrive.java
+++ b/cmds/statsd/tools/localtools/src/com/android/statsd/shelltools/testdrive/TestDrive.java
@@ -19,6 +19,7 @@ import com.android.internal.os.StatsdConfigProto.AtomMatcher;
import com.android.internal.os.StatsdConfigProto.EventMetric;
import com.android.internal.os.StatsdConfigProto.FieldFilter;
import com.android.internal.os.StatsdConfigProto.GaugeMetric;
+import com.android.internal.os.StatsdConfigProto.PullAtomPackages;
import com.android.internal.os.StatsdConfigProto.SimpleAtomMatcher;
import com.android.internal.os.StatsdConfigProto.StatsdConfig;
import com.android.internal.os.StatsdConfigProto.TimeUnit;
@@ -33,6 +34,7 @@ import com.google.common.io.Files;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
+import java.util.Arrays;
import java.util.Collections;
import java.util.HashSet;
import java.util.Set;
@@ -49,19 +51,22 @@ public class TestDrive {
private static final int VENDOR_PULLED_ATOM_START_TAG = 150000;
private static final long CONFIG_ID = 54321;
private static final String[] ALLOWED_LOG_SOURCES = {
- "AID_GRAPHICS",
- "AID_INCIDENTD",
- "AID_STATSD",
- "AID_RADIO",
- "com.android.systemui",
- "com.android.vending",
- "AID_SYSTEM",
- "AID_ROOT",
- "AID_BLUETOOTH",
- "AID_LMKD",
- "com.android.managedprovisioning",
- "AID_MEDIA",
- "AID_NETWORK_STACK"
+ "AID_GRAPHICS",
+ "AID_INCIDENTD",
+ "AID_STATSD",
+ "AID_RADIO",
+ "com.android.systemui",
+ "com.android.vending",
+ "AID_SYSTEM",
+ "AID_ROOT",
+ "AID_BLUETOOTH",
+ "AID_LMKD",
+ "com.android.managedprovisioning",
+ "AID_MEDIA",
+ "AID_NETWORK_STACK"
+ };
+ private static final String[] DEFAULT_PULL_SOURCES = {
+ "AID_SYSTEM",
};
private static final Logger LOGGER = Logger.getLogger(TestDrive.class.getName());
@@ -158,6 +163,16 @@ public class TestDrive {
StatsdConfig.Builder builder = StatsdConfig.newBuilder();
builder
.addAllAllowedLogSource(allowedSources)
+ .addAllDefaultPullPackages(Arrays.asList(DEFAULT_PULL_SOURCES))
+ .addPullAtomPackages(PullAtomPackages.newBuilder()
+ .setAtomId(Atom.GPU_STATS_GLOBAL_INFO_FIELD_NUMBER)
+ .addPackages("AID_GPU_SERVICE"))
+ .addPullAtomPackages(PullAtomPackages.newBuilder()
+ .setAtomId(Atom.GPU_STATS_APP_INFO_FIELD_NUMBER)
+ .addPackages("AID_GPU_SERVICE"))
+ .addPullAtomPackages(PullAtomPackages.newBuilder()
+ .setAtomId(Atom.TRAIN_INFO_FIELD_NUMBER)
+ .addPackages("AID_STATSD"))
.setHashStringsInMetricReport(false);
if (hasPulledAtom(atomIds)) {
diff --git a/core/java/android/app/ActivityManagerInternal.java b/core/java/android/app/ActivityManagerInternal.java
index f926075714a8..9f51edbb1ded 100644
--- a/core/java/android/app/ActivityManagerInternal.java
+++ b/core/java/android/app/ActivityManagerInternal.java
@@ -394,4 +394,13 @@ public abstract class ActivityManagerInternal {
*/
// TODO: remove this toast after feature development is done
public abstract void showWhileInUseDebugToast(int uid, int op, int mode);
+
+
+ /** Is this a device owner app? */
+ public abstract boolean isDeviceOwner(int uid);
+
+ /**
+ * Called by DevicePolicyManagerService to set the uid of the device owner.
+ */
+ public abstract void setDeviceOwnerUid(int uid);
}
diff --git a/core/java/android/app/AppOpsManager.java b/core/java/android/app/AppOpsManager.java
index a5dcefcf3ab7..c04588df9ca7 100644
--- a/core/java/android/app/AppOpsManager.java
+++ b/core/java/android/app/AppOpsManager.java
@@ -1496,8 +1496,6 @@ public class AppOpsManager {
OP_MANAGE_EXTERNAL_STORAGE,
OP_INTERACT_ACROSS_PROFILES,
OP_LOADER_USAGE_STATS,
- OP_AUTO_REVOKE_PERMISSIONS_IF_UNUSED,
- OP_AUTO_REVOKE_MANAGED_BY_INSTALLER,
};
/**
diff --git a/core/java/android/app/ContextImpl.java b/core/java/android/app/ContextImpl.java
index 17fd4efec9cc..d8757c36374a 100644
--- a/core/java/android/app/ContextImpl.java
+++ b/core/java/android/app/ContextImpl.java
@@ -1920,7 +1920,9 @@ class ContextImpl extends Context {
return SystemServiceRegistry.getSystemServiceName(serviceClass);
}
- private boolean isUiContext() {
+ /** @hide */
+ @Override
+ public boolean isUiContext() {
return mIsSystemOrSystemUiContext || mIsUiContext || isSystemOrSystemUI();
}
diff --git a/core/java/android/app/IActivityManager.aidl b/core/java/android/app/IActivityManager.aidl
index 7fc10ed090c8..833bfed573b2 100644
--- a/core/java/android/app/IActivityManager.aidl
+++ b/core/java/android/app/IActivityManager.aidl
@@ -144,9 +144,6 @@ interface IActivityManager {
void attachApplication(in IApplicationThread app, long startSeq);
List<ActivityManager.RunningTaskInfo> getTasks(int maxNum);
@UnsupportedAppUsage
- List<ActivityManager.RunningTaskInfo> getFilteredTasks(int maxNum, int ignoreActivityType,
- int ignoreWindowingMode);
- @UnsupportedAppUsage
void moveTaskToFront(in IApplicationThread caller, in String callingPackage, int task,
int flags, in Bundle options);
@UnsupportedAppUsage
diff --git a/core/java/android/app/IActivityTaskManager.aidl b/core/java/android/app/IActivityTaskManager.aidl
index 03717ecd4038..e476993f003f 100644
--- a/core/java/android/app/IActivityTaskManager.aidl
+++ b/core/java/android/app/IActivityTaskManager.aidl
@@ -155,8 +155,8 @@ interface IActivityTaskManager {
boolean removeTask(int taskId);
void removeAllVisibleRecentTasks();
List<ActivityManager.RunningTaskInfo> getTasks(int maxNum);
- List<ActivityManager.RunningTaskInfo> getFilteredTasks(int maxNum, int ignoreActivityType,
- int ignoreWindowingMode);
+ List<ActivityManager.RunningTaskInfo> getFilteredTasks(int maxNum,
+ boolean filterOnlyVisibleRecents);
boolean shouldUpRecreateTask(in IBinder token, in String destAffinity);
boolean navigateUpTo(in IBinder token, in Intent target, int resultCode,
in Intent resultData);
@@ -298,13 +298,6 @@ interface IActivityTaskManager {
void reportSizeConfigurations(in IBinder token, in int[] horizontalSizeConfiguration,
in int[] verticalSizeConfigurations, in int[] smallestWidthConfigurations);
- /**
- * Dismisses PiP
- * @param animate True if the dismissal should be animated.
- * @param animationDuration The duration of the resize animation in milliseconds or -1 if the
- * default animation duration should be used.
- */
- void dismissPip(boolean animate, int animationDuration);
void suppressResizeConfigChanges(boolean suppress);
void moveTasksToFullscreenStack(int fromStackId, boolean onTop);
boolean moveTopActivityToPinnedStack(int stackId, in Rect bounds);
diff --git a/core/java/android/app/SystemServiceRegistry.java b/core/java/android/app/SystemServiceRegistry.java
index 1aabd24d6df6..054e5e0945f3 100644
--- a/core/java/android/app/SystemServiceRegistry.java
+++ b/core/java/android/app/SystemServiceRegistry.java
@@ -1310,7 +1310,7 @@ public final class SystemServiceRegistry {
throws ServiceNotFoundException {
IBinder b = ServiceManager.getServiceOrThrow(
Context.FILE_INTEGRITY_SERVICE);
- return new FileIntegrityManager(
+ return new FileIntegrityManager(ctx.getOuterContext(),
IFileIntegrityService.Stub.asInterface(b));
}});
//CHECKSTYLE:ON IndentationCheck
diff --git a/core/java/android/app/TaskEmbedder.java b/core/java/android/app/TaskEmbedder.java
index 5ebcc46aa0d8..b8ad30840173 100644
--- a/core/java/android/app/TaskEmbedder.java
+++ b/core/java/android/app/TaskEmbedder.java
@@ -16,6 +16,7 @@
package android.app;
+import static android.app.WindowConfiguration.WINDOWING_MODE_MULTI_WINDOW;
import static android.hardware.display.DisplayManager.VIRTUAL_DISPLAY_FLAG_DESTROY_CONTENT_ON_REMOVAL;
import static android.hardware.display.DisplayManager.VIRTUAL_DISPLAY_FLAG_OWN_CONTENT_ONLY;
import static android.hardware.display.DisplayManager.VIRTUAL_DISPLAY_FLAG_PUBLIC;
@@ -291,7 +292,7 @@ public class TaskEmbedder {
* @see #startActivity(PendingIntent)
*/
public void startActivity(@NonNull Intent intent) {
- final ActivityOptions options = prepareActivityOptions();
+ final ActivityOptions options = prepareActivityOptions(null);
mContext.startActivity(intent, options.toBundle());
}
@@ -304,7 +305,7 @@ public class TaskEmbedder {
* @see #startActivity(PendingIntent)
*/
public void startActivity(@NonNull Intent intent, UserHandle user) {
- final ActivityOptions options = prepareActivityOptions();
+ final ActivityOptions options = prepareActivityOptions(null);
mContext.startActivityAsUser(intent, options.toBundle(), user);
}
@@ -316,7 +317,7 @@ public class TaskEmbedder {
* @see #startActivity(Intent)
*/
public void startActivity(@NonNull PendingIntent pendingIntent) {
- final ActivityOptions options = prepareActivityOptions();
+ final ActivityOptions options = prepareActivityOptions(null);
try {
pendingIntent.send(null /* context */, 0 /* code */, null /* intent */,
null /* onFinished */, null /* handler */, null /* requiredPermission */,
@@ -337,8 +338,7 @@ public class TaskEmbedder {
*/
public void startActivity(@NonNull PendingIntent pendingIntent, @Nullable Intent fillInIntent,
@NonNull ActivityOptions options) {
-
- options.setLaunchDisplayId(mVirtualDisplay.getDisplay().getDisplayId());
+ prepareActivityOptions(options);
try {
pendingIntent.send(mContext, 0 /* code */, fillInIntent,
null /* onFinished */, null /* handler */, null /* requiredPermission */,
@@ -364,21 +364,25 @@ public class TaskEmbedder {
@NonNull ActivityOptions options, @Nullable Rect sourceBounds) {
LauncherApps service =
(LauncherApps) mContext.getSystemService(Context.LAUNCHER_APPS_SERVICE);
- options.setLaunchDisplayId(mVirtualDisplay.getDisplay().getDisplayId());
+ prepareActivityOptions(options);
service.startShortcut(shortcut, sourceBounds, options.toBundle());
}
/**
- * Check if container is ready to launch and create {@link ActivityOptions} to target the
- * virtual display.
+ * Check if container is ready to launch and modify {@param options} to target the virtual
+ * display, creating them if necessary.
*/
- private ActivityOptions prepareActivityOptions() {
+ private ActivityOptions prepareActivityOptions(ActivityOptions options) {
if (mVirtualDisplay == null) {
throw new IllegalStateException(
"Trying to start activity before ActivityView is ready.");
}
- final ActivityOptions options = ActivityOptions.makeBasic();
+ if (options == null) {
+ options = ActivityOptions.makeBasic();
+ }
options.setLaunchDisplayId(getDisplayId());
+ options.setLaunchWindowingMode(WINDOWING_MODE_MULTI_WINDOW);
+ options.setTaskAlwaysOnTop(true);
return options;
}
diff --git a/core/java/android/content/Context.java b/core/java/android/content/Context.java
index 2fe935e35735..e21a31e5e185 100644
--- a/core/java/android/content/Context.java
+++ b/core/java/android/content/Context.java
@@ -6103,4 +6103,13 @@ public abstract class Context {
+ "get a UI context from ActivityThread#getSystemUiContext()");
}
}
+
+ /**
+ * Indicates if this context is a visual context such as {@link android.app.Activity} or
+ * a context created from {@link #createWindowContext(int, Bundle)}.
+ * @hide
+ */
+ public boolean isUiContext() {
+ throw new RuntimeException("Not implemented. Must override in a subclass.");
+ }
}
diff --git a/core/java/android/content/ContextWrapper.java b/core/java/android/content/ContextWrapper.java
index d389d2a4ae09..5dc41e483640 100644
--- a/core/java/android/content/ContextWrapper.java
+++ b/core/java/android/content/ContextWrapper.java
@@ -1145,4 +1145,12 @@ public class ContextWrapper extends Context {
mBase.setContentCaptureOptions(options);
}
}
+
+ /**
+ * @hide
+ */
+ @Override
+ public boolean isUiContext() {
+ return mBase.isUiContext();
+ }
}
diff --git a/core/java/android/content/pm/DataLoaderParams.java b/core/java/android/content/pm/DataLoaderParams.java
index 99c0907f1844..a791026d44cd 100644
--- a/core/java/android/content/pm/DataLoaderParams.java
+++ b/core/java/android/content/pm/DataLoaderParams.java
@@ -17,12 +17,8 @@
package android.content.pm;
import android.annotation.NonNull;
-import android.annotation.Nullable;
import android.annotation.SystemApi;
import android.content.ComponentName;
-import android.os.ParcelFileDescriptor;
-
-import java.util.Map;
/**
* This class represents the parameters used to configure a Data Loader.
@@ -44,7 +40,7 @@ public class DataLoaderParams {
*/
public static final @NonNull DataLoaderParams forStreaming(@NonNull ComponentName componentName,
@NonNull String arguments) {
- return new DataLoaderParams(DataLoaderType.STREAMING, componentName, arguments, null);
+ return new DataLoaderParams(DataLoaderType.STREAMING, componentName, arguments);
}
/**
@@ -55,29 +51,17 @@ public class DataLoaderParams {
*/
public static final @NonNull DataLoaderParams forIncremental(
@NonNull ComponentName componentName, @NonNull String arguments) {
- return new DataLoaderParams(DataLoaderType.INCREMENTAL, componentName, arguments, null);
+ return new DataLoaderParams(DataLoaderType.INCREMENTAL, componentName, arguments);
}
/** @hide */
public DataLoaderParams(@NonNull @DataLoaderType int type, @NonNull ComponentName componentName,
- @NonNull String arguments, @Nullable Map<String, ParcelFileDescriptor> namedFds) {
+ @NonNull String arguments) {
DataLoaderParamsParcel data = new DataLoaderParamsParcel();
data.type = type;
data.packageName = componentName.getPackageName();
data.className = componentName.getClassName();
data.arguments = arguments;
- if (namedFds == null || namedFds.isEmpty()) {
- data.dynamicArgs = new NamedParcelFileDescriptor[0];
- } else {
- data.dynamicArgs = new NamedParcelFileDescriptor[namedFds.size()];
- int i = 0;
- for (Map.Entry<String, ParcelFileDescriptor> namedFd : namedFds.entrySet()) {
- data.dynamicArgs[i] = new NamedParcelFileDescriptor();
- data.dynamicArgs[i].name = namedFd.getKey();
- data.dynamicArgs[i].fd = namedFd.getValue();
- i += 1;
- }
- }
mData = data;
}
diff --git a/core/java/android/content/pm/DataLoaderParamsParcel.aidl b/core/java/android/content/pm/DataLoaderParamsParcel.aidl
index e05843b4d4e9..d40012fd5718 100644
--- a/core/java/android/content/pm/DataLoaderParamsParcel.aidl
+++ b/core/java/android/content/pm/DataLoaderParamsParcel.aidl
@@ -17,7 +17,6 @@
package android.content.pm;
import android.content.pm.DataLoaderType;
-import android.content.pm.NamedParcelFileDescriptor;
/**
* Class for holding data loader configuration parameters.
@@ -28,5 +27,4 @@ parcelable DataLoaderParamsParcel {
@utf8InCpp String packageName;
@utf8InCpp String className;
@utf8InCpp String arguments;
- NamedParcelFileDescriptor[] dynamicArgs;
}
diff --git a/core/java/android/content/pm/PackageParser.java b/core/java/android/content/pm/PackageParser.java
index 20ddba41bda1..1dadbda1918b 100644
--- a/core/java/android/content/pm/PackageParser.java
+++ b/core/java/android/content/pm/PackageParser.java
@@ -1837,6 +1837,12 @@ public class PackageParser {
pkg.coreApp = parser.getAttributeBooleanValue(null, "coreApp", false);
+ final boolean isolatedSplits = sa.getBoolean(
+ com.android.internal.R.styleable.AndroidManifest_isolatedSplits, false);
+ if (isolatedSplits) {
+ pkg.applicationInfo.privateFlags |= ApplicationInfo.PRIVATE_FLAG_ISOLATED_SPLIT_LOADING;
+ }
+
pkg.mCompileSdkVersion = sa.getInteger(
com.android.internal.R.styleable.AndroidManifest_compileSdkVersion, 0);
pkg.applicationInfo.compileSdkVersion = pkg.mCompileSdkVersion;
@@ -1912,10 +1918,6 @@ public class PackageParser {
pkg.applicationInfo.flags |= ApplicationInfo.FLAG_EXTERNAL_STORAGE;
}
- if (sa.getBoolean(com.android.internal.R.styleable.AndroidManifest_isolatedSplits, false)) {
- pkg.applicationInfo.privateFlags |= ApplicationInfo.PRIVATE_FLAG_ISOLATED_SPLIT_LOADING;
- }
-
// Resource boolean are -1, so 1 means we don't know the value.
int supportsSmallScreens = 1;
int supportsNormalScreens = 1;
diff --git a/core/java/android/content/pm/parsing/ParsingPackageImpl.java b/core/java/android/content/pm/parsing/ParsingPackageImpl.java
index 079a47056c24..894ad5584922 100644
--- a/core/java/android/content/pm/parsing/ParsingPackageImpl.java
+++ b/core/java/android/content/pm/parsing/ParsingPackageImpl.java
@@ -433,6 +433,10 @@ public class ParsingPackageImpl implements ParsingPackage, Parcelable {
R.styleable.AndroidManifest_compileSdkVersion, 0));
setCompileSdkVersionCodename(manifestArray.getNonConfigurationString(
R.styleable.AndroidManifest_compileSdkVersionCodename, 0));
+
+ setIsolatedSplitLoading(manifestArray.getBoolean(
+ R.styleable.AndroidManifest_isolatedSplits, false));
+
}
}
diff --git a/core/java/android/content/pm/parsing/ParsingPackageUtils.java b/core/java/android/content/pm/parsing/ParsingPackageUtils.java
index ec771286d980..e90ccdffa8a8 100644
--- a/core/java/android/content/pm/parsing/ParsingPackageUtils.java
+++ b/core/java/android/content/pm/parsing/ParsingPackageUtils.java
@@ -386,15 +386,14 @@ public class ParsingPackageUtils {
return input.error(PackageManager.INSTALL_PARSE_FAILED_BAD_PACKAGE_NAME);
}
- TypedArray manifestArray = res.obtainAttributes(parser, R.styleable.AndroidManifest);
+ final TypedArray manifestArray = res.obtainAttributes(parser, R.styleable.AndroidManifest);
try {
- boolean isCoreApp = parser.getAttributeBooleanValue(null, "coreApp", false);
-
- ParsingPackage pkg = mCallback.startParsingPackage(pkgName, apkPath, codePath,
- manifestArray, isCoreApp);
-
- ParseResult<ParsingPackage> result = parseBaseApkTags(input, pkg, manifestArray,
- res, parser, flags);
+ final boolean isCoreApp =
+ parser.getAttributeBooleanValue(null, "coreApp", false);
+ final ParsingPackage pkg = mCallback.startParsingPackage(
+ pkgName, apkPath, codePath, manifestArray, isCoreApp);
+ final ParseResult<ParsingPackage> result =
+ parseBaseApkTags(input, pkg, manifestArray, res, parser, flags);
if (result.isError()) {
return result;
}
@@ -620,14 +619,12 @@ public class ParsingPackageUtils {
return sharedUserResult;
}
- pkg.setInstallLocation(anInt(PackageParser.PARSE_DEFAULT_INSTALL_LOCATION,
+ pkg.setInstallLocation(anInteger(PackageParser.PARSE_DEFAULT_INSTALL_LOCATION,
R.styleable.AndroidManifest_installLocation, sa))
- .setTargetSandboxVersion(anInt(PackageParser.PARSE_DEFAULT_TARGET_SANDBOX,
+ .setTargetSandboxVersion(anInteger(PackageParser.PARSE_DEFAULT_TARGET_SANDBOX,
R.styleable.AndroidManifest_targetSandboxVersion, sa))
/* Set the global "on SD card" flag */
- .setExternalStorage((flags & PackageParser.PARSE_EXTERNAL_STORAGE) != 0)
- .setIsolatedSplitLoading(
- bool(false, R.styleable.AndroidManifest_isolatedSplits, sa));
+ .setExternalStorage((flags & PackageParser.PARSE_EXTERNAL_STORAGE) != 0);
boolean foundApp = false;
final int depth = parser.getDepth();
@@ -2658,6 +2655,10 @@ public class ParsingPackageUtils {
return sa.getInt(attribute, defaultValue);
}
+ private static int anInteger(int defaultValue, @StyleableRes int attribute, TypedArray sa) {
+ return sa.getInteger(attribute, defaultValue);
+ }
+
private static int anInt(@StyleableRes int attribute, TypedArray sa) {
return sa.getInt(attribute, 0);
}
@@ -2688,6 +2689,6 @@ public class ParsingPackageUtils {
boolean hasFeature(String feature);
ParsingPackage startParsingPackage(String packageName, String baseCodePath, String codePath,
- TypedArray manifestArray, boolean isCoreApp);
+ @NonNull TypedArray manifestArray, boolean isCoreApp);
}
}
diff --git a/core/java/android/hardware/biometrics/BiometricConstants.java b/core/java/android/hardware/biometrics/BiometricConstants.java
index add67aa436c6..8e3f809e4f88 100644
--- a/core/java/android/hardware/biometrics/BiometricConstants.java
+++ b/core/java/android/hardware/biometrics/BiometricConstants.java
@@ -204,4 +204,18 @@ public interface BiometricConstants {
* @hide
*/
int BIOMETRIC_ACQUIRED_VENDOR_BASE = 1000;
+
+ //
+ // Internal messages.
+ //
+
+ /**
+ * See {@link BiometricPrompt.Builder#setReceiveSystemEvents(boolean)}. This message is sent
+ * immediately when the user cancels authentication for example by tapping the back button or
+ * tapping the scrim. This is before {@link #BIOMETRIC_ERROR_USER_CANCELED}, which is sent when
+ * dismissal animation completes.
+ * @hide
+ */
+ int BIOMETRIC_SYSTEM_EVENT_EARLY_USER_CANCEL = 1;
+
}
diff --git a/core/java/android/hardware/biometrics/BiometricPrompt.java b/core/java/android/hardware/biometrics/BiometricPrompt.java
index a3aa258fec35..5af7cef3e2b4 100644
--- a/core/java/android/hardware/biometrics/BiometricPrompt.java
+++ b/core/java/android/hardware/biometrics/BiometricPrompt.java
@@ -63,6 +63,7 @@ public class BiometricPrompt implements BiometricAuthenticator, BiometricConstan
/**
* @hide
*/
+ @RequiresPermission(USE_BIOMETRIC_INTERNAL)
public static final String KEY_USE_DEFAULT_TITLE = "use_default_title";
/**
* @hide
@@ -75,14 +76,17 @@ public class BiometricPrompt implements BiometricAuthenticator, BiometricConstan
/**
* @hide
*/
+ @RequiresPermission(USE_BIOMETRIC_INTERNAL)
public static final String KEY_DEVICE_CREDENTIAL_TITLE = "device_credential_title";
/**
* @hide
*/
+ @RequiresPermission(USE_BIOMETRIC_INTERNAL)
public static final String KEY_DEVICE_CREDENTIAL_SUBTITLE = "device_credential_subtitle";
/**
* @hide
*/
+ @RequiresPermission(USE_BIOMETRIC_INTERNAL)
public static final String KEY_DEVICE_CREDENTIAL_DESCRIPTION = "device_credential_description";
/**
* @hide
@@ -106,7 +110,15 @@ public class BiometricPrompt implements BiometricAuthenticator, BiometricConstan
* If this is set, check the Device Policy Manager for allowed biometrics.
* @hide
*/
+ @RequiresPermission(USE_BIOMETRIC_INTERNAL)
public static final String EXTRA_DISALLOW_BIOMETRICS_IF_POLICY_EXISTS = "check_dpm";
+ /**
+ * Request to receive system events, such as back gesture/button. See
+ * {@link AuthenticationCallback#onSystemEvent(int)}
+ * @hide
+ */
+ @RequiresPermission(USE_BIOMETRIC_INTERNAL)
+ public static final String KEY_RECEIVE_SYSTEM_EVENTS = "receive_system_events";
/**
* Error/help message will show for this amount of time.
@@ -384,6 +396,18 @@ public class BiometricPrompt implements BiometricAuthenticator, BiometricConstan
}
/**
+ * If set, receive internal events via {@link AuthenticationCallback#onSystemEvent(int)}
+ * @param set
+ * @return This builder.
+ * @hide
+ */
+ @NonNull
+ public Builder setReceiveSystemEvents(boolean set) {
+ mBundle.putBoolean(KEY_RECEIVE_SYSTEM_EVENTS, set);
+ return this;
+ }
+
+ /**
* Creates a {@link BiometricPrompt}.
*
* @return An instance of {@link BiometricPrompt}.
@@ -493,6 +517,13 @@ public class BiometricPrompt implements BiometricAuthenticator, BiometricConstan
});
}
}
+
+ @Override
+ public void onSystemEvent(int event) throws RemoteException {
+ mExecutor.execute(() -> {
+ mAuthenticationCallback.onSystemEvent(event);
+ });
+ }
};
private BiometricPrompt(Context context, Bundle bundle,
@@ -732,6 +763,12 @@ public class BiometricPrompt implements BiometricAuthenticator, BiometricConstan
*/
@Override
public void onAuthenticationAcquired(int acquireInfo) {}
+
+ /**
+ * Receiver for internal system events. See {@link Builder#setReceiveSystemEvents(boolean)}
+ * @hide
+ */
+ public void onSystemEvent(int event) {}
}
/**
diff --git a/core/java/android/hardware/biometrics/IBiometricServiceReceiver.aidl b/core/java/android/hardware/biometrics/IBiometricServiceReceiver.aidl
index 1d43aa640b40..b0cddfd3b47f 100644
--- a/core/java/android/hardware/biometrics/IBiometricServiceReceiver.aidl
+++ b/core/java/android/hardware/biometrics/IBiometricServiceReceiver.aidl
@@ -30,4 +30,6 @@ oneway interface IBiometricServiceReceiver {
void onAcquired(int acquiredInfo, String message);
// Notifies that the SystemUI dialog has been dismissed.
void onDialogDismissed(int reason);
+ // Notifies the client that an internal event, e.g. back button has occurred.
+ void onSystemEvent(int event);
}
diff --git a/core/java/android/hardware/biometrics/IBiometricServiceReceiverInternal.aidl b/core/java/android/hardware/biometrics/IBiometricServiceReceiverInternal.aidl
index e7219caf6cd8..e57abd548057 100644
--- a/core/java/android/hardware/biometrics/IBiometricServiceReceiverInternal.aidl
+++ b/core/java/android/hardware/biometrics/IBiometricServiceReceiverInternal.aidl
@@ -42,4 +42,6 @@ oneway interface IBiometricServiceReceiverInternal {
void onTryAgainPressed();
// Notifies that the user has pressed the "use password" button on SystemUI
void onDeviceCredentialPressed();
+ // Notifies the client that an internal event, e.g. back button has occurred.
+ void onSystemEvent(int event);
}
diff --git a/core/java/android/hardware/soundtrigger/ConversionUtil.java b/core/java/android/hardware/soundtrigger/ConversionUtil.java
index 3d763e630bd0..425218a63cf7 100644
--- a/core/java/android/hardware/soundtrigger/ConversionUtil.java
+++ b/core/java/android/hardware/soundtrigger/ConversionUtil.java
@@ -106,11 +106,11 @@ class ConversionUtil {
public static SoundModel api2aidlSoundModel(SoundTrigger.SoundModel apiModel) {
SoundModel aidlModel = new SoundModel();
- aidlModel.type = apiModel.type;
- aidlModel.uuid = api2aidlUuid(apiModel.uuid);
- aidlModel.vendorUuid = api2aidlUuid(apiModel.vendorUuid);
- aidlModel.data = byteArrayToSharedMemory(apiModel.data, "SoundTrigger SoundModel");
- aidlModel.dataSize = apiModel.data.length;
+ aidlModel.type = apiModel.getType();
+ aidlModel.uuid = api2aidlUuid(apiModel.getUuid());
+ aidlModel.vendorUuid = api2aidlUuid(apiModel.getVendorUuid());
+ aidlModel.data = byteArrayToSharedMemory(apiModel.getData(), "SoundTrigger SoundModel");
+ aidlModel.dataSize = apiModel.getData().length;
return aidlModel;
}
@@ -122,20 +122,20 @@ class ConversionUtil {
SoundTrigger.KeyphraseSoundModel apiModel) {
PhraseSoundModel aidlModel = new PhraseSoundModel();
aidlModel.common = api2aidlSoundModel(apiModel);
- aidlModel.phrases = new Phrase[apiModel.keyphrases.length];
- for (int i = 0; i < apiModel.keyphrases.length; ++i) {
- aidlModel.phrases[i] = api2aidlPhrase(apiModel.keyphrases[i]);
+ aidlModel.phrases = new Phrase[apiModel.getKeyphrases().length];
+ for (int i = 0; i < apiModel.getKeyphrases().length; ++i) {
+ aidlModel.phrases[i] = api2aidlPhrase(apiModel.getKeyphrases()[i]);
}
return aidlModel;
}
public static Phrase api2aidlPhrase(SoundTrigger.Keyphrase apiPhrase) {
Phrase aidlPhrase = new Phrase();
- aidlPhrase.id = apiPhrase.id;
- aidlPhrase.recognitionModes = api2aidlRecognitionModes(apiPhrase.recognitionModes);
- aidlPhrase.users = Arrays.copyOf(apiPhrase.users, apiPhrase.users.length);
- aidlPhrase.locale = apiPhrase.locale.toLanguageTag();
- aidlPhrase.text = apiPhrase.text;
+ aidlPhrase.id = apiPhrase.getId();
+ aidlPhrase.recognitionModes = api2aidlRecognitionModes(apiPhrase.getRecognitionModes());
+ aidlPhrase.users = Arrays.copyOf(apiPhrase.getUsers(), apiPhrase.getUsers().length);
+ aidlPhrase.locale = apiPhrase.getLocale().toLanguageTag();
+ aidlPhrase.text = apiPhrase.getText();
return aidlPhrase;
}
diff --git a/core/java/android/hardware/soundtrigger/SoundTrigger.java b/core/java/android/hardware/soundtrigger/SoundTrigger.java
index a74871d29041..98c4f618be18 100644
--- a/core/java/android/hardware/soundtrigger/SoundTrigger.java
+++ b/core/java/android/hardware/soundtrigger/SoundTrigger.java
@@ -104,32 +104,89 @@ public class SoundTrigger {
/**
* If set the underlying module supports AEC.
- * Describes bit field {@link ModuleProperties#audioCapabilities}
+ * Describes bit field {@link ModuleProperties#mAudioCapabilities}
*/
public static final int AUDIO_CAPABILITY_ECHO_CANCELLATION = 0x1;
/**
* If set, the underlying module supports noise suppression.
- * Describes bit field {@link ModuleProperties#audioCapabilities}
+ * Describes bit field {@link ModuleProperties#mAudioCapabilities}
*/
public static final int AUDIO_CAPABILITY_NOISE_SUPPRESSION = 0x2;
+ private final int mId;
+ @NonNull
+ private final String mImplementor;
+ @NonNull
+ private final String mDescription;
+ @NonNull
+ private final UUID mUuid;
+ private final int mVersion;
+ @NonNull
+ private final String mSupportedModelArch;
+ private final int mMaxSoundModels;
+ private final int mMaxKeyphrases;
+ private final int mMaxUsers;
+ @RecognitionModes
+ private final int mRecognitionModes;
+ private final boolean mSupportsCaptureTransition;
+ private final int mMaxBufferMillis;
+ private final boolean mSupportsConcurrentCapture;
+ private final int mPowerConsumptionMw;
+ private final boolean mReturnsTriggerInEvent;
+ @AudioCapabilities
+ private final int mAudioCapabilities;
+
+ ModuleProperties(int id, @NonNull String implementor, @NonNull String description,
+ @NonNull String uuid, int version, @NonNull String supportedModelArch,
+ int maxSoundModels, int maxKeyphrases, int maxUsers,
+ @RecognitionModes int recognitionModes, boolean supportsCaptureTransition,
+ int maxBufferMs, boolean supportsConcurrentCapture, int powerConsumptionMw,
+ boolean returnsTriggerInEvent, int audioCapabilities) {
+ this.mId = id;
+ this.mImplementor = requireNonNull(implementor);
+ this.mDescription = requireNonNull(description);
+ this.mUuid = UUID.fromString(requireNonNull(uuid));
+ this.mVersion = version;
+ this.mSupportedModelArch = requireNonNull(supportedModelArch);
+ this.mMaxSoundModels = maxSoundModels;
+ this.mMaxKeyphrases = maxKeyphrases;
+ this.mMaxUsers = maxUsers;
+ this.mRecognitionModes = recognitionModes;
+ this.mSupportsCaptureTransition = supportsCaptureTransition;
+ this.mMaxBufferMillis = maxBufferMs;
+ this.mSupportsConcurrentCapture = supportsConcurrentCapture;
+ this.mPowerConsumptionMw = powerConsumptionMw;
+ this.mReturnsTriggerInEvent = returnsTriggerInEvent;
+ this.mAudioCapabilities = audioCapabilities;
+ }
+
/** Unique module ID provided by the native service */
- public final int id;
+ public int getId() {
+ return mId;
+ }
/** human readable voice detection engine implementor */
@NonNull
- public final String implementor;
+ public String getImplementor() {
+ return mImplementor;
+ }
/** human readable voice detection engine description */
@NonNull
- public final String description;
+ public String getDescription() {
+ return mDescription;
+ }
/** Unique voice engine Id (changes with each version) */
@NonNull
- public final UUID uuid;
+ public UUID getUuid() {
+ return mUuid;
+ }
/** Voice detection engine version */
- public final int version;
+ public int getVersion() {
+ return mVersion;
+ }
/**
* String naming the architecture used for running the supported models.
@@ -137,66 +194,64 @@ public class SoundTrigger {
* architecture used)
*/
@NonNull
- public final String supportedModelArch;
+ public String getSupportedModelArch() {
+ return mSupportedModelArch;
+ }
/** Maximum number of active sound models */
- public final int maxSoundModels;
+ public int getMaxSoundModels() {
+ return mMaxSoundModels;
+ }
/** Maximum number of key phrases */
- public final int maxKeyphrases;
+ public int getMaxKeyphrases() {
+ return mMaxKeyphrases;
+ }
/** Maximum number of users per key phrase */
- public final int maxUsers;
+ public int getMaxUsers() {
+ return mMaxUsers;
+ }
/** Supported recognition modes (bit field, RECOGNITION_MODE_VOICE_TRIGGER ...) */
@RecognitionModes
- public final int recognitionModes;
+ public int getRecognitionModes() {
+ return mRecognitionModes;
+ }
/** Supports seamless transition to capture mode after recognition */
- public final boolean supportsCaptureTransition;
+ public boolean isCaptureTransitionSupported() {
+ return mSupportsCaptureTransition;
+ }
/** Maximum buffering capacity in ms if supportsCaptureTransition() is true */
- public final int maxBufferMs;
+ public int getMaxBufferMillis() {
+ return mMaxBufferMillis;
+ }
/** Supports capture by other use cases while detection is active */
- public final boolean supportsConcurrentCapture;
+ public boolean isConcurrentCaptureSupported() {
+ return mSupportsConcurrentCapture;
+ }
/** Rated power consumption when detection is active with TDB silence/sound/speech ratio */
- public final int powerConsumptionMw;
+ public int getPowerConsumptionMw() {
+ return mPowerConsumptionMw;
+ }
/** Returns the trigger (key phrase) capture in the binary data of the
* recognition callback event */
- public final boolean returnsTriggerInEvent;
+ public boolean isTriggerReturnedInEvent() {
+ return mReturnsTriggerInEvent;
+ }
/**
* Bit field encoding of the AudioCapabilities
* supported by the firmware.
*/
@AudioCapabilities
- public final int audioCapabilities;
-
- ModuleProperties(int id, @NonNull String implementor, @NonNull String description,
- @NonNull String uuid, int version, @NonNull String supportedModelArch,
- int maxSoundModels, int maxKeyphrases, int maxUsers,
- @RecognitionModes int recognitionModes, boolean supportsCaptureTransition,
- int maxBufferMs, boolean supportsConcurrentCapture, int powerConsumptionMw,
- boolean returnsTriggerInEvent, int audioCapabilities) {
- this.id = id;
- this.implementor = requireNonNull(implementor);
- this.description = requireNonNull(description);
- this.uuid = UUID.fromString(requireNonNull(uuid));
- this.version = version;
- this.supportedModelArch = requireNonNull(supportedModelArch);
- this.maxSoundModels = maxSoundModels;
- this.maxKeyphrases = maxKeyphrases;
- this.maxUsers = maxUsers;
- this.recognitionModes = recognitionModes;
- this.supportsCaptureTransition = supportsCaptureTransition;
- this.maxBufferMs = maxBufferMs;
- this.supportsConcurrentCapture = supportsConcurrentCapture;
- this.powerConsumptionMw = powerConsumptionMw;
- this.returnsTriggerInEvent = returnsTriggerInEvent;
- this.audioCapabilities = audioCapabilities;
+ public int getAudioCapabilities() {
+ return mAudioCapabilities;
}
public static final @android.annotation.NonNull Parcelable.Creator<ModuleProperties> CREATOR
@@ -235,22 +290,22 @@ public class SoundTrigger {
@Override
public void writeToParcel(Parcel dest, int flags) {
- dest.writeInt(id);
- dest.writeString(implementor);
- dest.writeString(description);
- dest.writeString(uuid.toString());
- dest.writeInt(version);
- dest.writeString(supportedModelArch);
- dest.writeInt(maxSoundModels);
- dest.writeInt(maxKeyphrases);
- dest.writeInt(maxUsers);
- dest.writeInt(recognitionModes);
- dest.writeByte((byte) (supportsCaptureTransition ? 1 : 0));
- dest.writeInt(maxBufferMs);
- dest.writeByte((byte) (supportsConcurrentCapture ? 1 : 0));
- dest.writeInt(powerConsumptionMw);
- dest.writeByte((byte) (returnsTriggerInEvent ? 1 : 0));
- dest.writeInt(audioCapabilities);
+ dest.writeInt(getId());
+ dest.writeString(getImplementor());
+ dest.writeString(getDescription());
+ dest.writeString(getUuid().toString());
+ dest.writeInt(getVersion());
+ dest.writeString(getSupportedModelArch());
+ dest.writeInt(getMaxSoundModels());
+ dest.writeInt(getMaxKeyphrases());
+ dest.writeInt(getMaxUsers());
+ dest.writeInt(getRecognitionModes());
+ dest.writeByte((byte) (isCaptureTransitionSupported() ? 1 : 0));
+ dest.writeInt(getMaxBufferMillis());
+ dest.writeByte((byte) (isConcurrentCaptureSupported() ? 1 : 0));
+ dest.writeInt(getPowerConsumptionMw());
+ dest.writeByte((byte) (isTriggerReturnedInEvent() ? 1 : 0));
+ dest.writeInt(getAudioCapabilities());
}
@Override
@@ -260,16 +315,17 @@ public class SoundTrigger {
@Override
public String toString() {
- return "ModuleProperties [id=" + id + ", implementor=" + implementor + ", description="
- + description + ", uuid=" + uuid + ", version=" + version
- + " , supportedModelArch=" + supportedModelArch + ", maxSoundModels="
- + maxSoundModels + ", maxKeyphrases=" + maxKeyphrases + ", maxUsers="
- + maxUsers + ", recognitionModes=" + recognitionModes
- + ", supportsCaptureTransition=" + supportsCaptureTransition + ", maxBufferMs="
- + maxBufferMs + ", supportsConcurrentCapture=" + supportsConcurrentCapture
- + ", powerConsumptionMw=" + powerConsumptionMw
- + ", returnsTriggerInEvent=" + returnsTriggerInEvent
- + ", audioCapabilities=" + audioCapabilities + "]";
+ return "ModuleProperties [id=" + getId() + ", implementor=" + getImplementor()
+ + ", description=" + getDescription() + ", uuid=" + getUuid()
+ + ", version=" + getVersion() + " , supportedModelArch="
+ + getSupportedModelArch() + ", maxSoundModels=" + getMaxSoundModels()
+ + ", maxKeyphrases=" + getMaxKeyphrases() + ", maxUsers=" + getMaxUsers()
+ + ", recognitionModes=" + getRecognitionModes() + ", supportsCaptureTransition="
+ + isCaptureTransitionSupported() + ", maxBufferMs=" + getMaxBufferMillis()
+ + ", supportsConcurrentCapture=" + isConcurrentCaptureSupported()
+ + ", powerConsumptionMw=" + getPowerConsumptionMw()
+ + ", returnsTriggerInEvent=" + isTriggerReturnedInEvent()
+ + ", audioCapabilities=" + getAudioCapabilities() + "]";
}
}
@@ -305,44 +361,64 @@ public class SoundTrigger {
*/
public static final int TYPE_GENERIC_SOUND = 1;
+ @NonNull
+ private final UUID mUuid;
+ @SoundModelType
+ private final int mType;
+ @NonNull
+ private final UUID mVendorUuid;
+ private final int mVersion;
+ @NonNull
+ private final byte[] mData;
+
+ /** @hide */
+ public SoundModel(@NonNull UUID uuid, @Nullable UUID vendorUuid, @SoundModelType int type,
+ @Nullable byte[] data, int version) {
+ this.mUuid = requireNonNull(uuid);
+ this.mVendorUuid = vendorUuid != null ? vendorUuid : new UUID(0, 0);
+ this.mType = type;
+ this.mVersion = version;
+ this.mData = data != null ? data : new byte[0];
+ }
+
/** Unique sound model identifier */
@NonNull
- public final UUID uuid;
+ public UUID getUuid() {
+ return mUuid;
+ }
/** Sound model type (e.g. TYPE_KEYPHRASE); */
@SoundModelType
- public final int type;
+ public int getType() {
+ return mType;
+ }
/** Unique sound model vendor identifier */
@NonNull
- public final UUID vendorUuid;
+ public UUID getVendorUuid() {
+ return mVendorUuid;
+ }
/** vendor specific version number of the model */
- public final int version;
+ public int getVersion() {
+ return mVersion;
+ }
/** Opaque data. For use by vendor implementation and enrollment application */
@NonNull
- public final byte[] data;
-
- /** @hide */
- public SoundModel(@NonNull UUID uuid, @Nullable UUID vendorUuid, @SoundModelType int type,
- @Nullable byte[] data, int version) {
- this.uuid = requireNonNull(uuid);
- this.vendorUuid = vendorUuid != null ? vendorUuid : new UUID(0, 0);
- this.type = type;
- this.version = version;
- this.data = data != null ? data : new byte[0];
+ public byte[] getData() {
+ return mData;
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
- result = prime * result + version;
- result = prime * result + Arrays.hashCode(data);
- result = prime * result + type;
- result = prime * result + ((uuid == null) ? 0 : uuid.hashCode());
- result = prime * result + ((vendorUuid == null) ? 0 : vendorUuid.hashCode());
+ result = prime * result + getVersion();
+ result = prime * result + Arrays.hashCode(getData());
+ result = prime * result + getType();
+ result = prime * result + ((getUuid() == null) ? 0 : getUuid().hashCode());
+ result = prime * result + ((getVendorUuid() == null) ? 0 : getVendorUuid().hashCode());
return result;
}
@@ -358,27 +434,27 @@ public class SoundTrigger {
return false;
}
SoundModel other = (SoundModel) obj;
- if (type != other.type) {
+ if (getType() != other.getType()) {
return false;
}
- if (uuid == null) {
- if (other.uuid != null) {
+ if (getUuid() == null) {
+ if (other.getUuid() != null) {
return false;
}
- } else if (!uuid.equals(other.uuid)) {
+ } else if (!getUuid().equals(other.getUuid())) {
return false;
}
- if (vendorUuid == null) {
- if (other.vendorUuid != null) {
+ if (getVendorUuid() == null) {
+ if (other.getVendorUuid() != null) {
return false;
}
- } else if (!vendorUuid.equals(other.vendorUuid)) {
+ } else if (!getVendorUuid().equals(other.getVendorUuid())) {
return false;
}
- if (!Arrays.equals(data, other.data)) {
+ if (!Arrays.equals(getData(), other.getData())) {
return false;
}
- if (version != other.version) {
+ if (getVersion() != other.getVersion()) {
return false;
}
return true;
@@ -390,8 +466,41 @@ public class SoundTrigger {
* {@link KeyphraseSoundModel}
*/
public static final class Keyphrase implements Parcelable {
+
+ private final int mId;
+ @RecognitionModes
+ private final int mRecognitionModes;
+ @NonNull
+ private final Locale mLocale;
+ @NonNull
+ private final String mText;
+ @NonNull
+ private final int[] mUsers;
+
+ /**
+ * Constructor for Keyphrase describes a key phrase that can be detected by a
+ * {@link KeyphraseSoundModel}
+ *
+ * @param id Unique keyphrase identifier for this keyphrase
+ * @param recognitionModes Bit field representation of recognition modes this keyphrase
+ * supports
+ * @param locale Locale of the keyphrase
+ * @param text Key phrase text
+ * @param users Users this key phrase has been trained for.
+ */
+ public Keyphrase(int id, @RecognitionModes int recognitionModes, @NonNull Locale locale,
+ @NonNull String text, @Nullable int[] users) {
+ this.mId = id;
+ this.mRecognitionModes = recognitionModes;
+ this.mLocale = requireNonNull(locale);
+ this.mText = requireNonNull(text);
+ this.mUsers = users != null ? users : new int[0];
+ }
+
/** Unique identifier for this keyphrase */
- public final int id;
+ public int getId() {
+ return mId;
+ }
/**
* Recognition modes supported for this key phrase in the model
@@ -402,41 +511,29 @@ public class SoundTrigger {
* @see #RECOGNITION_MODE_GENERIC
*/
@RecognitionModes
- public final int recognitionModes;
+ public int getRecognitionModes() {
+ return mRecognitionModes;
+ }
/** Locale of the keyphrase. */
@NonNull
- public final Locale locale;
+ public Locale getLocale() {
+ return mLocale;
+ }
/** Key phrase text */
@NonNull
- public final String text;
+ public String getText() {
+ return mText;
+ }
/**
* Users this key phrase has been trained for. countains sound trigger specific user IDs
* derived from system user IDs {@link android.os.UserHandle#getIdentifier()}.
*/
@NonNull
- public final int[] users;
-
- /**
- * Constructor for Keyphrase describes a key phrase that can be detected by a
- * {@link KeyphraseSoundModel}
- *
- * @param id Unique keyphrase identifier for this keyphrase
- * @param recognitionModes Bit field representation of recognition modes this keyphrase
- * supports
- * @param locale Locale of the keyphrase
- * @param text Key phrase text
- * @param users Users this key phrase has been trained for.
- */
- public Keyphrase(int id, @RecognitionModes int recognitionModes, @NonNull Locale locale,
- @NonNull String text, @Nullable int[] users) {
- this.id = id;
- this.recognitionModes = recognitionModes;
- this.locale = requireNonNull(locale);
- this.text = requireNonNull(text);
- this.users = users != null ? users : new int[0];
+ public int[] getUsers() {
+ return mUsers;
}
public static final @NonNull Parcelable.Creator<Keyphrase> CREATOR =
@@ -472,13 +569,13 @@ public class SoundTrigger {
@Override
public void writeToParcel(@NonNull Parcel dest, int flags) {
- dest.writeInt(id);
- dest.writeInt(recognitionModes);
- dest.writeString(locale.toLanguageTag());
- dest.writeString(text);
- if (users != null) {
- dest.writeInt(users.length);
- dest.writeIntArray(users);
+ dest.writeInt(getId());
+ dest.writeInt(getRecognitionModes());
+ dest.writeString(getLocale().toLanguageTag());
+ dest.writeString(getText());
+ if (getUsers() != null) {
+ dest.writeInt(getUsers().length);
+ dest.writeIntArray(getUsers());
} else {
dest.writeInt(-1);
}
@@ -494,11 +591,11 @@ public class SoundTrigger {
public int hashCode() {
final int prime = 31;
int result = 1;
- result = prime * result + ((text == null) ? 0 : text.hashCode());
- result = prime * result + id;
- result = prime * result + ((locale == null) ? 0 : locale.hashCode());
- result = prime * result + recognitionModes;
- result = prime * result + Arrays.hashCode(users);
+ result = prime * result + ((getText() == null) ? 0 : getText().hashCode());
+ result = prime * result + getId();
+ result = prime * result + ((getLocale() == null) ? 0 : getLocale().hashCode());
+ result = prime * result + getRecognitionModes();
+ result = prime * result + Arrays.hashCode(getUsers());
return result;
}
@@ -514,27 +611,27 @@ public class SoundTrigger {
return false;
}
Keyphrase other = (Keyphrase) obj;
- if (text == null) {
- if (other.text != null) {
+ if (getText() == null) {
+ if (other.getText() != null) {
return false;
}
- } else if (!text.equals(other.text)) {
+ } else if (!getText().equals(other.getText())) {
return false;
}
- if (id != other.id) {
+ if (getId() != other.getId()) {
return false;
}
- if (locale == null) {
- if (other.locale != null) {
+ if (getLocale() == null) {
+ if (other.getLocale() != null) {
return false;
}
- } else if (!locale.equals(other.locale)) {
+ } else if (!getLocale().equals(other.getLocale())) {
return false;
}
- if (recognitionModes != other.recognitionModes) {
+ if (getRecognitionModes() != other.getRecognitionModes()) {
return false;
}
- if (!Arrays.equals(users, other.users)) {
+ if (!Arrays.equals(getUsers(), other.getUsers())) {
return false;
}
return true;
@@ -542,9 +639,9 @@ public class SoundTrigger {
@Override
public String toString() {
- return "Keyphrase [id=" + id + ", recognitionModes=" + recognitionModes
- + ", locale=" + locale.toLanguageTag() + ", text=" + text
- + ", users=" + Arrays.toString(users) + "]";
+ return "Keyphrase [id=" + getId() + ", recognitionModes=" + getRecognitionModes()
+ + ", locale=" + getLocale().toLanguageTag() + ", text=" + getText()
+ + ", users=" + Arrays.toString(getUsers()) + "]";
}
}
@@ -554,15 +651,15 @@ public class SoundTrigger {
* and the list of corresponding {@link Keyphrase} descriptors.
*/
public static final class KeyphraseSoundModel extends SoundModel implements Parcelable {
- /** Key phrases in this sound model */
+
@NonNull
- public final Keyphrase[] keyphrases; // keyword phrases in model
+ private final Keyphrase[] mKeyphrases;
public KeyphraseSoundModel(
@NonNull UUID uuid, @NonNull UUID vendorUuid, @Nullable byte[] data,
@Nullable Keyphrase[] keyphrases, int version) {
super(uuid, vendorUuid, TYPE_KEYPHRASE, data, version);
- this.keyphrases = keyphrases != null ? keyphrases : new Keyphrase[0];
+ this.mKeyphrases = keyphrases != null ? keyphrases : new Keyphrase[0];
}
public KeyphraseSoundModel(@NonNull UUID uuid, @NonNull UUID vendorUuid,
@@ -570,6 +667,12 @@ public class SoundTrigger {
this(uuid, vendorUuid, data, keyphrases, -1);
}
+ /** Key phrases in this sound model */
+ @NonNull
+ public Keyphrase[] getKeyphrases() {
+ return mKeyphrases;
+ }
+
public static final @NonNull Parcelable.Creator<KeyphraseSoundModel> CREATOR =
new Parcelable.Creator<KeyphraseSoundModel>() {
@NonNull
@@ -608,32 +711,32 @@ public class SoundTrigger {
@Override
public void writeToParcel(@NonNull Parcel dest, int flags) {
- dest.writeString(uuid.toString());
- if (vendorUuid == null) {
+ dest.writeString(getUuid().toString());
+ if (getVendorUuid() == null) {
dest.writeInt(-1);
} else {
- dest.writeInt(vendorUuid.toString().length());
- dest.writeString(vendorUuid.toString());
+ dest.writeInt(getVendorUuid().toString().length());
+ dest.writeString(getVendorUuid().toString());
}
- dest.writeInt(version);
- dest.writeBlob(data);
- dest.writeTypedArray(keyphrases, flags);
+ dest.writeInt(getVersion());
+ dest.writeBlob(getData());
+ dest.writeTypedArray(getKeyphrases(), flags);
}
@Override
public String toString() {
- return "KeyphraseSoundModel [keyphrases=" + Arrays.toString(keyphrases)
- + ", uuid=" + uuid + ", vendorUuid=" + vendorUuid
- + ", type=" + type
- + ", data=" + (data == null ? 0 : data.length)
- + ", version=" + version + "]";
+ return "KeyphraseSoundModel [keyphrases=" + Arrays.toString(getKeyphrases())
+ + ", uuid=" + getUuid() + ", vendorUuid=" + getVendorUuid()
+ + ", type=" + getType()
+ + ", data=" + (getData() == null ? 0 : getData().length)
+ + ", version=" + getVersion() + "]";
}
@Override
public int hashCode() {
final int prime = 31;
int result = super.hashCode();
- result = prime * result + Arrays.hashCode(keyphrases);
+ result = prime * result + Arrays.hashCode(getKeyphrases());
return result;
}
@@ -649,7 +752,7 @@ public class SoundTrigger {
return false;
}
KeyphraseSoundModel other = (KeyphraseSoundModel) obj;
- if (!Arrays.equals(keyphrases, other.keyphrases)) {
+ if (!Arrays.equals(getKeyphrases(), other.getKeyphrases())) {
return false;
}
return true;
@@ -706,23 +809,23 @@ public class SoundTrigger {
@Override
public void writeToParcel(Parcel dest, int flags) {
- dest.writeString(uuid.toString());
- if (vendorUuid == null) {
+ dest.writeString(getUuid().toString());
+ if (getVendorUuid() == null) {
dest.writeInt(-1);
} else {
- dest.writeInt(vendorUuid.toString().length());
- dest.writeString(vendorUuid.toString());
+ dest.writeInt(getVendorUuid().toString().length());
+ dest.writeString(getVendorUuid().toString());
}
- dest.writeBlob(data);
- dest.writeInt(version);
+ dest.writeBlob(getData());
+ dest.writeInt(getVersion());
}
@Override
public String toString() {
- return "GenericSoundModel [uuid=" + uuid + ", vendorUuid=" + vendorUuid
- + ", type=" + type
- + ", data=" + (data == null ? 0 : data.length)
- + ", version=" + version + "]";
+ return "GenericSoundModel [uuid=" + getUuid() + ", vendorUuid=" + getVendorUuid()
+ + ", type=" + getType()
+ + ", data=" + (getData() == null ? 0 : getData().length)
+ + ", version=" + getVersion() + "]";
}
}
@@ -1825,7 +1928,7 @@ public class SoundTrigger {
/**
* Get an interface on a hardware module to control sound models and recognition on
* this module.
- * @param moduleId Sound module system identifier {@link ModuleProperties#id}. mandatory.
+ * @param moduleId Sound module system identifier {@link ModuleProperties#mId}. mandatory.
* @param listener {@link StatusListener} interface. Mandatory.
* @param handler the Handler that will receive the callabcks. Can be null if default handler
* is OK.
diff --git a/core/java/android/net/ConnectivityManager.java b/core/java/android/net/ConnectivityManager.java
index 2a323e5ec97d..7332ede0b997 100644
--- a/core/java/android/net/ConnectivityManager.java
+++ b/core/java/android/net/ConnectivityManager.java
@@ -705,6 +705,36 @@ public class ConnectivityManager {
@Deprecated
public static final int TYPE_TEST = 18; // TODO: Remove this once NetworkTypes are unused.
+ /**
+ * @deprecated Use {@link NetworkCapabilities} instead.
+ * @hide
+ */
+ @Deprecated
+ @Retention(RetentionPolicy.SOURCE)
+ @IntDef(prefix = { "TYPE_" }, value = {
+ TYPE_NONE,
+ TYPE_MOBILE,
+ TYPE_WIFI,
+ TYPE_MOBILE_MMS,
+ TYPE_MOBILE_SUPL,
+ TYPE_MOBILE_DUN,
+ TYPE_MOBILE_HIPRI,
+ TYPE_WIMAX,
+ TYPE_BLUETOOTH,
+ TYPE_DUMMY,
+ TYPE_ETHERNET,
+ TYPE_MOBILE_FOTA,
+ TYPE_MOBILE_IMS,
+ TYPE_MOBILE_CBS,
+ TYPE_WIFI_P2P,
+ TYPE_MOBILE_IA,
+ TYPE_MOBILE_EMERGENCY,
+ TYPE_PROXY,
+ TYPE_VPN,
+ TYPE_TEST
+ })
+ public @interface LegacyNetworkType {}
+
// Deprecated constants for return values of startUsingNetworkFeature. They used to live
// in com.android.internal.telephony.PhoneConstants until they were made inaccessible.
private static final int DEPRECATED_PHONE_CONSTANT_APN_ALREADY_ACTIVE = 0;
diff --git a/core/java/android/net/NetworkAgent.java b/core/java/android/net/NetworkAgent.java
index 5c754a1b9733..fe90a8457949 100644
--- a/core/java/android/net/NetworkAgent.java
+++ b/core/java/android/net/NetworkAgent.java
@@ -16,6 +16,8 @@
package android.net;
+import android.annotation.IntDef;
+import android.annotation.IntRange;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.SystemApi;
@@ -32,18 +34,53 @@ import android.util.Log;
import com.android.internal.util.AsyncChannel;
import com.android.internal.util.Protocol;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.time.Duration;
import java.util.ArrayList;
import java.util.Objects;
import java.util.concurrent.atomic.AtomicBoolean;
/**
- * A Utility class for handling for communicating between bearer-specific
+ * A utility class for handling for communicating between bearer-specific
* code and ConnectivityService.
*
+ * An agent manages the life cycle of a network. A network starts its
+ * life cycle when {@link register} is called on NetworkAgent. The network
+ * is then connecting. When full L3 connectivity has been established,
+ * the agent shoud call {@link markConnected} to inform the system that
+ * this network is ready to use. When the network disconnects its life
+ * ends and the agent should call {@link unregister}, at which point the
+ * system will clean up and free resources.
+ * Any reconnection becomes a new logical network, so after a network
+ * is disconnected the agent cannot be used any more. Network providers
+ * should create a new NetworkAgent instance to handle new connections.
+ *
* A bearer may have more than one NetworkAgent if it can simultaneously
* support separate networks (IMS / Internet / MMS Apns on cellular, or
* perhaps connections with different SSID or P2P for Wi-Fi).
*
+ * This class supports methods to start and stop sending keepalive packets.
+ * Keepalive packets are typically sent at periodic intervals over a network
+ * with NAT when there is no other traffic to avoid the network forcefully
+ * closing the connection. NetworkAgents that manage technologies that
+ * have hardware support for keepalive should implement the related
+ * methods to save battery life. NetworkAgent that cannot get support
+ * without waking up the CPU should not, as this would be prohibitive in
+ * terms of battery - these agents should simply not override the related
+ * methods, which results in the implementation returning
+ * {@link SocketKeepalive.ERROR_UNSUPPORTED} as appropriate.
+ *
+ * Keepalive packets need to be sent at relatively frequent intervals
+ * (a few seconds to a few minutes). As the contents of keepalive packets
+ * depend on the current network status, hardware needs to be configured
+ * to send them and has a limited amount of memory to do so. The HAL
+ * formalizes this as slots that an implementation can configure to send
+ * the correct packets. Devices typically have a small number of slots
+ * per radio technology, and the specific number of slots for each
+ * technology is specified in configuration files.
+ * {@see SocketKeepalive} for details.
+ *
* @hide
*/
@SystemApi
@@ -65,7 +102,7 @@ public abstract class NetworkAgent {
private final String LOG_TAG;
private static final boolean DBG = true;
private static final boolean VDBG = false;
- private final ArrayList<Message>mPreConnectedQueue = new ArrayList<Message>();
+ private final ArrayList<Message> mPreConnectedQueue = new ArrayList<Message>();
private volatile long mLastBwRefreshTime = 0;
private static final long BW_REFRESH_MIN_WIN_MS = 500;
private boolean mBandwidthUpdateScheduled = false;
@@ -74,6 +111,8 @@ public abstract class NetworkAgent {
// into the internal API of ConnectivityService.
@NonNull
private NetworkInfo mNetworkInfo;
+ @NonNull
+ private final Object mRegisterLock = new Object();
/**
* The ID of the {@link NetworkProvider} that created this object, or
@@ -158,6 +197,14 @@ public abstract class NetworkAgent {
*/
public static final int VALIDATION_STATUS_NOT_VALID = 2;
+ /** @hide */
+ @Retention(RetentionPolicy.SOURCE)
+ @IntDef(prefix = { "VALIDATION_STATUS_" }, value = {
+ VALIDATION_STATUS_VALID,
+ VALIDATION_STATUS_NOT_VALID
+ })
+ public @interface ValidationStatus {}
+
// TODO: remove.
/** @hide */
public static final int VALID_NETWORK = 1;
@@ -202,7 +249,7 @@ public abstract class NetworkAgent {
* Sent by ConnectivityService to the NetworkAgent to request that the specified packet be sent
* periodically on the given interval.
*
- * arg1 = the slot number of the keepalive to start
+ * arg1 = the hardware slot number of the keepalive to start
* arg2 = interval in seconds
* obj = KeepalivePacketData object describing the data to be sent
*
@@ -214,7 +261,7 @@ public abstract class NetworkAgent {
/**
* Requests that the specified keepalive packet be stopped.
*
- * arg1 = slot number of the keepalive to stop.
+ * arg1 = hardware slot number of the keepalive to stop.
*
* Also used internally by ConnectivityService / KeepaliveTracker, with different semantics.
* @hide
@@ -229,7 +276,7 @@ public abstract class NetworkAgent {
* This is also sent by KeepaliveTracker to the app's {@link SocketKeepalive},
* so that the app's {@link SocketKeepalive.Callback} methods can be called.
*
- * arg1 = slot number of the keepalive
+ * arg1 = hardware slot number of the keepalive
* arg2 = error code
* @hide
*/
@@ -259,7 +306,7 @@ public abstract class NetworkAgent {
* remote site will send ACK packets in response to the keepalive packets, the firmware also
* needs to be configured to properly filter the ACKs to prevent the system from waking up.
* This does not happen with UDP, so this message is TCP-specific.
- * arg1 = slot number of the keepalive to filter for.
+ * arg1 = hardware slot number of the keepalive to filter for.
* obj = the keepalive packet to send repeatedly.
* @hide
*/
@@ -268,7 +315,7 @@ public abstract class NetworkAgent {
/**
* Sent by the KeepaliveTracker to NetworkAgent to remove a packet filter. See
* {@link #CMD_ADD_KEEPALIVE_PACKET_FILTER}.
- * arg1 = slot number of the keepalive packet filter to remove.
+ * arg1 = hardware slot number of the keepalive packet filter to remove.
* @hide
*/
public static final int CMD_REMOVE_KEEPALIVE_PACKET_FILTER = BASE + 17;
@@ -441,7 +488,15 @@ public abstract class NetworkAgent {
+ (msg.arg1 == VALID_NETWORK ? "VALID, " : "INVALID, ")
+ redirectUrl);
}
- onValidationStatus(msg.arg1 /* status */, redirectUrl);
+ Uri uri = null;
+ try {
+ if (null != redirectUrl) {
+ uri = Uri.parse(redirectUrl);
+ }
+ } catch (Exception e) {
+ Log.wtf(LOG_TAG, "Surprising URI : " + redirectUrl, e);
+ }
+ onValidationStatus(msg.arg1 /* status */, uri);
break;
}
case CMD_SAVE_ACCEPT_UNVALIDATED: {
@@ -449,7 +504,8 @@ public abstract class NetworkAgent {
break;
}
case CMD_START_SOCKET_KEEPALIVE: {
- onStartSocketKeepalive(msg.arg1 /* slot */, msg.arg2 /* interval */,
+ onStartSocketKeepalive(msg.arg1 /* slot */,
+ Duration.ofSeconds(msg.arg2) /* interval */,
(KeepalivePacketData) msg.obj /* packet */);
break;
}
@@ -489,19 +545,29 @@ public abstract class NetworkAgent {
/**
* Register this network agent with ConnectivityService.
+ *
+ * This method can only be called once per network agent.
+ *
* @return the Network associated with this network agent (which can also be obtained later
* by calling getNetwork() on this agent).
+ * @throws IllegalStateException thrown by the system server if this network agent is
+ * already registered.
*/
@NonNull
public Network register() {
if (VDBG) log("Registering NetworkAgent");
final ConnectivityManager cm = (ConnectivityManager) mInitialConfiguration.context
.getSystemService(Context.CONNECTIVITY_SERVICE);
- mNetwork = cm.registerNetworkAgent(new Messenger(mHandler),
- new NetworkInfo(mInitialConfiguration.info),
- mInitialConfiguration.properties, mInitialConfiguration.capabilities,
- mInitialConfiguration.score, mInitialConfiguration.config, providerId);
- mInitialConfiguration = null; // All this memory can now be GC'd
+ synchronized (mRegisterLock) {
+ if (mNetwork != null) {
+ throw new IllegalStateException("Agent already registered");
+ }
+ mNetwork = cm.registerNetworkAgent(new Messenger(mHandler),
+ new NetworkInfo(mInitialConfiguration.info),
+ mInitialConfiguration.properties, mInitialConfiguration.capabilities,
+ mInitialConfiguration.score, mInitialConfiguration.config, providerId);
+ mInitialConfiguration = null; // All this memory can now be GC'd
+ }
return mNetwork;
}
@@ -544,18 +610,19 @@ public abstract class NetworkAgent {
* Must be called by the agent when the network's {@link LinkProperties} change.
* @param linkProperties the new LinkProperties.
*/
- public void sendLinkProperties(@NonNull LinkProperties linkProperties) {
+ public final void sendLinkProperties(@NonNull LinkProperties linkProperties) {
Objects.requireNonNull(linkProperties);
queueOrSendMessage(EVENT_NETWORK_PROPERTIES_CHANGED, new LinkProperties(linkProperties));
}
/**
* Inform ConnectivityService that this agent has now connected.
+ * Call {@link #unregister} to disconnect.
*/
- public void setConnected() {
+ public void markConnected() {
if (mIsLegacy) {
throw new UnsupportedOperationException(
- "Legacy agents can't call setConnected.");
+ "Legacy agents can't call markConnected.");
}
mNetworkInfo.setDetailedState(NetworkInfo.DetailedState.CONNECTED, null, null);
queueOrSendMessage(EVENT_NETWORK_INFO_CHANGED, mNetworkInfo);
@@ -569,8 +636,7 @@ public abstract class NetworkAgent {
*/
public void unregister() {
if (mIsLegacy) {
- throw new UnsupportedOperationException(
- "Legacy agents can't call unregister.");
+ throw new UnsupportedOperationException("Legacy agents can't call unregister.");
}
mNetworkInfo.setDetailedState(NetworkInfo.DetailedState.DISCONNECTED, null, null);
queueOrSendMessage(EVENT_NETWORK_INFO_CHANGED, mNetworkInfo);
@@ -626,7 +692,7 @@ public abstract class NetworkAgent {
* @hide TODO: expose something better.
*/
@UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
- public void sendNetworkInfo(NetworkInfo networkInfo) {
+ public final void sendNetworkInfo(NetworkInfo networkInfo) {
if (!mIsLegacy) {
throw new UnsupportedOperationException("Only legacy agents can call sendNetworkInfo.");
}
@@ -637,7 +703,7 @@ public abstract class NetworkAgent {
* Must be called by the agent when the network's {@link NetworkCapabilities} change.
* @param networkCapabilities the new NetworkCapabilities.
*/
- public void sendNetworkCapabilities(@NonNull NetworkCapabilities networkCapabilities) {
+ public final void sendNetworkCapabilities(@NonNull NetworkCapabilities networkCapabilities) {
Objects.requireNonNull(networkCapabilities);
mBandwidthUpdatePending.set(false);
mLastBwRefreshTime = System.currentTimeMillis();
@@ -647,9 +713,10 @@ public abstract class NetworkAgent {
/**
* Must be called by the agent to update the score of this network.
- * @param score the new score.
+ *
+ * @param score the new score, between 0 and 99.
*/
- public void sendNetworkScore(int score) {
+ public final void sendNetworkScore(@IntRange(from = 0, to = 99) int score) {
if (score < 0) {
throw new IllegalArgumentException("Score must be >= 0");
}
@@ -733,15 +800,15 @@ public abstract class NetworkAgent {
* {@code VALIDATION_STATUS_VALID} if Internet connectivity was validated,
* {@code VALIDATION_STATUS_NOT_VALID} if Internet connectivity was not validated.
*
- * This may be called multiple times as network status changes, or if there are multiple
- * subsequent attempts to validate connectivity that fail.
+ * This is guaranteed to be called again when the network status changes, but the system
+ * may also call this multiple times even if the status does not change.
*
* @param status one of {@code VALIDATION_STATUS_VALID} or {@code VALIDATION_STATUS_NOT_VALID}.
- * @param redirectUrl If Internet connectivity is being redirected (e.g., on a captive portal),
+ * @param redirectUri If Internet connectivity is being redirected (e.g., on a captive portal),
* this is the destination the probes are being redirected to, otherwise {@code null}.
*/
- public void onValidationStatus(int status, @Nullable String redirectUrl) {
- networkStatus(status, redirectUrl);
+ public void onValidationStatus(@ValidationStatus int status, @Nullable Uri redirectUri) {
+ networkStatus(status, redirectUri.toString());
}
/** @hide TODO delete once subclasses have moved to onValidationStatus */
protected void networkStatus(int status, String redirectUrl) {
@@ -767,13 +834,25 @@ public abstract class NetworkAgent {
* Requests that the network hardware send the specified packet at the specified interval.
*
* @param slot the hardware slot on which to start the keepalive.
- * @param intervalSeconds the interval between packets
+ * @param interval the interval between packets, between 10 and 3600. Note that this API
+ * does not support sub-second precision and will round off the request.
* @param packet the packet to send.
*/
- public void onStartSocketKeepalive(int slot, int intervalSeconds,
+ // seconds is from SocketKeepalive.MIN_INTERVAL_SEC to MAX_INTERVAL_SEC, but these should
+ // not be exposed as constants because they may change in the future (API guideline 4.8)
+ // and should have getters if exposed at all. Getters can't be used in the annotation,
+ // so the values unfortunately need to be copied.
+ public void onStartSocketKeepalive(int slot, @NonNull Duration interval,
@NonNull KeepalivePacketData packet) {
- Message msg = mHandler.obtainMessage(CMD_START_SOCKET_KEEPALIVE, slot, intervalSeconds,
- packet);
+ final long intervalSeconds = interval.getSeconds();
+ if (intervalSeconds < SocketKeepalive.MIN_INTERVAL_SEC
+ || intervalSeconds > SocketKeepalive.MAX_INTERVAL_SEC) {
+ throw new IllegalArgumentException("Interval needs to be comprised between "
+ + SocketKeepalive.MIN_INTERVAL_SEC + " and " + SocketKeepalive.MAX_INTERVAL_SEC
+ + " but was " + intervalSeconds);
+ }
+ final Message msg = mHandler.obtainMessage(CMD_START_SOCKET_KEEPALIVE, slot,
+ (int) intervalSeconds, packet);
startSocketKeepalive(msg);
msg.recycle();
}
@@ -801,9 +880,11 @@ public abstract class NetworkAgent {
* Must be called by the agent when a socket keepalive event occurs.
*
* @param slot the hardware slot on which the event occurred.
- * @param event the event that occurred.
+ * @param event the event that occurred, as one of the SocketKeepalive.ERROR_*
+ * or SocketKeepalive.SUCCESS constants.
*/
- public void sendSocketKeepaliveEvent(int slot, int event) {
+ public final void sendSocketKeepaliveEvent(int slot,
+ @SocketKeepalive.KeepaliveEvent int event) {
queueOrSendMessage(EVENT_SOCKET_KEEPALIVE, slot, event);
}
/** @hide TODO delete once callers have moved to sendSocketKeepaliveEvent */
@@ -845,9 +926,18 @@ public abstract class NetworkAgent {
}
/**
- * Called by ConnectivityService to inform this network transport of signal strength thresholds
+ * Called by ConnectivityService to inform this network agent of signal strength thresholds
* that when crossed should trigger a system wakeup and a NetworkCapabilities update.
*
+ * When the system updates the list of thresholds that should wake up the CPU for a
+ * given agent it will call this method on the agent. The agent that implement this
+ * should implement it in hardware so as to ensure the CPU will be woken up on breach.
+ * Agents are expected to react to a breach by sending an updated NetworkCapabilities
+ * object with the appropriate signal strength to sendNetworkCapabilities.
+ *
+ * The specific units are bearer-dependent. See details on the units and requests in
+ * {@link NetworkCapabilities.Builder#setSignalStrength}.
+ *
* @param thresholds the array of thresholds that should trigger wakeups.
*/
public void onSignalStrengthThresholdsUpdated(@NonNull int[] thresholds) {
diff --git a/core/java/android/net/NetworkAgentConfig.java b/core/java/android/net/NetworkAgentConfig.java
index ca9328a713f0..fee868a93be4 100644
--- a/core/java/android/net/NetworkAgentConfig.java
+++ b/core/java/android/net/NetworkAgentConfig.java
@@ -155,6 +155,7 @@ public final class NetworkAgentConfig implements Parcelable {
/**
* @return the legacy type
*/
+ @ConnectivityManager.LegacyNetworkType
public int getLegacyType() {
return legacyType;
}
@@ -206,7 +207,7 @@ public final class NetworkAgentConfig implements Parcelable {
/**
* Builder class to facilitate constructing {@link NetworkAgentConfig} objects.
*/
- public static class Builder {
+ public static final class Builder {
private final NetworkAgentConfig mConfig = new NetworkAgentConfig();
/**
diff --git a/core/java/android/net/NetworkCapabilities.java b/core/java/android/net/NetworkCapabilities.java
index af9414c56654..91ef911ef25c 100644
--- a/core/java/android/net/NetworkCapabilities.java
+++ b/core/java/android/net/NetworkCapabilities.java
@@ -1122,7 +1122,7 @@ public final class NetworkCapabilities implements Parcelable {
}
private boolean satisfiedBySpecifier(NetworkCapabilities nc) {
- return mNetworkSpecifier == null || mNetworkSpecifier.satisfiedBy(nc.mNetworkSpecifier)
+ return mNetworkSpecifier == null || mNetworkSpecifier.canBeSatisfiedBy(nc.mNetworkSpecifier)
|| nc.mNetworkSpecifier instanceof MatchAllNetworkSpecifier;
}
diff --git a/core/java/android/net/NetworkProvider.java b/core/java/android/net/NetworkProvider.java
index 418d6915d4b3..75086cf82b57 100644
--- a/core/java/android/net/NetworkProvider.java
+++ b/core/java/android/net/NetworkProvider.java
@@ -16,6 +16,7 @@
package android.net;
+import android.annotation.IntRange;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.RequiresPermission;
@@ -33,8 +34,8 @@ import android.util.Log;
* {@link NetworkAgent}s. The networks can then provide connectivity to apps and can be interacted
* with via networking APIs such as {@link ConnectivityManager}.
*
- * Subclasses should implement {@link #onNetworkRequested} and {@link #onRequestWithdrawn} to
- * receive {@link NetworkRequest}s sent by the system and by apps. A network that is not the
+ * Subclasses should implement {@link #onNetworkRequested} and {@link #onNetworkRequestWithdrawn}
+ * to receive {@link NetworkRequest}s sent by the system and by apps. A network that is not the
* best (highest-scoring) network for any request is generally not used by the system, and torn
* down.
*
@@ -77,7 +78,7 @@ public class NetworkProvider {
* Constructs a new NetworkProvider.
*
* @param looper the Looper on which to run {@link #onNetworkRequested} and
- * {@link #onRequestWithdrawn}.
+ * {@link #onNetworkRequestWithdrawn}.
* @param name the name of the listener, used only for debugging.
*
* @hide
@@ -94,7 +95,7 @@ public class NetworkProvider {
onNetworkRequested((NetworkRequest) m.obj, m.arg1, m.arg2);
break;
case CMD_CANCEL_REQUEST:
- onRequestWithdrawn((NetworkRequest) m.obj);
+ onNetworkRequestWithdrawn((NetworkRequest) m.obj);
break;
default:
Log.e(mName, "Unhandled message: " + m.what);
@@ -142,14 +143,15 @@ public class NetworkProvider {
* @hide
*/
@SystemApi
- public void onNetworkRequested(@NonNull NetworkRequest request, int score, int providerId) {}
+ public void onNetworkRequested(@NonNull NetworkRequest request,
+ @IntRange(from = 0, to = 99) int score, int providerId) {}
/**
* Called when a NetworkRequest is withdrawn.
* @hide
*/
@SystemApi
- public void onRequestWithdrawn(@NonNull NetworkRequest request) {}
+ public void onNetworkRequestWithdrawn(@NonNull NetworkRequest request) {}
/**
* Asserts that no provider will ever be able to satisfy the specified request. The provider
@@ -157,7 +159,7 @@ public class NetworkProvider {
* satisfying this request, and that the request cannot be satisfied. The application filing the
* request will receive an {@link NetworkCallback#onUnavailable()} callback.
*
- * @param request the request that cannot be fulfilled
+ * @param request the request that permanently cannot be fulfilled
* @hide
*/
@SystemApi
diff --git a/core/java/android/net/NetworkRequest.java b/core/java/android/net/NetworkRequest.java
index 964f13f39ec6..a6bd74a5870d 100644
--- a/core/java/android/net/NetworkRequest.java
+++ b/core/java/android/net/NetworkRequest.java
@@ -473,10 +473,8 @@ public class NetworkRequest implements Parcelable {
*
* @param nc Capabilities that should satisfy this NetworkRequest. null capabilities do not
* satisfy any request.
- * @hide
*/
- @SystemApi
- public boolean satisfiedBy(@Nullable NetworkCapabilities nc) {
+ public boolean canBeSatisfiedBy(@Nullable NetworkCapabilities nc) {
return networkCapabilities.satisfiedByNetworkCapabilities(nc);
}
diff --git a/core/java/android/net/NetworkSpecifier.java b/core/java/android/net/NetworkSpecifier.java
index 2dd0c4e207fe..160259e39813 100644
--- a/core/java/android/net/NetworkSpecifier.java
+++ b/core/java/android/net/NetworkSpecifier.java
@@ -35,7 +35,9 @@ public abstract class NetworkSpecifier {
* @hide
*/
@SystemApi
- public abstract boolean satisfiedBy(@Nullable NetworkSpecifier other);
+ public boolean canBeSatisfiedBy(@Nullable NetworkSpecifier other) {
+ return false;
+ }
/**
* Optional method which can be overridden by concrete implementations of NetworkSpecifier to
diff --git a/core/java/android/net/SocketKeepalive.java b/core/java/android/net/SocketKeepalive.java
index fc9a8f63c131..46aef10258d9 100644
--- a/core/java/android/net/SocketKeepalive.java
+++ b/core/java/android/net/SocketKeepalive.java
@@ -109,6 +109,17 @@ public abstract class SocketKeepalive implements AutoCloseable {
})
public @interface ErrorCode {}
+ /** @hide */
+ @Retention(RetentionPolicy.SOURCE)
+ @IntDef(value = {
+ SUCCESS,
+ ERROR_INVALID_LENGTH,
+ ERROR_UNSUPPORTED,
+ ERROR_INSUFFICIENT_RESOURCES,
+ ERROR_HARDWARE_UNSUPPORTED
+ })
+ public @interface KeepaliveEvent {}
+
/**
* The minimum interval in seconds between keepalive packet transmissions.
*
diff --git a/core/java/android/net/StringNetworkSpecifier.java b/core/java/android/net/StringNetworkSpecifier.java
index 6ae59716cfd8..3f2aa17f263e 100644
--- a/core/java/android/net/StringNetworkSpecifier.java
+++ b/core/java/android/net/StringNetworkSpecifier.java
@@ -40,7 +40,7 @@ public final class StringNetworkSpecifier extends NetworkSpecifier implements Pa
/** @hide */
@Override
- public boolean satisfiedBy(NetworkSpecifier other) {
+ public boolean canBeSatisfiedBy(NetworkSpecifier other) {
return equals(other);
}
diff --git a/core/java/android/net/TelephonyNetworkSpecifier.java b/core/java/android/net/TelephonyNetworkSpecifier.java
index 726f77059707..aafebd7ecfc8 100644
--- a/core/java/android/net/TelephonyNetworkSpecifier.java
+++ b/core/java/android/net/TelephonyNetworkSpecifier.java
@@ -97,7 +97,7 @@ public final class TelephonyNetworkSpecifier extends NetworkSpecifier implements
/** @hide */
@Override
- public boolean satisfiedBy(NetworkSpecifier other) {
+ public boolean canBeSatisfiedBy(NetworkSpecifier other) {
// Any generic requests should be satisfied by a specific telephony network.
// For simplicity, we treat null same as MatchAllNetworkSpecifier
return equals(other) || other == null || other instanceof MatchAllNetworkSpecifier;
diff --git a/core/java/android/os/IVibratorService.aidl b/core/java/android/os/IVibratorService.aidl
index 84013e7ebc88..615ae6593330 100644
--- a/core/java/android/os/IVibratorService.aidl
+++ b/core/java/android/os/IVibratorService.aidl
@@ -28,7 +28,7 @@ interface IVibratorService
boolean registerVibratorStateListener(in IVibratorStateListener listener);
boolean unregisterVibratorStateListener(in IVibratorStateListener listener);
boolean hasAmplitudeControl();
- boolean[] areEffectsSupported(in int[] effectIds);
+ int[] areEffectsSupported(in int[] effectIds);
boolean[] arePrimitivesSupported(in int[] primitiveIds);
boolean setAlwaysOnEffect(int uid, String opPkg, int alwaysOnId, in VibrationEffect effect,
in VibrationAttributes attributes);
diff --git a/core/java/android/os/Process.java b/core/java/android/os/Process.java
index 5d2c9d18c00c..b7b3c4fc8add 100644
--- a/core/java/android/os/Process.java
+++ b/core/java/android/os/Process.java
@@ -607,9 +607,6 @@ public class Process {
* started.
* @param pkgDataInfoMap Map from related package names to private data directory
* volume UUID and inode number.
- * @param whitelistedDataInfoMap Map from whitelisted package names to private data directory
- * volume UUID and inode number.
- * @param bindMountAppsData whether zygote needs to mount CE and DE data.
* @param bindMountAppStorageDirs whether zygote needs to mount Android/obb and Android/data.
* @param zygoteArgs Additional arguments to supply to the zygote process.
* @return An object that describes the result of the attempt to start the process.
@@ -634,17 +631,13 @@ public class Process {
@Nullable long[] disabledCompatChanges,
@Nullable Map<String, Pair<String, Long>>
pkgDataInfoMap,
- @Nullable Map<String, Pair<String, Long>>
- whitelistedDataInfoMap,
- boolean bindMountAppsData,
boolean bindMountAppStorageDirs,
@Nullable String[] zygoteArgs) {
return ZYGOTE_PROCESS.start(processClass, niceName, uid, gid, gids,
runtimeFlags, mountExternal, targetSdkVersion, seInfo,
abi, instructionSet, appDataDir, invokeWith, packageName,
zygotePolicyFlags, isTopApp, disabledCompatChanges,
- pkgDataInfoMap, whitelistedDataInfoMap, bindMountAppsData,
- bindMountAppStorageDirs, zygoteArgs);
+ pkgDataInfoMap, bindMountAppStorageDirs, zygoteArgs);
}
/** @hide */
@@ -668,8 +661,7 @@ public class Process {
runtimeFlags, mountExternal, targetSdkVersion, seInfo,
abi, instructionSet, appDataDir, invokeWith, packageName,
/*zygotePolicyFlags=*/ ZYGOTE_POLICY_FLAG_EMPTY, /*isTopApp=*/ false,
- disabledCompatChanges, /* pkgDataInfoMap */ null,
- /* whitelistedDataInfoMap */ null, false, false, zygoteArgs);
+ disabledCompatChanges, /* pkgDataInfoMap */ null, false, zygoteArgs);
}
/**
diff --git a/core/java/android/os/RecoverySystem.java b/core/java/android/os/RecoverySystem.java
index d60820ef0f57..8cdcd49cb2cc 100644
--- a/core/java/android/os/RecoverySystem.java
+++ b/core/java/android/os/RecoverySystem.java
@@ -665,15 +665,17 @@ public class RecoverySystem {
* the preparation for unattended update is reset.
*
* @param context the Context to use.
- * @throws IOException if there were any errors setting up unattended update
+ * @throws IOException if there were any errors clearing the unattended update state
* @hide
*/
@SystemApi
@RequiresPermission(android.Manifest.permission.RECOVERY)
- public static boolean clearPrepareForUnattendedUpdate(@NonNull Context context)
+ public static void clearPrepareForUnattendedUpdate(@NonNull Context context)
throws IOException {
RecoverySystem rs = (RecoverySystem) context.getSystemService(Context.RECOVERY_SERVICE);
- return rs.clearLskf();
+ if (!rs.clearLskf()) {
+ throw new IOException("could not reset unattended update state");
+ }
}
/**
@@ -684,21 +686,22 @@ public class RecoverySystem {
* @param context the Context to use.
* @param updateToken the token used to call {@link #prepareForUnattendedUpdate} before
* @param reason the reboot reason to give to the {@link PowerManager}
- * @throws IOException if there were any errors setting up unattended update
- * @return false if the reboot couldn't proceed because the device wasn't ready for an
+ * @throws IOException if the reboot couldn't proceed because the device wasn't ready for an
* unattended reboot or if the {@code updateToken} did not match the previously
* given token
* @hide
*/
@SystemApi
@RequiresPermission(android.Manifest.permission.RECOVERY)
- public static boolean rebootAndApply(@NonNull Context context, @NonNull String updateToken,
+ public static void rebootAndApply(@NonNull Context context, @NonNull String updateToken,
@NonNull String reason) throws IOException {
if (updateToken == null) {
throw new NullPointerException("updateToken == null");
}
RecoverySystem rs = (RecoverySystem) context.getSystemService(Context.RECOVERY_SERVICE);
- return rs.rebootWithLskf(updateToken, reason);
+ if (!rs.rebootWithLskf(updateToken, reason)) {
+ throw new IOException("system not prepared to apply update");
+ }
}
/**
diff --git a/core/java/android/os/SystemVibrator.java b/core/java/android/os/SystemVibrator.java
index da20c7f2ae70..2dba8dce62da 100644
--- a/core/java/android/os/SystemVibrator.java
+++ b/core/java/android/os/SystemVibrator.java
@@ -21,12 +21,13 @@ import android.annotation.NonNull;
import android.compat.annotation.UnsupportedAppUsage;
import android.content.Context;
import android.media.AudioAttributes;
-import android.os.IVibratorStateListener;
import android.util.ArrayMap;
import android.util.Log;
+
import com.android.internal.annotations.GuardedBy;
-import java.util.concurrent.Executor;
+
import java.util.Objects;
+import java.util.concurrent.Executor;
/**
* Vibrator implementation that controls the main system vibrator.
@@ -238,13 +239,13 @@ public class SystemVibrator extends Vibrator {
}
@Override
- public boolean[] areEffectsSupported(@VibrationEffect.EffectType int... effectIds) {
+ public int[] areEffectsSupported(@VibrationEffect.EffectType int... effectIds) {
try {
return mService.areEffectsSupported(effectIds);
} catch (RemoteException e) {
Log.w(TAG, "Failed to query effect support");
+ throw e.rethrowAsRuntimeException();
}
- return new boolean[effectIds.length];
}
@Override
@@ -254,8 +255,8 @@ public class SystemVibrator extends Vibrator {
return mService.arePrimitivesSupported(primitiveIds);
} catch (RemoteException e) {
Log.w(TAG, "Failed to query effect support");
+ throw e.rethrowAsRuntimeException();
}
- return new boolean[primitiveIds.length];
}
diff --git a/core/java/android/os/VibrationEffect.java b/core/java/android/os/VibrationEffect.java
index aa89b515adc6..ca861577ab37 100644
--- a/core/java/android/os/VibrationEffect.java
+++ b/core/java/android/os/VibrationEffect.java
@@ -961,7 +961,7 @@ public abstract class VibrationEffect implements Parcelable {
*
* @see VibrationEffect#startComposition()
*/
- public static class Composition {
+ public static final class Composition {
/** @hide */
@IntDef(prefix = { "PRIMITIVE_" }, value = {
PRIMITIVE_CLICK,
@@ -1020,6 +1020,8 @@ public abstract class VibrationEffect implements Parcelable {
private ArrayList<PrimitiveEffect> mEffects = new ArrayList<>();
+ Composition() { }
+
/**
* Add a haptic primitive to the end of the current composition.
*
@@ -1030,7 +1032,7 @@ public abstract class VibrationEffect implements Parcelable {
*
* @return The {@link Composition} object to enable adding multiple primitives in one chain.
*/
- @Nullable
+ @NonNull
public Composition addPrimitive(@Primitive int primitiveId) {
addPrimitive(primitiveId, /*scale*/ 1.0f, /*delay*/ 0);
return this;
@@ -1046,7 +1048,7 @@ public abstract class VibrationEffect implements Parcelable {
*
* @return The {@link Composition} object to enable adding multiple primitives in one chain.
*/
- @Nullable
+ @NonNull
public Composition addPrimitive(@Primitive int primitiveId,
@FloatRange(from = 0f, to = 1f) float scale) {
addPrimitive(primitiveId, scale, /*delay*/ 0);
@@ -1058,11 +1060,11 @@ public abstract class VibrationEffect implements Parcelable {
*
* @param primitiveId The primitive to add
* @param scale The scale to apply to the intensity of the primitive.
- * @param delay The amount of time, in milliseconds, to wait before playing the prior
+ * @param delay The amount of time, in milliseconds, to wait between playing the prior
* primitive and this one
* @return The {@link Composition} object to enable adding multiple primitives in one chain.
*/
- @Nullable
+ @NonNull
public Composition addPrimitive(@Primitive int primitiveId,
@FloatRange(from = 0f, to = 1f) float scale, @IntRange(from = 0) int delay) {
mEffects.add(new PrimitiveEffect(checkPrimitive(primitiveId), scale, delay));
diff --git a/core/java/android/os/Vibrator.java b/core/java/android/os/Vibrator.java
index d4da7a84d2a1..86d009e8607e 100644
--- a/core/java/android/os/Vibrator.java
+++ b/core/java/android/os/Vibrator.java
@@ -32,6 +32,7 @@ import android.util.Log;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
+import java.util.Arrays;
import java.util.concurrent.Executor;
/**
@@ -72,6 +73,37 @@ public abstract class Vibrator {
*/
public static final int VIBRATION_INTENSITY_HIGH = 3;
+ /**
+ * Vibration effect support: unknown
+ *
+ * The hardware doesn't report it's supported effects, so we can't determine whether the
+ * effect is supported or not.
+ */
+ public static final int VIBRATION_EFFECT_SUPPORT_UNKNOWN = 0;
+
+ /**
+ * Vibration effect support: supported
+ *
+ * This effect is supported by the underlying hardware.
+ */
+ public static final int VIBRATION_EFFECT_SUPPORT_YES = 1;
+
+ /**
+ * Vibration effect support: unsupported
+ *
+ * This effect is <b>not</b> supported by the underlying hardware.
+ */
+ public static final int VIBRATION_EFFECT_SUPPORT_NO = 2;
+
+ /** @hide */
+ @Retention(RetentionPolicy.SOURCE)
+ @IntDef(prefix = {"VIBRATION_EFFECT_SUPPORT_"}, value = {
+ VIBRATION_EFFECT_SUPPORT_UNKNOWN,
+ VIBRATION_EFFECT_SUPPORT_YES,
+ VIBRATION_EFFECT_SUPPORT_NO,
+ })
+ public @interface VibrationEffectSupport {}
+
/** @hide */
@Retention(RetentionPolicy.SOURCE)
@IntDef(prefix = {"VIBRATION_INTENSITY_"}, value = {
@@ -318,47 +350,61 @@ public abstract class Vibrator {
/**
* Query whether the vibrator supports the given effects.
*
- * If the returned array is {@code null}, the hardware doesn't support querying its supported
- * effects. It may support any or all effects, but there's no way to programmatically know
- * whether a {@link #vibrate} call will be successful.
+ * Not all hardware reports its effect capabilities, so the system may not necessarily know
+ * whether an effect is supported or not.
*
- * If the returned array is non-null, then it will be the same length as the query array and
- * the value at a given index will contain whether the effect at that same index in the
- * querying array is supported or not.
+ * The returned array will be the same length as the query array and the value at a given index
+ * will contain {@link #VIBRATION_EFFECT_SUPPORT_YES} if the effect at that same index in the
+ * querying array is supported, {@link #VIBRATION_EFFECT_SUPPORT_NO} if it isn't supported, or
+ * {@link #VIBRATION_EFFECT_SUPPORT_UNKNOWN} if the system can't determine whether it's
+ * supported or not.
*
* @param effectIds Which effects to query for.
- * @return Whether the effects are supported. Null when the hardware doesn't tell us what it
- * supports.
+ * @return An array containing the systems current knowledge about whether the given effects
+ * are supported or not.
*/
- @Nullable
- public boolean[] areEffectsSupported(
+ @NonNull
+ @VibrationEffectSupport
+ public int[] areEffectsSupported(
@NonNull @VibrationEffect.EffectType int... effectIds) {
- return new boolean[effectIds.length];
+ final int[] support = new int[effectIds.length];
+ Arrays.fill(support, VIBRATION_EFFECT_SUPPORT_NO);
+ return support;
}
/**
* Query whether the vibrator supports all of the given effects.
*
- * If the result is {@code null}, the hardware doesn't support querying its supported
- * effects. It may support any or all effects, but there's no way to programmatically know
- * whether a {@link #vibrate} call will be successful.
+ * Not all hardware reports its effect capabilities, so the system may not necessarily know
+ * whether an effect is supported or not.
*
- * If the returned array is non-null, then it will return whether all of the effects are
+ * If the result is {@link #VIBRATION_EFFECT_SUPPORT_YES}, all effects in the query are
* supported by the hardware.
*
+ * If the result is {@link #VIBRATION_EFFECT_SUPPORT_NO}, at least one of the effects in the
+ * query is not supported.
+ *
+ * If the result is {@link #VIBRATION_EFFECT_SUPPORT_UNKNOWN}, the system doesn't know whether
+ * all of the effects are supported. It may support any or all of the queried effects,
+ * but there's no way to programmatically know whether a {@link #vibrate} call will successfully
+ * cause a vibration. It's guaranteed, however, that none of the queried effects are
+ * definitively unsupported by the hardware.
+ *
* @param effectIds Which effects to query for.
- * @return Whether the effects are supported. {@code null} when the hardware doesn't tell us
- * what it supports.
+ * @return Whether all of the effects are supported.
*/
- @Nullable
- public Boolean areAllEffectsSupported(
+ @VibrationEffectSupport
+ public final int areAllEffectsSupported(
@NonNull @VibrationEffect.EffectType int... effectIds) {
- for (boolean supported : areEffectsSupported(effectIds)) {
- if (!supported) {
- return false;
+ int support = VIBRATION_EFFECT_SUPPORT_YES;
+ for (int supported : areEffectsSupported(effectIds)) {
+ if (supported == VIBRATION_EFFECT_SUPPORT_NO) {
+ return VIBRATION_EFFECT_SUPPORT_NO;
+ } else if (supported == VIBRATION_EFFECT_SUPPORT_UNKNOWN) {
+ support = VIBRATION_EFFECT_SUPPORT_UNKNOWN;
}
}
- return true;
+ return support;
}
@@ -384,7 +430,7 @@ public abstract class Vibrator {
* @param primitiveIds Which primitives to query for.
* @return Whether primitives effects are supported.
*/
- public boolean areAllPrimitivesSupported(
+ public final boolean areAllPrimitivesSupported(
@NonNull @VibrationEffect.Composition.Primitive int... primitiveIds) {
for (boolean supported : arePrimitivesSupported(primitiveIds)) {
if (!supported) {
diff --git a/core/java/android/os/ZygoteProcess.java b/core/java/android/os/ZygoteProcess.java
index a4c99c006d80..5f3f14facd75 100644
--- a/core/java/android/os/ZygoteProcess.java
+++ b/core/java/android/os/ZygoteProcess.java
@@ -333,9 +333,6 @@ public class ZygoteProcess {
* started.
* @param pkgDataInfoMap Map from related package names to private data directory
* volume UUID and inode number.
- * @param whitelistedDataInfoMap Map from whitelisted package names to private data directory
- * volume UUID and inode number.
- * @param bindMountAppsData whether zygote needs to mount CE and DE data.
* @param bindMountAppStorageDirs whether zygote needs to mount Android/obb and Android/data.
*
* @param zygoteArgs Additional arguments to supply to the Zygote process.
@@ -358,9 +355,6 @@ public class ZygoteProcess {
@Nullable long[] disabledCompatChanges,
@Nullable Map<String, Pair<String, Long>>
pkgDataInfoMap,
- @Nullable Map<String, Pair<String, Long>>
- whitelistedDataInfoMap,
- boolean bindMountAppsData,
boolean bindMountAppStorageDirs,
@Nullable String[] zygoteArgs) {
// TODO (chriswailes): Is there a better place to check this value?
@@ -373,8 +367,7 @@ public class ZygoteProcess {
runtimeFlags, mountExternal, targetSdkVersion, seInfo,
abi, instructionSet, appDataDir, invokeWith, /*startChildZygote=*/ false,
packageName, zygotePolicyFlags, isTopApp, disabledCompatChanges,
- pkgDataInfoMap, whitelistedDataInfoMap, bindMountAppsData,
- bindMountAppStorageDirs, zygoteArgs);
+ pkgDataInfoMap, bindMountAppStorageDirs, zygoteArgs);
} catch (ZygoteStartFailedEx ex) {
Log.e(LOG_TAG,
"Starting VM process through Zygote failed");
@@ -615,9 +608,6 @@ public class ZygoteProcess {
* @param disabledCompatChanges a list of disabled compat changes for the process being started.
* @param pkgDataInfoMap Map from related package names to private data directory volume UUID
* and inode number.
- * @param whitelistedDataInfoMap Map from whitelisted package names to private data directory
- * volume UUID and inode number.
- * @param bindMountAppsData whether zygote needs to mount CE and DE data.
* @param bindMountAppStorageDirs whether zygote needs to mount Android/obb and Android/data.
* @param extraArgs Additional arguments to supply to the zygote process.
* @return An object that describes the result of the attempt to start the process.
@@ -641,9 +631,6 @@ public class ZygoteProcess {
@Nullable long[] disabledCompatChanges,
@Nullable Map<String, Pair<String, Long>>
pkgDataInfoMap,
- @Nullable Map<String, Pair<String, Long>>
- whitelistedDataInfoMap,
- boolean bindMountAppsData,
boolean bindMountAppStorageDirs,
@Nullable String[] extraArgs)
throws ZygoteStartFailedEx {
@@ -741,33 +728,11 @@ public class ZygoteProcess {
}
argsForZygote.add(sb.toString());
}
- if (whitelistedDataInfoMap != null && whitelistedDataInfoMap.size() > 0) {
- StringBuilder sb = new StringBuilder();
- sb.append(Zygote.WHITELISTED_DATA_INFO_MAP);
- sb.append("=");
- boolean started = false;
- for (Map.Entry<String, Pair<String, Long>> entry : whitelistedDataInfoMap.entrySet()) {
- if (started) {
- sb.append(',');
- }
- started = true;
- sb.append(entry.getKey());
- sb.append(',');
- sb.append(entry.getValue().first);
- sb.append(',');
- sb.append(entry.getValue().second);
- }
- argsForZygote.add(sb.toString());
- }
if (bindMountAppStorageDirs) {
argsForZygote.add(Zygote.BIND_MOUNT_APP_STORAGE_DIRS);
}
- if (bindMountAppsData) {
- argsForZygote.add(Zygote.BIND_MOUNT_APP_DATA_DIRS);
- }
-
if (disabledCompatChanges != null && disabledCompatChanges.length > 0) {
StringBuilder sb = new StringBuilder();
sb.append("--disabled-compat-changes=");
@@ -1326,7 +1291,6 @@ public class ZygoteProcess {
true /* startChildZygote */, null /* packageName */,
ZYGOTE_POLICY_FLAG_SYSTEM_PROCESS /* zygotePolicyFlags */, false /* isTopApp */,
null /* disabledCompatChanges */, null /* pkgDataInfoMap */,
- null /* whitelistedDataInfoMap */, false /* bindMountAppsData*/,
/* bindMountAppStorageDirs */ false, extraArgs);
} catch (ZygoteStartFailedEx ex) {
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index 7d7c8ccdd7c1..fbe381b2ec15 100644
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -6589,11 +6589,9 @@ public final class Settings {
"accessibility_shortcut_target_service";
/**
- * Setting specifying the accessibility services, accessibility shortcut targets,
- * or features to be toggled via the accessibility button in the navigation bar.
- *
- * <p> This is a colon-separated string list which contains the flattened
- * {@link ComponentName} and the class name of a system class implementing a supported
+ * Setting specifying the accessibility service or feature to be toggled via the
+ * accessibility button in the navigation bar. This is either a flattened
+ * {@link ComponentName} or the class name of a system class implementing a supported
* accessibility feature.
* @hide
*/
@@ -6602,15 +6600,14 @@ public final class Settings {
/**
* Setting specifying the accessibility services, accessibility shortcut targets,
- * or features to be toggled via the long press accessibility button in the navigation bar.
+ * or features to be toggled via the accessibility button in the navigation bar.
*
* <p> This is a colon-separated string list which contains the flattened
* {@link ComponentName} and the class name of a system class implementing a supported
* accessibility feature.
* @hide
*/
- public static final String ACCESSIBILITY_BUTTON_LONG_PRESS_TARGETS =
- "accessibility_button_long_press_targets";
+ public static final String ACCESSIBILITY_BUTTON_TARGETS = "accessibility_button_targets";
/**
* The system class name of magnification controller which is a target to be toggled via
@@ -6775,8 +6772,8 @@ public final class Settings {
* zoom in the display content and is targeted to low vision users. The current
* magnification scale is controlled by {@link #ACCESSIBILITY_DISPLAY_MAGNIFICATION_SCALE}.
*
- * @deprecated Use {@link #ACCESSIBILITY_BUTTON_TARGET_COMPONENT} instead.
- * {@link #ACCESSIBILITY_BUTTON_TARGET_COMPONENT} holds the magnification system class name
+ * @deprecated Use {@link #ACCESSIBILITY_BUTTON_TARGETS} instead.
+ * {@link #ACCESSIBILITY_BUTTON_TARGETS} holds the magnification system class name
* when navigation bar magnification is enabled.
* @hide
*/
@@ -8574,6 +8571,16 @@ public final class Settings {
public static final String QS_TILES = "sysui_qs_tiles";
/**
+ * Whether this user has enabled Quick controls.
+ *
+ * 0 indicates disabled and 1 indicates enabled. A non existent value should be treated as
+ * enabled.
+ *
+ * @hide
+ */
+ public static final String CONTROLS_ENABLED = "controls_enabled";
+
+ /**
* Specifies whether the web action API is enabled.
*
* @hide
diff --git a/core/java/android/provider/Telephony.java b/core/java/android/provider/Telephony.java
index 1eb53aa366fa..b34268d04238 100644
--- a/core/java/android/provider/Telephony.java
+++ b/core/java/android/provider/Telephony.java
@@ -1332,7 +1332,6 @@ public final class Telephony {
* @hide
*/
@SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
- @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
public static final String ACTION_SMS_MMS_DB_LOST =
"android.provider.action.SMS_MMS_DB_LOST";
diff --git a/core/java/android/security/FileIntegrityManager.java b/core/java/android/security/FileIntegrityManager.java
index cdd6584e9b35..266046e57cd5 100644
--- a/core/java/android/security/FileIntegrityManager.java
+++ b/core/java/android/security/FileIntegrityManager.java
@@ -31,9 +31,11 @@ import java.security.cert.X509Certificate;
@SystemService(Context.FILE_INTEGRITY_SERVICE)
public final class FileIntegrityManager {
@NonNull private final IFileIntegrityService mService;
+ @NonNull private final Context mContext;
/** @hide */
- public FileIntegrityManager(@NonNull IFileIntegrityService service) {
+ public FileIntegrityManager(@NonNull Context context, @NonNull IFileIntegrityService service) {
+ mContext = context;
mService = service;
}
@@ -69,7 +71,8 @@ public final class FileIntegrityManager {
public boolean isAppSourceCertificateTrusted(@NonNull X509Certificate certificate)
throws CertificateEncodingException {
try {
- return mService.isAppSourceCertificateTrusted(certificate.getEncoded());
+ return mService.isAppSourceCertificateTrusted(
+ certificate.getEncoded(), mContext.getOpPackageName());
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
diff --git a/core/java/android/security/IFileIntegrityService.aidl b/core/java/android/security/IFileIntegrityService.aidl
index ebb8bcb85350..dff347ec758a 100644
--- a/core/java/android/security/IFileIntegrityService.aidl
+++ b/core/java/android/security/IFileIntegrityService.aidl
@@ -22,5 +22,5 @@ package android.security;
*/
interface IFileIntegrityService {
boolean isApkVeritySupported();
- boolean isAppSourceCertificateTrusted(in byte[] certificateBytes);
+ boolean isAppSourceCertificateTrusted(in byte[] certificateBytes, in String packageName);
}
diff --git a/core/java/android/service/contentcapture/ContentCaptureService.java b/core/java/android/service/contentcapture/ContentCaptureService.java
index cecfe24613a4..61744e423b5b 100644
--- a/core/java/android/service/contentcapture/ContentCaptureService.java
+++ b/core/java/android/service/contentcapture/ContentCaptureService.java
@@ -18,7 +18,7 @@ package android.service.contentcapture;
import static android.view.contentcapture.ContentCaptureHelper.sDebug;
import static android.view.contentcapture.ContentCaptureHelper.sVerbose;
import static android.view.contentcapture.ContentCaptureHelper.toList;
-import static android.view.contentcapture.ContentCaptureSession.NO_SESSION_ID;
+import static android.view.contentcapture.ContentCaptureManager.NO_SESSION_ID;
import static com.android.internal.util.function.pooled.PooledLambda.obtainMessage;
diff --git a/core/java/android/service/controls/ControlsProviderService.java b/core/java/android/service/controls/ControlsProviderService.java
index 9accf5b0abf5..4262c4022131 100644
--- a/core/java/android/service/controls/ControlsProviderService.java
+++ b/core/java/android/service/controls/ControlsProviderService.java
@@ -304,12 +304,11 @@ public abstract class ControlsProviderService extends Service {
Preconditions.checkNotNull(context);
Preconditions.checkNotNull(componentName);
Preconditions.checkNotNull(control);
- final ComponentName sysuiComponent = ComponentName.unflattenFromString(
- context.getResources().getString(
- com.android.internal.R.string.config_systemUIServiceComponent));
+ final String controlsPackage = context.getString(
+ com.android.internal.R.string.config_controlsPackage);
Intent intent = new Intent(ACTION_ADD_CONTROL);
intent.putExtra(Intent.EXTRA_COMPONENT_NAME, componentName);
- intent.setPackage(sysuiComponent.getPackageName());
+ intent.setPackage(controlsPackage);
if (isStatelessControl(control)) {
intent.putExtra(EXTRA_CONTROL, control);
} else {
diff --git a/core/java/android/service/dataloader/DataLoaderService.java b/core/java/android/service/dataloader/DataLoaderService.java
index 0170726b31d6..c047dc0d07c7 100644
--- a/core/java/android/service/dataloader/DataLoaderService.java
+++ b/core/java/android/service/dataloader/DataLoaderService.java
@@ -29,7 +29,6 @@ import android.content.pm.IDataLoader;
import android.content.pm.IDataLoaderStatusListener;
import android.content.pm.InstallationFile;
import android.content.pm.InstallationFileParcel;
-import android.content.pm.NamedParcelFileDescriptor;
import android.os.IBinder;
import android.os.ParcelFileDescriptor;
import android.util.ExceptionUtils;
@@ -133,16 +132,6 @@ public abstract class DataLoaderService extends Service {
}
}
}
- if (params.dynamicArgs != null) {
- NamedParcelFileDescriptor[] fds = params.dynamicArgs;
- for (NamedParcelFileDescriptor nfd : fds) {
- try {
- nfd.fd.close();
- } catch (IOException e) {
- Slog.e(TAG, "Failed to close DynamicArgs parcel file descriptor " + e);
- }
- }
- }
}
}
diff --git a/core/java/android/service/dreams/DreamService.java b/core/java/android/service/dreams/DreamService.java
index e70311fb9429..c9be1c1fabb2 100644
--- a/core/java/android/service/dreams/DreamService.java
+++ b/core/java/android/service/dreams/DreamService.java
@@ -15,8 +15,6 @@
*/
package android.service.dreams;
-import static android.view.WindowManager.LayoutParams.TYPE_DREAM;
-
import android.annotation.IdRes;
import android.annotation.LayoutRes;
import android.annotation.NonNull;
@@ -1071,7 +1069,6 @@ public class DreamService extends Service implements Window.Callback {
private void onWindowCreated(Window w) {
mWindow = w;
mWindow.setCallback(this);
- mWindow.setType(TYPE_DREAM);
mWindow.requestFeature(Window.FEATURE_NO_TITLE);
WindowManager.LayoutParams lp = mWindow.getAttributes();
diff --git a/core/java/android/service/voice/AlwaysOnHotwordDetector.java b/core/java/android/service/voice/AlwaysOnHotwordDetector.java
index f8265d6366ab..97cd7608f876 100644
--- a/core/java/android/service/voice/AlwaysOnHotwordDetector.java
+++ b/core/java/android/service/voice/AlwaysOnHotwordDetector.java
@@ -487,7 +487,7 @@ public class AlwaysOnHotwordDetector {
ModuleProperties properties =
mModelManagementService.getDspModuleProperties();
if (properties != null) {
- return properties.audioCapabilities;
+ return properties.getAudioCapabilities();
}
return 0;
diff --git a/core/java/android/telephony/PhoneStateListener.java b/core/java/android/telephony/PhoneStateListener.java
index f6d56eed0fb3..c36a33f7a53d 100644
--- a/core/java/android/telephony/PhoneStateListener.java
+++ b/core/java/android/telephony/PhoneStateListener.java
@@ -21,6 +21,7 @@ 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;
import android.os.Build;
@@ -65,6 +66,43 @@ public class PhoneStateListener {
private static final boolean DBG = false; // STOPSHIP if true
/**
+ * Experiment flag to set the per-pid registration limit for PhoneStateListeners
+ *
+ * Limit on registrations of {@link PhoneStateListener}s on a per-pid
+ * basis. When this limit is exceeded, any calls to {@link TelephonyManager#listen} will fail
+ * with an {@link IllegalStateException}.
+ *
+ * {@link android.os.Process#PHONE_UID}, {@link android.os.Process#SYSTEM_UID}, and the uid that
+ * TelephonyRegistry runs under are exempt from this limit.
+ *
+ * If the value of the flag is less than 1, enforcement of the limit will be disabled.
+ * @hide
+ */
+ public static final String FLAG_PER_PID_REGISTRATION_LIMIT =
+ "phone_state_listener_per_pid_registration_limit";
+
+ /**
+ * Default value for the per-pid registation limit.
+ * See {@link #FLAG_PER_PID_REGISTRATION_LIMIT}.
+ * @hide
+ */
+ public static final int DEFAULT_PER_PID_REGISTRATION_LIMIT = 50;
+
+ /**
+ * This change enables a limit on the number of {@link PhoneStateListener} objects any process
+ * may register via {@link TelephonyManager#listen}. The default limit is 50, which may change
+ * via remote device config updates.
+ *
+ * This limit is enforced via an {@link IllegalStateException} thrown from
+ * {@link TelephonyManager#listen} when the offending process attempts to register one too many
+ * listeners.
+ *
+ * @hide
+ */
+ @ChangeId
+ public static final long PHONE_STATE_LISTENER_LIMIT_CHANGE_ID = 150880553L;
+
+ /**
* Stop listening for updates.
*
* The PhoneStateListener is not tied to any subscription and unregistered for any update.
diff --git a/core/java/android/view/InsetsController.java b/core/java/android/view/InsetsController.java
index e6bd84391fef..40a460dfece0 100644
--- a/core/java/android/view/InsetsController.java
+++ b/core/java/android/view/InsetsController.java
@@ -16,6 +16,7 @@
package android.view;
+import static android.view.InsetsState.ITYPE_CAPTION_BAR;
import static android.view.InsetsState.ITYPE_IME;
import static android.view.InsetsState.toInternalType;
import static android.view.InsetsState.toPublicType;
@@ -367,6 +368,7 @@ public class InsetsController implements WindowInsetsController, InsetsAnimation
private int mLastLegacySystemUiFlags;
private DisplayCutout mLastDisplayCutout;
private boolean mStartingAnimation;
+ private int mCaptionInsetsHeight = 0;
private SyncRtSurfaceTransactionApplier mApplier;
@@ -460,7 +462,8 @@ public class InsetsController implements WindowInsetsController, InsetsAnimation
@VisibleForTesting
public boolean onStateChanged(InsetsState state) {
- boolean localStateChanged = !mState.equals(state);
+ boolean localStateChanged = !mState.equals(state, true /* excludingCaptionInsets */)
+ || !captionInsetsUnchanged();
if (!localStateChanged && mLastDispachedState.equals(state)) {
return false;
}
@@ -470,7 +473,7 @@ public class InsetsController implements WindowInsetsController, InsetsAnimation
if (localStateChanged) {
mViewRoot.notifyInsetsChanged();
}
- if (!mState.equals(mLastDispachedState)) {
+ if (!mState.equals(mLastDispachedState, true /* excludingCaptionInsets */)) {
sendStateToWindowManager();
}
return true;
@@ -488,6 +491,23 @@ public class InsetsController implements WindowInsetsController, InsetsAnimation
mState.removeSource(source.getType());
}
}
+ if (mCaptionInsetsHeight != 0) {
+ mState.getSource(ITYPE_CAPTION_BAR).setFrame(new Rect(mFrame.left, mFrame.top,
+ mFrame.right, mFrame.top + mCaptionInsetsHeight));
+ }
+ }
+
+ private boolean captionInsetsUnchanged() {
+ if (mState.peekSource(ITYPE_CAPTION_BAR) == null
+ && mCaptionInsetsHeight == 0) {
+ return true;
+ }
+ if (mState.peekSource(ITYPE_CAPTION_BAR) != null
+ && mCaptionInsetsHeight
+ == mState.peekSource(ITYPE_CAPTION_BAR).getFrame().height()) {
+ return true;
+ }
+ return false;
}
/**
@@ -964,6 +984,7 @@ public class InsetsController implements WindowInsetsController, InsetsAnimation
InsetsState tmpState = new InsetsState();
for (int i = mSourceConsumers.size() - 1; i >= 0; i--) {
final InsetsSourceConsumer consumer = mSourceConsumers.valueAt(i);
+ if (consumer.getType() == ITYPE_CAPTION_BAR) continue;
if (consumer.getControl() != null) {
tmpState.addSource(mState.getSource(consumer.getType()));
}
@@ -1105,6 +1126,11 @@ public class InsetsController implements WindowInsetsController, InsetsAnimation
}
@Override
+ public void setCaptionInsetsHeight(int height) {
+ mCaptionInsetsHeight = height;
+ }
+
+ @Override
public void setSystemBarsBehavior(@Behavior int behavior) {
mViewRoot.mWindowAttributes.privateFlags |= PRIVATE_FLAG_BEHAVIOR_CONTROLLED;
if (mViewRoot.mWindowAttributes.insetsFlags.behavior != behavior) {
diff --git a/core/java/android/view/InsetsSource.java b/core/java/android/view/InsetsSource.java
index 294faaf0b5c8..033ccef3666d 100644
--- a/core/java/android/view/InsetsSource.java
+++ b/core/java/android/view/InsetsSource.java
@@ -16,6 +16,7 @@
package android.view;
+import static android.view.InsetsState.ITYPE_CAPTION_BAR;
import static android.view.InsetsState.ITYPE_IME;
import android.annotation.NonNull;
@@ -118,6 +119,12 @@ public class InsetsSource implements Parcelable {
if (!getIntersection(frame, relativeFrame, mTmpFrame)) {
return Insets.NONE;
}
+ // During drag-move and drag-resizing, the caption insets position may not get updated
+ // before the app frame get updated. To layout the app content correctly during drag events,
+ // we always return the insets with the corresponding height covering the top.
+ if (getType() == ITYPE_CAPTION_BAR) {
+ return Insets.of(0, frame.height(), 0, 0);
+ }
// TODO: Currently, non-floating IME always intersects at bottom due to issues with cutout.
// However, we should let the policy decide from the server.
diff --git a/core/java/android/view/InsetsState.java b/core/java/android/view/InsetsState.java
index 40e6f57f2286..c5154662928e 100644
--- a/core/java/android/view/InsetsState.java
+++ b/core/java/android/view/InsetsState.java
@@ -45,6 +45,8 @@ import android.view.WindowInsets.Type;
import android.view.WindowInsets.Type.InsetsType;
import android.view.WindowManager.LayoutParams.SoftInputModeFlags;
+import com.android.internal.annotations.VisibleForTesting;
+
import java.io.PrintWriter;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
@@ -498,6 +500,19 @@ public class InsetsState implements Parcelable {
@Override
public boolean equals(Object o) {
+ return equals(o, false);
+ }
+
+ /**
+ * An equals method can exclude the caption insets. This is useful because we assemble the
+ * caption insets information on the client side, and when we communicate with server, it's
+ * excluded.
+ * @param excludingCaptionInsets {@code true} if we want to compare two InsetsState objects but
+ * ignore the caption insets source value.
+ * @return {@code true} if the two InsetsState objects are equal, {@code false} otherwise.
+ */
+ @VisibleForTesting
+ public boolean equals(Object o, boolean excludingCaptionInsets) {
if (this == o) { return true; }
if (o == null || getClass() != o.getClass()) { return false; }
@@ -506,11 +521,24 @@ public class InsetsState implements Parcelable {
if (!mDisplayFrame.equals(state.mDisplayFrame)) {
return false;
}
- if (mSources.size() != state.mSources.size()) {
+ int size = mSources.size();
+ int otherSize = state.mSources.size();
+ if (excludingCaptionInsets) {
+ if (mSources.get(ITYPE_CAPTION_BAR) != null) {
+ size--;
+ }
+ if (state.mSources.get(ITYPE_CAPTION_BAR) != null) {
+ otherSize--;
+ }
+ }
+ if (size != otherSize) {
return false;
}
for (int i = mSources.size() - 1; i >= 0; i--) {
InsetsSource source = mSources.valueAt(i);
+ if (excludingCaptionInsets) {
+ if (source.getType() == ITYPE_CAPTION_BAR) continue;
+ }
InsetsSource otherSource = state.mSources.get(source.getType());
if (otherSource == null) {
return false;
diff --git a/core/java/android/view/PendingInsetsController.java b/core/java/android/view/PendingInsetsController.java
index 229ee03521bc..a106b2c4726d 100644
--- a/core/java/android/view/PendingInsetsController.java
+++ b/core/java/android/view/PendingInsetsController.java
@@ -42,6 +42,7 @@ public class PendingInsetsController implements WindowInsetsController {
private InsetsController mReplayedInsetsController;
private ArrayList<OnControllableInsetsChangedListener> mControllableInsetsChangedListeners
= new ArrayList<>();
+ private int mCaptionInsetsHeight = 0;
@Override
public void show(int types) {
@@ -80,6 +81,11 @@ public class PendingInsetsController implements WindowInsetsController {
}
@Override
+ public void setCaptionInsetsHeight(int height) {
+ mCaptionInsetsHeight = height;
+ }
+
+ @Override
public void setSystemBarsBehavior(int behavior) {
if (mReplayedInsetsController != null) {
mReplayedInsetsController.setSystemBarsBehavior(behavior);
@@ -134,6 +140,9 @@ public class PendingInsetsController implements WindowInsetsController {
if (mAppearanceMask != 0) {
controller.setSystemBarsAppearance(mAppearance, mAppearanceMask);
}
+ if (mCaptionInsetsHeight != 0) {
+ controller.setCaptionInsetsHeight(mCaptionInsetsHeight);
+ }
int size = mRequests.size();
for (int i = 0; i < size; i++) {
mRequests.get(i).replay(controller);
diff --git a/core/java/android/view/Surface.java b/core/java/android/view/Surface.java
index 13d6dd67bb19..d12ca73599f3 100644
--- a/core/java/android/view/Surface.java
+++ b/core/java/android/view/Surface.java
@@ -871,24 +871,24 @@ public class Surface implements Parcelable {
/**
* Sets the intended frame rate for this surface.
*
- * On devices that are capable of running the display at different refresh rates, the
- * system may choose a display refresh rate to better match this surface's frame
+ * <p>On devices that are capable of running the display at different refresh rates,
+ * the system may choose a display refresh rate to better match this surface's frame
* rate. Usage of this API won't introduce frame rate throttling, or affect other
* aspects of the application's frame production pipeline. However, because the system
* may change the display refresh rate, calls to this function may result in changes
* to Choreographer callback timings, and changes to the time interval at which the
- * system releases buffers back to the application.
+ * system releases buffers back to the application.</p>
*
- * Note that this only has an effect for surfaces presented on the display. If this
+ * <p>Note that this only has an effect for surfaces presented on the display. If this
* surface is consumed by something other than the system compositor, e.g. a media
- * codec, this call has no effect.
+ * codec, this call has no effect.</p>
*
* @param frameRate The intended frame rate of this surface, in frames per second. 0
* is a special value that indicates the app will accept the system's choice for the
* display frame rate, which is the default behavior if this function isn't
- * called. The frameRate param does *not* need to be a valid refresh rate for this
- * device's display - e.g., it's fine to pass 30fps to a device that can only run the
- * display at 60fps.
+ * called. The frameRate param does <em>not</em> need to be a valid refresh rate for
+ * this device's display - e.g., it's fine to pass 30fps to a device that can only run
+ * the display at 60fps.
*
* @param compatibility The frame rate compatibility of this surface. The
* compatibility value may influence the system's choice of display frame rate. See
diff --git a/core/java/android/view/SurfaceControl.java b/core/java/android/view/SurfaceControl.java
index c87808b113f6..a37c1cbc76ad 100644
--- a/core/java/android/view/SurfaceControl.java
+++ b/core/java/android/view/SurfaceControl.java
@@ -2738,7 +2738,7 @@ public final class SurfaceControl implements Parcelable {
/**
* Sets the intended frame rate for the surface {@link SurfaceControl}.
- *
+ * <p>
* On devices that are capable of running the display at different refresh rates, the system
* may choose a display refresh rate to better match this surface's frame rate. Usage of
* this API won't directly affect the application's frame production pipeline. However,
@@ -2750,9 +2750,9 @@ public final class SurfaceControl implements Parcelable {
* @param frameRate The intended frame rate for this surface, in frames per second. 0 is a
* special value that indicates the app will accept the system's choice for
* the display frame rate, which is the default behavior if this function
- * isn't called. The frameRate param does *not* need to be a valid refresh
- * rate for this device's display - e.g., it's fine to pass 30fps to a
- * device that can only run the display at 60fps.
+ * isn't called. The frameRate param does <em>not</em> need to be a valid
+ * refresh rate for this device's display - e.g., it's fine to pass 30fps
+ * to a device that can only run the display at 60fps.
* @param compatibility The frame rate compatibility of this surface. The compatibility
* value may influence the system's choice of display frame rate. See
* the Surface.FRAME_RATE_COMPATIBILITY_* values for more info.
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index 4922917c911c..da186087a34a 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -28768,6 +28768,11 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
publicAlternatives = "Use {@link WindowInsets#getInsets(int)}")
final Rect mStableInsets = new Rect();
+ /**
+ * Current caption insets to the display coordinate.
+ */
+ final Rect mCaptionInsets = new Rect();
+
final DisplayCutout.ParcelableWrapper mDisplayCutout =
new DisplayCutout.ParcelableWrapper(DisplayCutout.NO_CUTOUT);
diff --git a/core/java/android/view/ViewConfiguration.java b/core/java/android/view/ViewConfiguration.java
index 4bea623716dc..69d37ab91a1c 100644
--- a/core/java/android/view/ViewConfiguration.java
+++ b/core/java/android/view/ViewConfiguration.java
@@ -16,8 +16,11 @@
package android.view;
+import static android.os.StrictMode.vmIncorrectContextUseEnabled;
+
import android.annotation.FloatRange;
import android.annotation.TestApi;
+import android.app.Activity;
import android.app.AppGlobals;
import android.compat.annotation.UnsupportedAppUsage;
import android.content.Context;
@@ -25,9 +28,12 @@ import android.content.res.Configuration;
import android.content.res.Resources;
import android.graphics.Rect;
import android.os.Build;
+import android.os.Bundle;
import android.os.RemoteException;
+import android.os.StrictMode;
import android.provider.Settings;
import android.util.DisplayMetrics;
+import android.util.Log;
import android.util.SparseArray;
import android.util.TypedValue;
@@ -35,6 +41,8 @@ import android.util.TypedValue;
* Contains methods to standard constants used in the UI for timeouts, sizes, and distances.
*/
public class ViewConfiguration {
+ private static final String TAG = "ViewConfiguration";
+
/**
* Defines the width of the horizontal scrollbar and the height of the vertical scrollbar in
* dips
@@ -372,11 +380,13 @@ public class ViewConfiguration {
}
/**
- * Creates a new configuration for the specified context. The configuration depends on
- * various parameters of the context, like the dimension of the display or the density
- * of the display.
+ * Creates a new configuration for the specified visual {@link Context}. The configuration
+ * depends on various parameters of the {@link Context}, like the dimension of the display or
+ * the density of the display.
*
- * @param context The application context used to initialize this view configuration.
+ * @param context A visual {@link Context} used to initialize the view configuration. It must
+ * be {@link Activity} or other {@link Context} created with
+ * {@link Context#createWindowContext(int, Bundle)}.
*
* @see #get(android.content.Context)
* @see android.util.DisplayMetrics
@@ -480,13 +490,27 @@ public class ViewConfiguration {
}
/**
- * Returns a configuration for the specified context. The configuration depends on
- * various parameters of the context, like the dimension of the display or the
+ * Returns a configuration for the specified visual {@link Context}. The configuration depends
+ * on various parameters of the {@link Context}, like the dimension of the display or the
* density of the display.
*
- * @param context The application context used to initialize the view configuration.
+ * @param context A visual {@link Context} used to initialize the view configuration. It must
+ * be {@link Activity} or other {@link Context} created with
+ * {@link Context#createWindowContext(int, Bundle)}.
*/
public static ViewConfiguration get(Context context) {
+ if (!context.isUiContext() && vmIncorrectContextUseEnabled()) {
+ final String errorMessage = "Tried to access UI constants from a non-visual Context.";
+ final String message = "UI constants, such as display metrics or window metrics, "
+ + "must be accessed from Activity or other visual Context. "
+ + "Use an Activity or a Context created with "
+ + "Context#createWindowContext(int, Bundle), which are adjusted to the "
+ + "configuration and visual bounds of an area on screen.";
+ final Exception exception = new IllegalArgumentException(errorMessage);
+ StrictMode.onIncorrectContextUsed(message, exception);
+ Log.e(TAG, errorMessage + message, exception);
+ }
+
final DisplayMetrics metrics = context.getResources().getDisplayMetrics();
final int density = (int) (100.0f * metrics.density);
diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java
index 50202aed36d2..51304dcfe8cb 100644
--- a/core/java/android/view/ViewRootImpl.java
+++ b/core/java/android/view/ViewRootImpl.java
@@ -158,6 +158,7 @@ import com.android.internal.annotations.GuardedBy;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.os.IResultReceiver;
import com.android.internal.os.SomeArgs;
+import com.android.internal.policy.DecorView;
import com.android.internal.policy.PhoneFallbackEventHandler;
import com.android.internal.util.Preconditions;
import com.android.internal.view.BaseSurfaceHolder;
@@ -2221,6 +2222,19 @@ public final class ViewRootImpl implements ViewParent,
Trace.traceEnd(Trace.TRACE_TAG_VIEW);
}
+ private boolean updateCaptionInsets() {
+ if (!(mView instanceof DecorView)) return false;
+ final int captionInsetsHeight = ((DecorView) mView).getCaptionInsetsHeight();
+ final Rect captionFrame = new Rect();
+ if (captionInsetsHeight != 0) {
+ captionFrame.set(mWinFrame.left, mWinFrame.top, mWinFrame.right,
+ mWinFrame.top + captionInsetsHeight);
+ }
+ if (mAttachInfo.mCaptionInsets.equals(captionFrame)) return false;
+ mAttachInfo.mCaptionInsets.set(captionFrame);
+ return true;
+ }
+
private boolean shouldDispatchCutout() {
return mWindowAttributes.layoutInDisplayCutoutMode
== LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS
@@ -2592,6 +2606,9 @@ public final class ViewRootImpl implements ViewParent,
mAttachInfo.mAlwaysConsumeSystemBars = mPendingAlwaysConsumeSystemBars;
dispatchApplyInsets = true;
}
+ if (updateCaptionInsets()) {
+ dispatchApplyInsets = true;
+ }
if (dispatchApplyInsets || mLastSystemUiVisibility !=
mAttachInfo.mSystemUiVisibility || mApplyInsetsRequested) {
mLastSystemUiVisibility = mAttachInfo.mSystemUiVisibility;
diff --git a/core/java/android/view/Window.java b/core/java/android/view/Window.java
index 0c5c18316e61..ae9afabad533 100644
--- a/core/java/android/view/Window.java
+++ b/core/java/android/view/Window.java
@@ -49,9 +49,6 @@ import android.transition.Transition;
import android.transition.TransitionManager;
import android.util.Pair;
import android.view.View.OnApplyWindowInsetsListener;
-import android.view.ViewGroup.LayoutParams;
-import android.view.WindowInsets.Side.InsetsSide;
-import android.view.WindowInsets.Type.InsetsType;
import android.view.accessibility.AccessibilityEvent;
import java.util.Collections;
@@ -323,7 +320,7 @@ public abstract class Window {
@UnsupportedAppUsage
private boolean mDestroyed;
- private boolean mOverlayWithDecorCaptionEnabled = false;
+ private boolean mOverlayWithDecorCaptionEnabled = true;
private boolean mCloseOnSwipeEnabled = false;
// The current window attributes.
diff --git a/core/java/android/view/WindowInsets.java b/core/java/android/view/WindowInsets.java
index fde184ccfb0e..9b2a6cbce48f 100644
--- a/core/java/android/view/WindowInsets.java
+++ b/core/java/android/view/WindowInsets.java
@@ -17,6 +17,7 @@
package android.view;
+import static android.view.WindowInsets.Type.CAPTION_BAR;
import static android.view.WindowInsets.Type.DISPLAY_CUTOUT;
import static android.view.WindowInsets.Type.FIRST;
import static android.view.WindowInsets.Type.IME;
diff --git a/core/java/android/view/WindowInsetsController.java b/core/java/android/view/WindowInsetsController.java
index 0282ecac8920..439223cf568b 100644
--- a/core/java/android/view/WindowInsetsController.java
+++ b/core/java/android/view/WindowInsetsController.java
@@ -196,6 +196,15 @@ public interface WindowInsetsController {
@Appearance int getSystemBarsAppearance();
/**
+ * Notify the caption insets height change. The information will be used on the client side to,
+ * make sure the InsetsState has the correct caption insets.
+ *
+ * @param height the height of caption bar insets.
+ * @hide
+ */
+ void setCaptionInsetsHeight(int height);
+
+ /**
* Controls the behavior of system bars.
*
* @param behavior Determines how the bars behave when being hidden by the application.
diff --git a/core/java/android/view/WindowManager.java b/core/java/android/view/WindowManager.java
index 77ce5c1b1ddc..cc380f32297e 100644
--- a/core/java/android/view/WindowManager.java
+++ b/core/java/android/view/WindowManager.java
@@ -781,8 +781,6 @@ public interface WindowManager extends ViewManager {
to = "BOOT_PROGRESS"),
@ViewDebug.IntToString(from = TYPE_INPUT_CONSUMER,
to = "INPUT_CONSUMER"),
- @ViewDebug.IntToString(from = TYPE_DREAM,
- to = "DREAM"),
@ViewDebug.IntToString(from = TYPE_NAVIGATION_BAR_PANEL,
to = "NAVIGATION_BAR_PANEL"),
@ViewDebug.IntToString(from = TYPE_DISPLAY_OVERLAY,
@@ -1105,13 +1103,6 @@ public interface WindowManager extends ViewManager {
public static final int TYPE_INPUT_CONSUMER = FIRST_SYSTEM_WINDOW+22;
/**
- * Window type: Dreams (screen saver) window, just above keyguard.
- * In multiuser systems shows only on the owning user's window.
- * @hide
- */
- public static final int TYPE_DREAM = FIRST_SYSTEM_WINDOW+23;
-
- /**
* Window type: Navigation bar panel (when navigation bar is distinct from status bar)
* In multiuser systems shows on all users' windows.
* @hide
@@ -1180,8 +1171,9 @@ public interface WindowManager extends ViewManager {
public static final int TYPE_QS_DIALOG = FIRST_SYSTEM_WINDOW+35;
/**
- * Window type: shares similar characteristics with {@link #TYPE_DREAM}. The layer is
+ * Window type: shows directly above the keyguard. The layer is
* reserved for screenshot region selection. These windows must not take input focus.
+ * In multiuser systems shows only on the owning user's window.
* @hide
*/
public static final int TYPE_SCREENSHOT = FIRST_SYSTEM_WINDOW + 36;
diff --git a/core/java/android/view/autofill/AutofillManager.java b/core/java/android/view/autofill/AutofillManager.java
index 267a5a6561af..83a79344917c 100644
--- a/core/java/android/view/autofill/AutofillManager.java
+++ b/core/java/android/view/autofill/AutofillManager.java
@@ -41,7 +41,9 @@ import android.graphics.Rect;
import android.metrics.LogMaker;
import android.os.Build;
import android.os.Bundle;
+import android.os.Handler;
import android.os.IBinder;
+import android.os.Looper;
import android.os.Parcelable;
import android.os.RemoteException;
import android.os.SystemClock;
@@ -63,6 +65,7 @@ import android.view.accessibility.AccessibilityManager;
import android.view.accessibility.AccessibilityNodeInfo;
import android.view.accessibility.AccessibilityNodeProvider;
import android.view.accessibility.AccessibilityWindowInfo;
+import android.view.inputmethod.InputMethodManager;
import android.widget.EditText;
import android.widget.TextView;
@@ -2444,6 +2447,44 @@ public final class AutofillManager {
}
}
+ private void requestShowSoftInput(@NonNull AutofillId id) {
+ if (sVerbose) Log.v(TAG, "requestShowSoftInput(" + id + ")");
+ final AutofillClient client = getClient();
+ if (client == null) {
+ return;
+ }
+ final View view = client.autofillClientFindViewByAutofillIdTraversal(id);
+ if (view == null) {
+ if (sVerbose) Log.v(TAG, "View is not found");
+ return;
+ }
+ final Handler handler = view.getHandler();
+ if (handler == null) {
+ if (sVerbose) Log.v(TAG, "Ignoring requestShowSoftInput due to no handler in view");
+ return;
+ }
+ if (handler.getLooper() != Looper.myLooper()) {
+ // The view is running on a different thread than our own, so we need to reschedule
+ // our work for over there.
+ if (sVerbose) Log.v(TAG, "Scheduling showSoftInput() on the view UI thread");
+ handler.post(() -> requestShowSoftInputInViewThread(view));
+ } else {
+ requestShowSoftInputInViewThread(view);
+ }
+ }
+
+ // This method must be called from within the View thread.
+ private static void requestShowSoftInputInViewThread(@NonNull View view) {
+ if (!view.isFocused()) {
+ Log.w(TAG, "Ignoring requestShowSoftInput() due to non-focused view");
+ return;
+ }
+ final InputMethodManager inputMethodManager = view.getContext().getSystemService(
+ InputMethodManager.class);
+ boolean ret = inputMethodManager.showSoftInput(view, /*flags=*/ 0);
+ if (sVerbose) Log.v(TAG, " InputMethodManager.showSoftInput returns " + ret);
+ }
+
/** @hide */
public void requestHideFillUi() {
requestHideFillUi(mIdShownFillUi, true);
@@ -3368,6 +3409,14 @@ public final class AutofillManager {
afm.post(() -> afm.getAugmentedAutofillClient(result));
}
}
+
+ @Override
+ public void requestShowSoftInput(@NonNull AutofillId id) {
+ final AutofillManager afm = mAfm.get();
+ if (afm != null) {
+ afm.post(() -> afm.requestShowSoftInput(id));
+ }
+ }
}
private static final class AugmentedAutofillManagerClient
diff --git a/core/java/android/view/autofill/IAutoFillManagerClient.aidl b/core/java/android/view/autofill/IAutoFillManagerClient.aidl
index 4371b3c54f94..87d65c223c25 100644
--- a/core/java/android/view/autofill/IAutoFillManagerClient.aidl
+++ b/core/java/android/view/autofill/IAutoFillManagerClient.aidl
@@ -117,4 +117,9 @@ oneway interface IAutoFillManagerClient {
* Notifies disables autofill for the app or activity.
*/
void notifyDisableAutofill(long disableDuration, in ComponentName componentName);
+
+ /**
+ * Requests to show the soft input method if the focus is on the given id.
+ */
+ void requestShowSoftInput(in AutofillId id);
}
diff --git a/core/java/android/view/contentcapture/ContentCaptureContext.java b/core/java/android/view/contentcapture/ContentCaptureContext.java
index 1692051924f4..b84cb88ccd84 100644
--- a/core/java/android/view/contentcapture/ContentCaptureContext.java
+++ b/core/java/android/view/contentcapture/ContentCaptureContext.java
@@ -15,7 +15,7 @@
*/
package android.view.contentcapture;
-import static android.view.contentcapture.ContentCaptureSession.NO_SESSION_ID;
+import static android.view.contentcapture.ContentCaptureManager.NO_SESSION_ID;
import android.annotation.IntDef;
import android.annotation.NonNull;
diff --git a/core/java/android/view/contentcapture/ContentCaptureEvent.java b/core/java/android/view/contentcapture/ContentCaptureEvent.java
index ea34d948c91a..f49b1beee8ad 100644
--- a/core/java/android/view/contentcapture/ContentCaptureEvent.java
+++ b/core/java/android/view/contentcapture/ContentCaptureEvent.java
@@ -16,7 +16,7 @@
package android.view.contentcapture;
import static android.view.contentcapture.ContentCaptureHelper.getSanitizedString;
-import static android.view.contentcapture.ContentCaptureSession.NO_SESSION_ID;
+import static android.view.contentcapture.ContentCaptureManager.NO_SESSION_ID;
import android.annotation.IntDef;
import android.annotation.NonNull;
diff --git a/core/java/android/view/contentcapture/ContentCaptureManager.java b/core/java/android/view/contentcapture/ContentCaptureManager.java
index b9889276ae0b..954b83b6f9ee 100644
--- a/core/java/android/view/contentcapture/ContentCaptureManager.java
+++ b/core/java/android/view/contentcapture/ContentCaptureManager.java
@@ -235,6 +235,13 @@ public final class ContentCaptureManager {
public static final int RESULT_CODE_SECURITY_EXCEPTION = -1;
/**
+ * ID used to indicate that a session does not exist
+ * @hide
+ */
+ @SystemApi
+ public static final int NO_SESSION_ID = 0;
+
+ /**
* Timeout for calls to system_server.
*/
private static final int SYNC_CALLS_TIMEOUT_MS = 5000;
diff --git a/core/java/android/view/contentcapture/ContentCaptureSession.java b/core/java/android/view/contentcapture/ContentCaptureSession.java
index 012f5e6d3507..39c7210d8dac 100644
--- a/core/java/android/view/contentcapture/ContentCaptureSession.java
+++ b/core/java/android/view/contentcapture/ContentCaptureSession.java
@@ -17,12 +17,12 @@ package android.view.contentcapture;
import static android.view.contentcapture.ContentCaptureHelper.sDebug;
import static android.view.contentcapture.ContentCaptureHelper.sVerbose;
+import static android.view.contentcapture.ContentCaptureManager.NO_SESSION_ID;
import android.annotation.CallSuper;
import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.Nullable;
-import android.annotation.SystemApi;
import android.graphics.Insets;
import android.util.DebugUtils;
import android.util.Log;
@@ -53,13 +53,6 @@ public abstract class ContentCaptureSession implements AutoCloseable {
private static final Random sIdGenerator = new Random();
/**
- * ID used to indicate that a session does not exist
- * @hide
- */
- @SystemApi
- public static final int NO_SESSION_ID = 0;
-
- /**
* Initial state, when there is no session.
*
* @hide
diff --git a/core/java/com/android/internal/os/Zygote.java b/core/java/com/android/internal/os/Zygote.java
index c75898994f3e..ff03f1a1a2ab 100644
--- a/core/java/com/android/internal/os/Zygote.java
+++ b/core/java/com/android/internal/os/Zygote.java
@@ -205,15 +205,9 @@ public final class Zygote {
/** List of packages with the same uid, and its app data info: volume uuid and inode. */
public static final String PKG_DATA_INFO_MAP = "--pkg-data-info-map";
- /** List of whitelisted packages and its app data info: volume uuid and inode. */
- public static final String WHITELISTED_DATA_INFO_MAP = "--whitelisted-data-info-map";
-
/** Bind mount app storage dirs to lower fs not via fuse */
public static final String BIND_MOUNT_APP_STORAGE_DIRS = "--bind-mount-storage-dirs";
- /** Bind mount app storage dirs to lower fs not via fuse */
- public static final String BIND_MOUNT_APP_DATA_DIRS = "--bind-mount-data-dirs";
-
/**
* An extraArg passed when a zygote process is forking a child-zygote, specifying a name
* in the abstract socket namespace. This socket name is what the new child zygote
@@ -319,8 +313,6 @@ public final class Zygote {
* @param isTopApp true if the process is for top (high priority) application.
* @param pkgDataInfoList A list that stores related packages and its app data
* info: volume uuid and inode.
- * @param whitelistedDataInfoList Like pkgDataInfoList, but it's for whitelisted apps.
- * @param bindMountAppDataDirs True if the zygote needs to mount data dirs.
* @param bindMountAppStorageDirs True if the zygote needs to mount storage dirs.
*
* @return 0 if this is the child, pid of the child
@@ -329,15 +321,13 @@ public final class Zygote {
static int forkAndSpecialize(int uid, int gid, int[] gids, int runtimeFlags,
int[][] rlimits, int mountExternal, String seInfo, String niceName, int[] fdsToClose,
int[] fdsToIgnore, boolean startChildZygote, String instructionSet, String appDataDir,
- boolean isTopApp, String[] pkgDataInfoList, String[] whitelistedDataInfoList,
- boolean bindMountAppDataDirs, boolean bindMountAppStorageDirs) {
+ boolean isTopApp, String[] pkgDataInfoList, boolean bindMountAppStorageDirs) {
ZygoteHooks.preFork();
int pid = nativeForkAndSpecialize(
uid, gid, gids, runtimeFlags, rlimits, mountExternal, seInfo, niceName, fdsToClose,
fdsToIgnore, startChildZygote, instructionSet, appDataDir, isTopApp,
- pkgDataInfoList, whitelistedDataInfoList, bindMountAppDataDirs,
- bindMountAppStorageDirs);
+ pkgDataInfoList, bindMountAppStorageDirs);
if (pid == 0) {
// Note that this event ends at the end of handleChildProc,
Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "PostFork");
@@ -354,7 +344,6 @@ public final class Zygote {
int runtimeFlags, int[][] rlimits, int mountExternal, String seInfo, String niceName,
int[] fdsToClose, int[] fdsToIgnore, boolean startChildZygote, String instructionSet,
String appDataDir, boolean isTopApp, String[] pkgDataInfoList,
- String[] whitelistedDataInfoList, boolean bindMountAppDataDirs,
boolean bindMountAppStorageDirs);
/**
@@ -382,19 +371,15 @@ public final class Zygote {
* volume uuid and CE dir inode. For example, pkgDataInfoList = [app_a_pkg_name,
* app_a_data_volume_uuid, app_a_ce_inode, app_b_pkg_name, app_b_data_volume_uuid,
* app_b_ce_inode, ...];
- * @param whitelistedDataInfoList Like pkgDataInfoList, but it's for whitelisted apps.
- * @param bindMountAppDataDirs True if the zygote needs to mount data dirs.
* @param bindMountAppStorageDirs True if the zygote needs to mount storage dirs.
*/
private static void specializeAppProcess(int uid, int gid, int[] gids, int runtimeFlags,
int[][] rlimits, int mountExternal, String seInfo, String niceName,
boolean startChildZygote, String instructionSet, String appDataDir, boolean isTopApp,
- String[] pkgDataInfoList, String[] whitelistedDataInfoList,
- boolean bindMountAppDataDirs, boolean bindMountAppStorageDirs) {
+ String[] pkgDataInfoList, boolean bindMountAppStorageDirs) {
nativeSpecializeAppProcess(uid, gid, gids, runtimeFlags, rlimits, mountExternal, seInfo,
niceName, startChildZygote, instructionSet, appDataDir, isTopApp,
- pkgDataInfoList, whitelistedDataInfoList,
- bindMountAppDataDirs, bindMountAppStorageDirs);
+ pkgDataInfoList, bindMountAppStorageDirs);
// Note that this event ends at the end of handleChildProc.
Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "PostFork");
@@ -414,8 +399,7 @@ public final class Zygote {
private static native void nativeSpecializeAppProcess(int uid, int gid, int[] gids,
int runtimeFlags, int[][] rlimits, int mountExternal, String seInfo, String niceName,
boolean startChildZygote, String instructionSet, String appDataDir, boolean isTopApp,
- String[] pkgDataInfoList, String[] whitelistedDataInfoList,
- boolean bindMountAppDataDirs, boolean bindMountAppStorageDirs);
+ String[] pkgDataInfoList, boolean bindMountAppStorageDirs);
/**
* Called to do any initialization before starting an application.
@@ -740,8 +724,7 @@ public final class Zygote {
args.mRuntimeFlags, rlimits, args.mMountExternal,
args.mSeInfo, args.mNiceName, args.mStartChildZygote,
args.mInstructionSet, args.mAppDataDir, args.mIsTopApp,
- args.mPkgDataInfoList, args.mWhitelistedDataInfoList,
- args.mBindMountAppDataDirs, args.mBindMountAppStorageDirs);
+ args.mPkgDataInfoList, args.mBindMountAppStorageDirs);
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
diff --git a/core/java/com/android/internal/os/ZygoteArguments.java b/core/java/com/android/internal/os/ZygoteArguments.java
index 94c1f71a26db..1a63765fcaa6 100644
--- a/core/java/com/android/internal/os/ZygoteArguments.java
+++ b/core/java/com/android/internal/os/ZygoteArguments.java
@@ -227,22 +227,11 @@ class ZygoteArguments {
String[] mPkgDataInfoList;
/**
- * A list that stores all whitelisted app data info: volume uuid and inode.
- * Null if it does need to do app data isolation.
- */
- String[] mWhitelistedDataInfoList;
-
- /**
* @see Zygote#BIND_MOUNT_APP_STORAGE_DIRS
*/
boolean mBindMountAppStorageDirs;
/**
- * @see Zygote#BIND_MOUNT_APP_DATA_DIRS
- */
- boolean mBindMountAppDataDirs;
-
- /**
* Constructs instance and parses args
*
* @param args zygote command-line args
@@ -463,12 +452,8 @@ class ZygoteArguments {
}
} else if (arg.startsWith(Zygote.PKG_DATA_INFO_MAP)) {
mPkgDataInfoList = getAssignmentList(arg);
- } else if (arg.startsWith(Zygote.WHITELISTED_DATA_INFO_MAP)) {
- mWhitelistedDataInfoList = getAssignmentList(arg);
} else if (arg.equals(Zygote.BIND_MOUNT_APP_STORAGE_DIRS)) {
mBindMountAppStorageDirs = true;
- } else if (arg.equals(Zygote.BIND_MOUNT_APP_DATA_DIRS)) {
- mBindMountAppDataDirs = true;
} else {
break;
}
diff --git a/core/java/com/android/internal/os/ZygoteConnection.java b/core/java/com/android/internal/os/ZygoteConnection.java
index 6e880d43b73e..bc8dfd4aa402 100644
--- a/core/java/com/android/internal/os/ZygoteConnection.java
+++ b/core/java/com/android/internal/os/ZygoteConnection.java
@@ -258,8 +258,7 @@ class ZygoteConnection {
parsedArgs.mRuntimeFlags, rlimits, parsedArgs.mMountExternal, parsedArgs.mSeInfo,
parsedArgs.mNiceName, fdsToClose, fdsToIgnore, parsedArgs.mStartChildZygote,
parsedArgs.mInstructionSet, parsedArgs.mAppDataDir, parsedArgs.mIsTopApp,
- parsedArgs.mPkgDataInfoList,parsedArgs.mWhitelistedDataInfoList,
- parsedArgs.mBindMountAppDataDirs, parsedArgs.mBindMountAppStorageDirs);
+ parsedArgs.mPkgDataInfoList, parsedArgs.mBindMountAppStorageDirs);
try {
if (pid == 0) {
diff --git a/core/java/com/android/internal/policy/DecorView.java b/core/java/com/android/internal/policy/DecorView.java
index 51b73fc674e7..d2508f3616e4 100644
--- a/core/java/com/android/internal/policy/DecorView.java
+++ b/core/java/com/android/internal/policy/DecorView.java
@@ -78,7 +78,6 @@ import android.view.ContextThemeWrapper;
import android.view.Gravity;
import android.view.InputQueue;
import android.view.InsetsState;
-import android.view.InsetsController;
import android.view.InsetsState.InternalInsetsType;
import android.view.KeyEvent;
import android.view.KeyboardShortcutGroup;
@@ -1174,6 +1173,12 @@ public class DecorView extends FrameLayout implements RootViewSurfaceTaker, Wind
false /* matchVertical */, statusBarNeedsLeftInset, statusBarSideInset,
animate && !disallowAnimate,
mForceWindowDrawsBarBackgrounds, state);
+
+ if (mHasCaption) {
+ final int captionColor = calculateStatusBarColor();
+ mDecorCaptionView.getCaption().setBackgroundColor(captionColor);
+ updateDecorCaptionShade();
+ }
}
// When we expand the window with FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS or
@@ -1355,7 +1360,7 @@ public class DecorView extends FrameLayout implements RootViewSurfaceTaker, Wind
: state.attributes.isPresent(insetsState, mWindow.getAttributes().flags, force);
boolean show = state.attributes.isVisible(state.present, color,
mWindow.getAttributes().flags, force);
- boolean showView = show && !isResizing() && size > 0;
+ boolean showView = show && !isResizing() && !mHasCaption && size > 0;
boolean visibilityChanged = false;
View view = state.view;
@@ -2021,6 +2026,7 @@ public class DecorView extends FrameLayout implements RootViewSurfaceTaker, Wind
if (getForeground() != null) {
drawableChanged();
}
+ getWindowInsetsController().setCaptionInsetsHeight(getCaptionInsetsHeight());
}
}
@@ -2094,6 +2100,7 @@ public class DecorView extends FrameLayout implements RootViewSurfaceTaker, Wind
mDecorCaptionView.onConfigurationChanged(displayWindowDecor);
enableCaption(displayWindowDecor);
}
+ getWindowInsetsController().setCaptionInsetsHeight(getCaptionInsetsHeight());
}
void onResourcesLoaded(LayoutInflater inflater, int layoutResource) {
@@ -2182,11 +2189,11 @@ public class DecorView extends FrameLayout implements RootViewSurfaceTaker, Wind
inflater = inflater.from(context);
final DecorCaptionView view = (DecorCaptionView) inflater.inflate(R.layout.decor_caption,
null);
- setDecorCaptionShade(context, view);
+ setDecorCaptionShade(view);
return view;
}
- private void setDecorCaptionShade(Context context, DecorCaptionView view) {
+ private void setDecorCaptionShade(DecorCaptionView view) {
final int shade = mWindow.getDecorCaptionShade();
switch (shade) {
case DECOR_CAPTION_SHADE_LIGHT:
@@ -2196,15 +2203,10 @@ public class DecorView extends FrameLayout implements RootViewSurfaceTaker, Wind
setDarkDecorCaptionShade(view);
break;
default: {
- TypedValue value = new TypedValue();
- context.getTheme().resolveAttribute(R.attr.colorPrimary, value, true);
- // We invert the shade depending on brightness of the theme. Dark shade for light
- // theme and vice versa. Thanks to this the buttons should be visible on the
- // background.
- if (Color.luminance(value.data) < 0.5) {
- setLightDecorCaptionShade(view);
- } else {
+ if ((getWindowSystemUiVisibility() & SYSTEM_UI_FLAG_LIGHT_STATUS_BAR) != 0) {
setDarkDecorCaptionShade(view);
+ } else {
+ setLightDecorCaptionShade(view);
}
break;
}
@@ -2213,7 +2215,7 @@ public class DecorView extends FrameLayout implements RootViewSurfaceTaker, Wind
void updateDecorCaptionShade() {
if (mDecorCaptionView != null) {
- setDecorCaptionShade(getContext(), mDecorCaptionView);
+ setDecorCaptionShade(mDecorCaptionView);
}
}
@@ -2484,6 +2486,15 @@ public class DecorView extends FrameLayout implements RootViewSurfaceTaker, Wind
}
/**
+ * @hide
+ * @return the height of insets covering the top of window content area.
+ */
+ public int getCaptionInsetsHeight() {
+ if (!mWindow.isOverlayWithDecorCaptionEnabled()) return 0;
+ return getCaptionHeight();
+ }
+
+ /**
* Converts a DIP measure into physical pixels.
* @param dip The dip value.
* @return Returns the number of pixels.
diff --git a/core/java/com/android/internal/widget/DecorCaptionView.java b/core/java/com/android/internal/widget/DecorCaptionView.java
index b5d787c24fbd..7a01024ffc36 100644
--- a/core/java/com/android/internal/widget/DecorCaptionView.java
+++ b/core/java/com/android/internal/widget/DecorCaptionView.java
@@ -17,7 +17,6 @@
package com.android.internal.widget;
import android.content.Context;
-import android.graphics.Color;
import android.graphics.Rect;
import android.os.RemoteException;
import android.util.AttributeSet;
@@ -53,8 +52,7 @@ import java.util.ArrayList;
* <li>..</li>
* </ul>
*
- * Although this ViewGroup has only two direct sub-Views, its behavior is more complex due to
- * overlaying caption on the content and drawing.
+ * Here describe the behavior of overlaying caption on the content and drawing.
*
* First, no matter where the content View gets added, it will always be the first child and the
* caption will be the second. This way the caption will always be drawn on top of the content when
@@ -66,11 +64,9 @@ import java.util.ArrayList;
* <li>DecorCaptionView.onInterceptTouchEvent() will try intercepting the touch events if the
* down action is performed on top close or maximize buttons; the reason for that is we want these
* buttons to always work.</li>
- * <li>The content View will receive the touch event. Mind that content is actually underneath the
- * caption, so we need to introduce our own dispatch ordering. We achieve this by overriding
- * {@link #buildTouchDispatchChildList()}.</li>
- * <li>If the touch event is not consumed by the content View, it will go to the caption View
- * and the dragging logic will be executed.</li>
+ * <li>The caption view will try to consume the event to apply the dragging logic.</li>
+ * <li>If the touch event is not consumed by the caption, the content View will receive the touch
+ * event</li>
* </ul>
*/
public class DecorCaptionView extends ViewGroup implements View.OnTouchListener,
@@ -137,11 +133,6 @@ public class DecorCaptionView extends ViewGroup implements View.OnTouchListener,
mOwner = owner;
mShow = show;
mOverlayWithAppContent = owner.isOverlayWithDecorCaptionEnabled();
- if (mOverlayWithAppContent) {
- // The caption is covering the content, so we make its background transparent to make
- // the content visible.
- mCaption.setBackgroundColor(Color.TRANSPARENT);
- }
updateCaptionVisibility();
// By changing the outline provider to BOUNDS, the window can remove its
// background without removing the shadow.
@@ -236,18 +227,6 @@ public class DecorCaptionView extends ViewGroup implements View.OnTouchListener,
}
@Override
- public ArrayList<View> buildTouchDispatchChildList() {
- mTouchDispatchList.ensureCapacity(3);
- if (mCaption != null) {
- mTouchDispatchList.add(mCaption);
- }
- if (mContent != null) {
- mTouchDispatchList.add(mContent);
- }
- return mTouchDispatchList;
- }
-
- @Override
public boolean shouldDelayChildPressedState() {
return false;
}
diff --git a/core/jni/android_util_AssetManager.cpp b/core/jni/android_util_AssetManager.cpp
index cb5a332c6e85..bf3fc5704739 100644
--- a/core/jni/android_util_AssetManager.cpp
+++ b/core/jni/android_util_AssetManager.cpp
@@ -214,12 +214,8 @@ static jint CopyValue(JNIEnv* env, ApkAssetsCookie cookie, const Res_value& valu
// ----------------------------------------------------------------------------
-static std::unique_ptr<DynamicLibManager> sDynamicLibManager =
- std::make_unique<DynamicLibManager>();
-
// Let the opaque type AAssetManager refer to a guarded AssetManager2 instance.
struct GuardedAssetManager : public ::AAssetManager {
- GuardedAssetManager() : guarded_assetmanager(sDynamicLibManager.get()) {}
Guarded<AssetManager2> guarded_assetmanager;
};
diff --git a/core/jni/com_android_internal_os_Zygote.cpp b/core/jni/com_android_internal_os_Zygote.cpp
index aa2d1b5fa02b..ea3c0fa9fc3c 100644
--- a/core/jni/com_android_internal_os_Zygote.cpp
+++ b/core/jni/com_android_internal_os_Zygote.cpp
@@ -110,6 +110,7 @@ using android::base::StringAppendF;
using android::base::StringPrintf;
using android::base::WriteStringToFile;
using android::base::GetBoolProperty;
+using android::base::GetProperty;
#define CREATE_ERROR(...) StringPrintf("%s:%d: ", __FILE__, __LINE__). \
append(StringPrintf(__VA_ARGS__))
@@ -169,6 +170,18 @@ static int gSystemServerSocketFd = -1;
static constexpr int DEFAULT_DATA_DIR_PERMISSION = 0751;
+/**
+ * Property to control if app data isolation is enabled.
+ */
+static const std::string ANDROID_APP_DATA_ISOLATION_ENABLED_PROPERTY =
+ "persist.zygote.app_data_isolation";
+
+/**
+ * Property to enable app data isolation for sdcard obb or data in vold.
+ */
+static const std::string ANDROID_VOLD_APP_DATA_ISOLATION_ENABLED_PROPERTY =
+ "persist.sys.vold_app_data_isolation_enabled";
+
static constexpr const uint64_t UPPER_HALF_WORD_MASK = 0xFFFF'FFFF'0000'0000;
static constexpr const uint64_t LOWER_HALF_WORD_MASK = 0x0000'0000'FFFF'FFFF;
@@ -1306,13 +1319,20 @@ static void relabelAllDirs(const char* path, security_context_t context, fail_fn
* be decrypted after storage is decrypted.
*
*/
-static void isolateAppData(JNIEnv* env, const std::vector<std::string>& merged_data_info_list,
- uid_t uid, const char* process_name,
- jstring managed_nice_name, fail_fn_t fail_fn) {
+static void isolateAppData(JNIEnv* env, jobjectArray pkg_data_info_list,
+ uid_t uid, const char* process_name, jstring managed_nice_name,
+ fail_fn_t fail_fn) {
const userid_t userId = multiuser_get_user_id(uid);
- int size = merged_data_info_list.size();
+ auto extract_fn = std::bind(ExtractJString, env, process_name, managed_nice_name, _1);
+
+ int size = (pkg_data_info_list != nullptr) ? env->GetArrayLength(pkg_data_info_list) : 0;
+ // Size should be a multiple of 3, as it contains list of <package_name, volume_uuid, inode>
+ if ((size % 3) != 0) {
+ fail_fn(CREATE_ERROR("Wrong pkg_inode_list size %d", size));
+ }
+ ensureInAppMountNamespace(fail_fn);
// Mount tmpfs on all possible data directories, so app no longer see the original apps data.
char internalCePath[PATH_MAX];
@@ -1357,10 +1377,14 @@ static void isolateAppData(JNIEnv* env, const std::vector<std::string>& merged_d
bool legacySymlinkCreated = false;
for (int i = 0; i < size; i += 3) {
- std::string const & packageName = merged_data_info_list[i];
- std::string const & volUuid = merged_data_info_list[i + 1];
- std::string const & inode = merged_data_info_list[i + 2];
+ jstring package_str = (jstring) (env->GetObjectArrayElement(pkg_data_info_list, i));
+ std::string packageName = extract_fn(package_str).value();
+ jstring vol_str = (jstring) (env->GetObjectArrayElement(pkg_data_info_list, i + 1));
+ std::string volUuid = extract_fn(vol_str).value();
+
+ jstring inode_str = (jstring) (env->GetObjectArrayElement(pkg_data_info_list, i + 2));
+ std::string inode = extract_fn(inode_str).value();
std::string::size_type sz;
long long ceDataInode = std::stoll(inode, &sz);
@@ -1458,48 +1482,6 @@ static void isolateAppData(JNIEnv* env, const std::vector<std::string>& merged_d
freecon(dataDataContext);
}
-static void insertPackagesToMergedList(JNIEnv* env,
- std::vector<std::string>& merged_data_info_list,
- jobjectArray data_info_list, const char* process_name,
- jstring managed_nice_name, fail_fn_t fail_fn) {
-
- auto extract_fn = std::bind(ExtractJString, env, process_name, managed_nice_name, _1);
-
- int size = (data_info_list != nullptr) ? env->GetArrayLength(data_info_list) : 0;
- // Size should be a multiple of 3, as it contains list of <package_name, volume_uuid, inode>
- if ((size % 3) != 0) {
- fail_fn(CREATE_ERROR("Wrong data_info_list size %d", size));
- }
-
- for (int i = 0; i < size; i += 3) {
- jstring package_str = (jstring) (env->GetObjectArrayElement(data_info_list, i));
- std::string packageName = extract_fn(package_str).value();
- merged_data_info_list.push_back(packageName);
-
- jstring vol_str = (jstring) (env->GetObjectArrayElement(data_info_list, i + 1));
- std::string volUuid = extract_fn(vol_str).value();
- merged_data_info_list.push_back(volUuid);
-
- jstring inode_str = (jstring) (env->GetObjectArrayElement(data_info_list, i + 2));
- std::string inode = extract_fn(inode_str).value();
- merged_data_info_list.push_back(inode);
- }
-}
-
-static void isolateAppData(JNIEnv* env, jobjectArray pkg_data_info_list,
- jobjectArray whitelisted_data_info_list, uid_t uid, const char* process_name,
- jstring managed_nice_name, fail_fn_t fail_fn) {
-
- ensureInAppMountNamespace(fail_fn);
- std::vector<std::string> merged_data_info_list;
- insertPackagesToMergedList(env, merged_data_info_list, pkg_data_info_list,
- process_name, managed_nice_name, fail_fn);
- insertPackagesToMergedList(env, merged_data_info_list, whitelisted_data_info_list,
- process_name, managed_nice_name, fail_fn);
-
- isolateAppData(env, merged_data_info_list, uid, process_name, managed_nice_name, fail_fn);
-}
-
/**
* Like isolateAppData(), isolate jit profile directories, so apps don't see what
* other apps are installed by reading content inside /data/misc/profiles/cur.
@@ -1612,9 +1594,7 @@ static void SpecializeCommon(JNIEnv* env, uid_t uid, gid_t gid, jintArray gids,
jstring managed_nice_name, bool is_system_server,
bool is_child_zygote, jstring managed_instruction_set,
jstring managed_app_data_dir, bool is_top_app,
- jobjectArray pkg_data_info_list,
- jobjectArray whitelisted_data_info_list,
- bool mount_data_dirs, bool mount_storage_dirs) {
+ jobjectArray pkg_data_info_list, bool mount_storage_dirs) {
const char* process_name = is_system_server ? "system_server" : "zygote";
auto fail_fn = std::bind(ZygoteFailure, env, process_name, managed_nice_name, _1);
auto extract_fn = std::bind(ExtractJString, env, process_name, managed_nice_name, _1);
@@ -1648,9 +1628,9 @@ static void SpecializeCommon(JNIEnv* env, uid_t uid, gid_t gid, jintArray gids,
// give a null in same_uid_pkgs and private_volumes so they don't need app data isolation.
// Isolated process / webview / app zygote should be gated by SELinux and file permission
// so they can't even traverse CE / DE directories.
- if (mount_data_dirs) {
- isolateAppData(env, pkg_data_info_list, whitelisted_data_info_list,
- uid, process_name, managed_nice_name, fail_fn);
+ if (pkg_data_info_list != nullptr
+ && GetBoolProperty(ANDROID_APP_DATA_ISOLATION_ENABLED_PROPERTY, true)) {
+ isolateAppData(env, pkg_data_info_list, uid, process_name, managed_nice_name, fail_fn);
isolateJitProfile(env, pkg_data_info_list, uid, process_name, managed_nice_name, fail_fn);
}
if ((mount_external != MOUNT_EXTERNAL_INSTALLER) && mount_storage_dirs) {
@@ -2023,8 +2003,7 @@ static jint com_android_internal_os_Zygote_nativeForkAndSpecialize(
jint mount_external, jstring se_info, jstring nice_name,
jintArray managed_fds_to_close, jintArray managed_fds_to_ignore, jboolean is_child_zygote,
jstring instruction_set, jstring app_data_dir, jboolean is_top_app,
- jobjectArray pkg_data_info_list, jobjectArray whitelisted_data_info_list,
- jboolean mount_data_dirs, jboolean mount_storage_dirs) {
+ jobjectArray pkg_data_info_list, jboolean mount_storage_dirs) {
jlong capabilities = CalculateCapabilities(env, uid, gid, gids, is_child_zygote);
if (UNLIKELY(managed_fds_to_close == nullptr)) {
@@ -2062,8 +2041,6 @@ static jint com_android_internal_os_Zygote_nativeForkAndSpecialize(
mount_external, se_info, nice_name, false,
is_child_zygote == JNI_TRUE, instruction_set, app_data_dir,
is_top_app == JNI_TRUE, pkg_data_info_list,
- whitelisted_data_info_list,
- mount_data_dirs == JNI_TRUE,
mount_storage_dirs == JNI_TRUE);
}
return pid;
@@ -2099,8 +2076,7 @@ static jint com_android_internal_os_Zygote_nativeForkSystemServer(
permitted_capabilities, effective_capabilities,
MOUNT_EXTERNAL_DEFAULT, nullptr, nullptr, true,
false, nullptr, nullptr, /* is_top_app= */ false,
- /* pkg_data_info_list */ nullptr,
- /* whitelisted_data_info_list */ nullptr, false, false);
+ /* pkg_data_info_list */ nullptr, false);
} else if (pid > 0) {
// The zygote process checks whether the child process has died or not.
ALOGI("System server process %d has been created", pid);
@@ -2230,16 +2206,15 @@ static void com_android_internal_os_Zygote_nativeSpecializeAppProcess(
jint runtime_flags, jobjectArray rlimits,
jint mount_external, jstring se_info, jstring nice_name,
jboolean is_child_zygote, jstring instruction_set, jstring app_data_dir, jboolean is_top_app,
- jobjectArray pkg_data_info_list, jobjectArray whitelisted_data_info_list,
- jboolean mount_data_dirs, jboolean mount_storage_dirs) {
+ jobjectArray pkg_data_info_list, jboolean mount_storage_dirs) {
jlong capabilities = CalculateCapabilities(env, uid, gid, gids, is_child_zygote);
SpecializeCommon(env, uid, gid, gids, runtime_flags, rlimits,
capabilities, capabilities,
mount_external, se_info, nice_name, false,
is_child_zygote == JNI_TRUE, instruction_set, app_data_dir,
- is_top_app == JNI_TRUE, pkg_data_info_list, whitelisted_data_info_list,
- mount_data_dirs == JNI_TRUE, mount_storage_dirs == JNI_TRUE);
+ is_top_app == JNI_TRUE, pkg_data_info_list,
+ mount_storage_dirs == JNI_TRUE);
}
/**
@@ -2433,7 +2408,7 @@ static jint com_android_internal_os_Zygote_nativeParseSigChld(JNIEnv* env, jclas
static const JNINativeMethod gMethods[] = {
{"nativeForkAndSpecialize",
"(II[II[[IILjava/lang/String;Ljava/lang/String;[I[IZLjava/lang/String;Ljava/lang/"
- "String;Z[Ljava/lang/String;[Ljava/lang/String;ZZ)I",
+ "String;Z[Ljava/lang/String;Z)I",
(void*)com_android_internal_os_Zygote_nativeForkAndSpecialize},
{"nativeForkSystemServer", "(II[II[[IJJ)I",
(void*)com_android_internal_os_Zygote_nativeForkSystemServer},
@@ -2446,7 +2421,7 @@ static const JNINativeMethod gMethods[] = {
{"nativeForkUsap", "(II[IZ)I", (void*)com_android_internal_os_Zygote_nativeForkUsap},
{"nativeSpecializeAppProcess",
"(II[II[[IILjava/lang/String;Ljava/lang/String;ZLjava/lang/String;Ljava/lang/"
- "String;Z[Ljava/lang/String;[Ljava/lang/String;ZZ)V",
+ "String;Z[Ljava/lang/String;Z)V",
(void*)com_android_internal_os_Zygote_nativeSpecializeAppProcess},
{"nativeInitNativeState", "(Z)V",
(void*)com_android_internal_os_Zygote_nativeInitNativeState},
diff --git a/core/proto/android/providers/settings/secure.proto b/core/proto/android/providers/settings/secure.proto
index a3313b21131d..075aa97edb58 100644
--- a/core/proto/android/providers/settings/secure.proto
+++ b/core/proto/android/providers/settings/secure.proto
@@ -77,7 +77,7 @@ message SecureSettingsProto {
optional SettingProto interactive_ui_timeout_ms = 33 [ (android.privacy).dest = DEST_AUTOMATIC ];
// Settings for magnification mode
optional SettingProto accessibility_magnification_mode = 34 [ (android.privacy).dest = DEST_AUTOMATIC ];
- optional SettingProto button_long_press_targets = 35 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto button_targets = 35 [ (android.privacy).dest = DEST_AUTOMATIC ];
}
optional Accessibility accessibility = 2;
@@ -180,6 +180,14 @@ message SecureSettingsProto {
optional SettingProto cmas_additional_broadcast_pkg = 14 [ (android.privacy).dest = DEST_AUTOMATIC ];
repeated SettingProto completed_categories = 15;
optional SettingProto connectivity_release_pending_intent_delay_ms = 16 [ (android.privacy).dest = DEST_AUTOMATIC ];
+
+ message Controls {
+ option (android.msg_privacy).dest = DEST_EXPLICIT;
+
+ optional SettingProto enabled = 1 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ }
+ optional Controls controls = 79;
+
optional SettingProto device_paired = 17 [ (android.privacy).dest = DEST_AUTOMATIC ];
optional SettingProto dialer_default_application = 18 [ (android.privacy).dest = DEST_AUTOMATIC ];
optional SettingProto display_density_forced = 19 [ (android.privacy).dest = DEST_AUTOMATIC ];
@@ -580,5 +588,5 @@ message SecureSettingsProto {
// Please insert fields in alphabetical order and group them into messages
// if possible (to avoid reaching the method limit).
- // Next tag = 79;
+ // Next tag = 80;
}
diff --git a/core/res/res/values/attrs_manifest.xml b/core/res/res/values/attrs_manifest.xml
index 28eb98b07690..2a2da6a45857 100644
--- a/core/res/res/values/attrs_manifest.xml
+++ b/core/res/res/values/attrs_manifest.xml
@@ -1827,6 +1827,9 @@
<attr name="gwpAsanMode" />
+ <!-- @hide no longer used, kept to preserve padding -->
+ <attr name="allowAutoRevokePermissionsExemption" format="boolean" />
+
<attr name="autoRevokePermissions">
<enum name="allowed" value="0" />
<enum name="discouraged" value="1" />
@@ -2113,35 +2116,6 @@
<declare-styleable name="AndroidManifestQueriesProvider" parent="AndroidManifestQueries" >
<attr name="authorities" />
</declare-styleable>
- <!--
- Matches an overlayable, its overlays, its actor, and/or its containing target.
- A target or actor must always be specified, but can be combined for more specificity.
- Valid combinations and what they match are:
-
- targetPackage:
- - All overlays targeting any overlayables inside 'targetPackage'
-
- targetPackage + targetName:
- - All overlays targeting the overlayable 'targetName' inside 'targetPackage'
-
- targetPackage + targetName + actor:
- - All overlays targeting the overlayable 'targetName' inside 'targetPackage' if the
- overlayable specifies 'actor'
-
- targetPackage + actor:
- - All overlays targeting overlayables inside 'targetPackage' that specify `actor`
- - The actor itself if the above matches
-
- actor:
- - All overlays targeting overlayables that specify `actor`
- - All targets that contain an overlayable that specifies `actor`
- - The actor itself
- -->
- <declare-styleable name="AndroidManifestQueriesOverlayable">
- <attr name="targetPackage" />
- <attr name="targetName"/>
- <attr name="actor" format="string" />
- </declare-styleable>
<!-- The <code>static-library</code> tag declares that this apk is providing itself
diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml
index e3a73377e365..acda77f185fd 100644
--- a/core/res/res/values/config.xml
+++ b/core/res/res/values/config.xml
@@ -2779,6 +2779,10 @@
<string name="config_systemUIServiceComponent" translatable="false"
>com.android.systemui/com.android.systemui.SystemUIService</string>
+ <!-- Package handling Quick controls -->
+ <string name="config_controlsPackage" translatable="false"
+ >com.android.systemui</string>
+
<!-- Keyguard component -->
<string name="config_keyguardComponent" translatable="false"
>com.android.systemui/com.android.systemui.keyguard.KeyguardService</string>
@@ -4424,4 +4428,7 @@
<!-- Set to true to enable the user switcher on the keyguard. -->
<bool name="config_keyguardUserSwitcher">false</bool>
+ <!-- Set to true to make assistant show in front of the dream/screensaver. -->
+ <bool name="config_assistantOnTopOfDream">false</bool>
+
</resources>
diff --git a/core/res/res/values/public.xml b/core/res/res/values/public.xml
index e694e160009e..67d20da03925 100644
--- a/core/res/res/values/public.xml
+++ b/core/res/res/values/public.xml
@@ -3014,11 +3014,12 @@
<!-- @hide @SystemApi -->
<public name="minExtensionVersion" />
<public name="allowNativeHeapPointerTagging" />
+ <!-- @hide no longer used, kept to preserve padding -->
+ <public name="allowAutoRevokePermissionsExemption"/>
<public name="autoRevokePermissions" />
<public name="preserveLegacyExternalStorage" />
<public name="mimeGroup" />
<public name="gwpAsanMode" />
- <public name="actor" />
</public-group>
<public-group type="drawable" first-id="0x010800b5">
diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml
index 5b880365657c..e2e65dd465ae 100644
--- a/core/res/res/values/strings.xml
+++ b/core/res/res/values/strings.xml
@@ -1138,17 +1138,17 @@
<!-- Title of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
<string name="permlab_accessFineLocation">access precise location only in the foreground</string>
<!-- Description of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
- <string name="permdesc_accessFineLocation">This app can get your exact location only when it is in the foreground. Location services must be turned on and available on your device for the app to be able to use them. This may increase battery consumption.</string>
+ <string name="permdesc_accessFineLocation">This app can get your precise location from location services while the app is in use. Location services for your device must be turned on for the app to get location. This may increase battery usage.</string>
<!-- Title of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
<string name="permlab_accessCoarseLocation">access approximate location only in the foreground</string>
<!-- Description of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
- <string name="permdesc_accessCoarseLocation">This app can get your approximate location only when it is in the foreground. Location services must be turned on and available on your device for the app to be able to use them.</string>
+ <string name="permdesc_accessCoarseLocation">This app can get your approximate location from location services while the app is in use. Location services for your device must be turned on for the app to get location.</string>
<!-- Title of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
<string name="permlab_accessBackgroundLocation">access location in the background</string>
<!-- Description of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
- <string name="permdesc_accessBackgroundLocation">This app can access location while running in the background, in addition to foreground location access.</string>
+ <string name="permdesc_accessBackgroundLocation">This app can access location at any time, even while the app is not in use.</string>
<!-- Title of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
<string name="permlab_modifyAudioSettings">change your audio settings</string>
@@ -3597,6 +3597,8 @@
<string name="ext_media_new_notification_title">New <xliff:g id="name" example="SD card">%s</xliff:g></string>
<!-- Notification body when new external media is detected [CHAR LIMIT=NONE] -->
<string name="ext_media_new_notification_message">Tap to set up</string>
+ <!-- Automotive specific notification body when new external media is detected. Empty because there is no fix action (b/151671685) [CHAR LIMIT=NONE] -->
+ <string name="ext_media_new_notification_message" product="automotive"></string>
<!-- Notification body when external media is ready for use [CHAR LIMIT=NONE] -->
<string name="ext_media_ready_notification_message">For transferring photos and media</string>
@@ -3605,8 +3607,10 @@
<string name="ext_media_unmountable_notification_title">Issue with <xliff:g id="name" example="SD card">%s</xliff:g></string>
<!-- Notification body when external media is unmountable (corrupt) [CHAR LIMIT=NONE] -->
<string name="ext_media_unmountable_notification_message">Tap to fix</string>
- <!-- TV-specifiv notification body when external media is unmountable (corrupt) [CHAR LIMIT=NONE] -->
+ <!-- TV-specific notification body when external media is unmountable (corrupt) [CHAR LIMIT=NONE] -->
<string name="ext_media_unmountable_notification_message" product="tv"><xliff:g id="name" example="SD card">%s</xliff:g> is corrupt. Select to fix.</string>
+ <!-- Automotive specific notification body when external media is unmountable (corrupt). Empty because there is no fix action (b/151671685) [CHAR LIMIT=NONE] -->
+ <string name="ext_media_unmountable_notification_message" product="automotive"></string>
<!-- Notification title when external media is unsupported [CHAR LIMIT=30] -->
<string name="ext_media_unsupported_notification_title">Unsupported <xliff:g id="name" example="SD card">%s</xliff:g></string>
@@ -3614,6 +3618,8 @@
<string name="ext_media_unsupported_notification_message">This device doesn\u2019t support this <xliff:g id="name" example="SD card">%s</xliff:g>. Tap to set up in a supported format.</string>
<!-- TV-specific notification body when external media is unsupported [CHAR LIMIT=NONE] -->
<string name="ext_media_unsupported_notification_message" product="tv">This device doesn\u2019t support this <xliff:g id="name" example="SD card">%s</xliff:g>. Select to set up in a supported format.</string>
+ <!-- Automotive specific notification body when external media is unsupported. No action is specified to fix (b/151671685) [CHAR LIMIT=NONE] -->
+ <string name="ext_media_unsupported_notification_message" product="automotive">This device doesn\u2019t support this <xliff:g id="name" example="SD card">%s</xliff:g>.</string>
<!-- Notification title when external media is unsafely removed [CHAR LIMIT=30] -->
<string name="ext_media_badremoval_notification_title"><xliff:g id="name" example="SD card">%s</xliff:g> unexpectedly removed</string>
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index 22caf4c2a37d..04c6a41833df 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -365,6 +365,7 @@
<java-symbol type="bool" name="config_hasRecents" />
<java-symbol type="string" name="config_recentsComponentName" />
<java-symbol type="string" name="config_systemUIServiceComponent" />
+ <java-symbol type="string" name="config_controlsPackage" />
<java-symbol type="string" name="config_screenRecorderComponent" />
<java-symbol type="string" name="config_somnambulatorComponent" />
<java-symbol type="string" name="config_screenshotServiceComponent" />
@@ -3953,4 +3954,7 @@
<!-- Set to true to enable the user switcher on the keyguard. -->
<java-symbol type="bool" name="config_keyguardUserSwitcher" />
+
+ <!-- Set to true to make assistant show in front of the dream/screensaver. -->
+ <java-symbol type="bool" name="config_assistantOnTopOfDream"/>
</resources>
diff --git a/core/tests/coretests/src/android/service/controls/ControlProviderServiceTest.java b/core/tests/coretests/src/android/service/controls/ControlProviderServiceTest.java
index 13000e943141..f4ebe2f9a755 100644
--- a/core/tests/coretests/src/android/service/controls/ControlProviderServiceTest.java
+++ b/core/tests/coretests/src/android/service/controls/ControlProviderServiceTest.java
@@ -64,8 +64,7 @@ import java.util.function.Consumer;
@RunWith(AndroidJUnit4.class)
public class ControlProviderServiceTest {
- private static final ComponentName TEST_SYSUI_COMPONENT =
- ComponentName.unflattenFromString("sysui/.test.cls");
+ private static final String TEST_CONTROLS_PACKAGE = "sysui";
private static final ComponentName TEST_COMPONENT =
ComponentName.unflattenFromString("test.pkg/.test.cls");
@@ -97,8 +96,8 @@ public class ControlProviderServiceTest {
when(mSubscriber.asBinder()).thenCallRealMethod();
when(mSubscriber.queryLocalInterface(any())).thenReturn(mSubscriber);
- when(mResources.getString(com.android.internal.R.string.config_systemUIServiceComponent))
- .thenReturn(TEST_SYSUI_COMPONENT.flattenToString());
+ when(mResources.getString(com.android.internal.R.string.config_controlsPackage))
+ .thenReturn(TEST_CONTROLS_PACKAGE);
when(mContext.getResources()).thenReturn(mResources);
Bundle b = new Bundle();
@@ -252,7 +251,7 @@ public class ControlProviderServiceTest {
eq(Manifest.permission.BIND_CONTROLS));
Intent intent = mIntentArgumentCaptor.getValue();
assertEquals(ControlsProviderService.ACTION_ADD_CONTROL, intent.getAction());
- assertEquals(TEST_SYSUI_COMPONENT.getPackageName(), intent.getPackage());
+ assertEquals(TEST_CONTROLS_PACKAGE, intent.getPackage());
assertEquals(TEST_COMPONENT, intent.getParcelableExtra(Intent.EXTRA_COMPONENT_NAME));
assertTrue(equals(control,
intent.getParcelableExtra(ControlsProviderService.EXTRA_CONTROL)));
diff --git a/core/tests/coretests/src/android/view/InsetsControllerTest.java b/core/tests/coretests/src/android/view/InsetsControllerTest.java
index efdb51dcdfa9..cbb379bf8207 100644
--- a/core/tests/coretests/src/android/view/InsetsControllerTest.java
+++ b/core/tests/coretests/src/android/view/InsetsControllerTest.java
@@ -21,6 +21,7 @@ import static android.view.InsetsController.ANIMATION_TYPE_NONE;
import static android.view.InsetsController.ANIMATION_TYPE_SHOW;
import static android.view.InsetsSourceConsumer.ShowResult.IME_SHOW_DELAYED;
import static android.view.InsetsSourceConsumer.ShowResult.SHOW_IMMEDIATELY;
+import static android.view.InsetsState.ITYPE_CAPTION_BAR;
import static android.view.InsetsState.ITYPE_IME;
import static android.view.InsetsState.ITYPE_NAVIGATION_BAR;
import static android.view.InsetsState.ITYPE_STATUS_BAR;
@@ -88,7 +89,6 @@ import java.util.concurrent.CountDownLatch;
@Presubmit
@RunWith(AndroidJUnit4.class)
public class InsetsControllerTest {
-
private InsetsController mController;
private SurfaceSession mSession = new SurfaceSession();
private SurfaceControl mLeash;
@@ -665,6 +665,26 @@ public class InsetsControllerTest {
InstrumentationRegistry.getInstrumentation().waitForIdleSync();
}
+ @Test
+ public void testCaptionInsetsStateAssemble() {
+ InstrumentationRegistry.getInstrumentation().runOnMainSync(() -> {
+ mController.onFrameChanged(new Rect(0, 0, 100, 300));
+ final InsetsState state = new InsetsState(mController.getState(), true);
+ final Rect captionFrame = new Rect(0, 0, 100, 100);
+ mController.setCaptionInsetsHeight(100);
+ mController.onStateChanged(state);
+ final InsetsState currentState = new InsetsState(mController.getState());
+ // The caption bar source should be synced with the info in mAttachInfo.
+ assertEquals(captionFrame, currentState.peekSource(ITYPE_CAPTION_BAR).getFrame());
+ assertTrue(currentState.equals(state, true /* excludingCaptionInsets*/));
+ mController.setCaptionInsetsHeight(0);
+ mController.onStateChanged(state);
+ // The caption bar source should not be there at all, because we don't add empty
+ // caption to the state from the server.
+ assertNull(mController.getState().peekSource(ITYPE_CAPTION_BAR));
+ });
+ }
+
private void waitUntilNextFrame() throws Exception {
final CountDownLatch latch = new CountDownLatch(1);
Choreographer.getMainThreadInstance().postCallback(Choreographer.CALLBACK_COMMIT,
diff --git a/core/tests/coretests/src/android/view/InsetsStateTest.java b/core/tests/coretests/src/android/view/InsetsStateTest.java
index 721dc98ff4d1..2884777fc997 100644
--- a/core/tests/coretests/src/android/view/InsetsStateTest.java
+++ b/core/tests/coretests/src/android/view/InsetsStateTest.java
@@ -153,6 +153,35 @@ public class InsetsStateTest {
}
}
+
+ @Test
+ public void testCalculateInsets_captionStatusBarOverlap() throws Exception {
+ try (InsetsModeSession session =
+ new InsetsModeSession(ViewRootImpl.NEW_INSETS_MODE_FULL)) {
+ mState.getSource(ITYPE_STATUS_BAR).setFrame(new Rect(0, 0, 100, 100));
+ mState.getSource(ITYPE_STATUS_BAR).setVisible(true);
+ mState.getSource(ITYPE_CAPTION_BAR).setFrame(new Rect(0, 0, 100, 300));
+ mState.getSource(ITYPE_CAPTION_BAR).setVisible(true);
+
+ Rect visibleInsets = mState.calculateVisibleInsets(
+ new Rect(0, 0, 100, 400), SOFT_INPUT_ADJUST_NOTHING);
+ assertEquals(new Rect(0, 300, 0, 0), visibleInsets);
+ }
+ }
+
+ @Test
+ public void testCalculateInsets_captionBarOffset() throws Exception {
+ try (InsetsModeSession session =
+ new InsetsModeSession(ViewRootImpl.NEW_INSETS_MODE_FULL)) {
+ mState.getSource(ITYPE_CAPTION_BAR).setFrame(new Rect(0, 0, 100, 300));
+ mState.getSource(ITYPE_CAPTION_BAR).setVisible(true);
+
+ Rect visibleInsets = mState.calculateVisibleInsets(
+ new Rect(0, 0, 150, 400), SOFT_INPUT_ADJUST_NOTHING);
+ assertEquals(new Rect(0, 300, 0, 0), visibleInsets);
+ }
+ }
+
@Test
public void testStripForDispatch() {
mState.getSource(ITYPE_STATUS_BAR).setFrame(new Rect(0, 0, 100, 100));
diff --git a/core/tests/coretests/src/android/widget/EditorCursorDragTest.java b/core/tests/coretests/src/android/widget/EditorCursorDragTest.java
index 9a93dbf67d33..4bfffd72d835 100644
--- a/core/tests/coretests/src/android/widget/EditorCursorDragTest.java
+++ b/core/tests/coretests/src/android/widget/EditorCursorDragTest.java
@@ -494,6 +494,7 @@ public class EditorCursorDragTest {
simulateDrag(tv, events, true);
}
+ @Suppress // b/152574363
@Test
public void testLineChangeSlop() throws Throwable {
TextView tv = mActivity.findViewById(R.id.textview);
diff --git a/data/etc/privapp-permissions-platform.xml b/data/etc/privapp-permissions-platform.xml
index 1efde8681352..59bdf3dad43e 100644
--- a/data/etc/privapp-permissions-platform.xml
+++ b/data/etc/privapp-permissions-platform.xml
@@ -27,6 +27,10 @@ applications that come with the platform
<permission name="android.permission.INTERACT_ACROSS_USERS" />
</privapp-permissions>
+ <privapp-permissions package="com.android.angle">
+ <permission name="android.permission.WRITE_SECURE_SETTINGS"/>
+ </privapp-permissions>
+
<privapp-permissions package="com.android.apps.tag">
<permission name="android.permission.WRITE_SECURE_SETTINGS"/>
</privapp-permissions>
diff --git a/graphics/java/android/graphics/drawable/AdaptiveIconDrawable.java b/graphics/java/android/graphics/drawable/AdaptiveIconDrawable.java
index 746378e10bc7..31ad81b9c346 100644
--- a/graphics/java/android/graphics/drawable/AdaptiveIconDrawable.java
+++ b/graphics/java/android/graphics/drawable/AdaptiveIconDrawable.java
@@ -975,6 +975,7 @@ public class AdaptiveIconDrawable extends Drawable implements Drawable.Callback
mChangingConfigurations = orig.mChangingConfigurations;
mChildrenChangingConfigurations = orig.mChildrenChangingConfigurations;
+ mSourceDrawableId = orig.mSourceDrawableId;
for (int i = 0; i < N_CHILDREN; i++) {
final ChildDrawable or = origChildDrawable[i];
diff --git a/libs/androidfw/Android.bp b/libs/androidfw/Android.bp
index f87f98a59a12..02c85aa34f4b 100644
--- a/libs/androidfw/Android.bp
+++ b/libs/androidfw/Android.bp
@@ -44,7 +44,6 @@ cc_library {
"AttributeResolution.cpp",
"ChunkIterator.cpp",
"ConfigDescription.cpp",
- "DynamicLibManager.cpp",
"Idmap.cpp",
"LoadedArsc.cpp",
"Locale.cpp",
diff --git a/libs/androidfw/AssetManager2.cpp b/libs/androidfw/AssetManager2.cpp
index f20e18453f8b..eaf452b5fa71 100644
--- a/libs/androidfw/AssetManager2.cpp
+++ b/libs/androidfw/AssetManager2.cpp
@@ -25,7 +25,6 @@
#include "android-base/logging.h"
#include "android-base/stringprintf.h"
-#include "androidfw/DynamicLibManager.h"
#include "androidfw/ResourceUtils.h"
#include "androidfw/Util.h"
#include "utils/ByteOrder.h"
@@ -67,12 +66,7 @@ struct FindEntryResult {
StringPoolRef entry_string_ref;
};
-AssetManager2::AssetManager2() : dynamic_lib_manager_(std::make_unique<DynamicLibManager>()) {
- memset(&configuration_, 0, sizeof(configuration_));
-}
-
-AssetManager2::AssetManager2(DynamicLibManager* dynamic_lib_manager)
- : dynamic_lib_manager_(dynamic_lib_manager) {
+AssetManager2::AssetManager2() {
memset(&configuration_, 0, sizeof(configuration_));
}
@@ -91,6 +85,9 @@ void AssetManager2::BuildDynamicRefTable() {
package_groups_.clear();
package_ids_.fill(0xff);
+ // A mapping from apk assets path to the runtime package id of its first loaded package.
+ std::unordered_map<std::string, uint8_t> apk_assets_package_ids;
+
// Overlay resources are not directly referenced by an application so their resource ids
// can change throughout the application's lifetime. Assign overlay package ids last.
std::vector<const ApkAssets*> sorted_apk_assets(apk_assets_);
@@ -98,37 +95,25 @@ void AssetManager2::BuildDynamicRefTable() {
return !a->IsOverlay();
});
- std::unordered_map<std::string, uint8_t> apk_assets_package_ids;
- std::unordered_map<std::string, uint8_t> package_name_package_ids;
-
- // Assign stable package ids to application packages.
- uint8_t next_available_package_id = 0U;
- for (const auto& apk_assets : sorted_apk_assets) {
- for (const auto& package : apk_assets->GetLoadedArsc()->GetPackages()) {
- uint8_t package_id = package->GetPackageId();
- if (package->IsOverlay()) {
- package_id = GetDynamicLibManager()->FindUnassignedId(next_available_package_id);
- next_available_package_id = package_id + 1;
- } else if (package->IsDynamic()) {
- package_id = GetDynamicLibManager()->GetAssignedId(package->GetPackageName());
- }
-
- // Map the path of the apk assets to the package id of its first loaded package.
- apk_assets_package_ids[apk_assets->GetPath()] = package_id;
-
- // Map the package name of the package to the first loaded package with that package id.
- package_name_package_ids[package->GetPackageName()] = package_id;
- }
+ // The assets cookie must map to the position of the apk assets in the unsorted apk assets list.
+ std::unordered_map<const ApkAssets*, ApkAssetsCookie> apk_assets_cookies;
+ apk_assets_cookies.reserve(apk_assets_.size());
+ for (size_t i = 0, n = apk_assets_.size(); i < n; i++) {
+ apk_assets_cookies[apk_assets_[i]] = static_cast<ApkAssetsCookie>(i);
}
- const int apk_assets_count = apk_assets_.size();
- for (int i = 0; i < apk_assets_count; i++) {
- const auto& apk_assets = apk_assets_[i];
- for (const auto& package : apk_assets->GetLoadedArsc()->GetPackages()) {
- const auto package_id_entry = package_name_package_ids.find(package->GetPackageName());
- CHECK(package_id_entry != package_name_package_ids.end())
- << "no package id assgined to package " << package->GetPackageName();
- const uint8_t package_id = package_id_entry->second;
+ // 0x01 is reserved for the android package.
+ int next_package_id = 0x02;
+ for (const ApkAssets* apk_assets : sorted_apk_assets) {
+ const LoadedArsc* loaded_arsc = apk_assets->GetLoadedArsc();
+ for (const std::unique_ptr<const LoadedPackage>& package : loaded_arsc->GetPackages()) {
+ // Get the package ID or assign one if a shared library.
+ int package_id;
+ if (package->IsDynamic()) {
+ package_id = next_package_id++;
+ } else {
+ package_id = package->GetPackageId();
+ }
// Add the mapping for package ID to index if not present.
uint8_t idx = package_ids_[package_id];
@@ -162,7 +147,7 @@ void AssetManager2::BuildDynamicRefTable() {
target_package_group.overlays_.push_back(
ConfiguredOverlay{loaded_idmap->GetTargetResourcesMap(target_package_id,
overlay_table.get()),
- static_cast<ApkAssetsCookie>(i)});
+ apk_assets_cookies[apk_assets]});
}
}
@@ -174,7 +159,7 @@ void AssetManager2::BuildDynamicRefTable() {
// Add the package and to the set of packages with the same ID.
package_group->packages_.push_back(ConfiguredPackage{package.get(), {}});
- package_group->cookies_.push_back(static_cast<ApkAssetsCookie>(i));
+ package_group->cookies_.push_back(apk_assets_cookies[apk_assets]);
// Add the package name -> build time ID mappings.
for (const DynamicPackageEntry& entry : package->GetDynamicPackageMap()) {
@@ -182,6 +167,8 @@ void AssetManager2::BuildDynamicRefTable() {
package_group->dynamic_ref_table->mEntries.replaceValueFor(
package_name, static_cast<uint8_t>(entry.package_id));
}
+
+ apk_assets_package_ids.insert(std::make_pair(apk_assets->GetPath(), package_id));
}
}
@@ -1329,16 +1316,6 @@ uint8_t AssetManager2::GetAssignedPackageId(const LoadedPackage* package) const
return 0;
}
-DynamicLibManager* AssetManager2::GetDynamicLibManager() const {
- auto dynamic_lib_manager =
- std::get_if<std::unique_ptr<DynamicLibManager>>(&dynamic_lib_manager_);
- if (dynamic_lib_manager) {
- return (*dynamic_lib_manager).get();
- } else {
- return *std::get_if<DynamicLibManager*>(&dynamic_lib_manager_);
- }
-}
-
std::unique_ptr<Theme> AssetManager2::NewTheme() {
return std::unique_ptr<Theme>(new Theme(this));
}
diff --git a/libs/androidfw/DynamicLibManager.cpp b/libs/androidfw/DynamicLibManager.cpp
deleted file mode 100644
index 895b7695bf26..000000000000
--- a/libs/androidfw/DynamicLibManager.cpp
+++ /dev/null
@@ -1,34 +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.
- */
-
-#include "androidfw/DynamicLibManager.h"
-
-namespace android {
-
-uint8_t DynamicLibManager::GetAssignedId(const std::string& library_package_name) {
- auto lib_entry = shared_lib_package_ids_.find(library_package_name);
- if (lib_entry != shared_lib_package_ids_.end()) {
- return lib_entry->second;
- }
-
- return shared_lib_package_ids_[library_package_name] = next_package_id_++;
-}
-
-uint8_t DynamicLibManager::FindUnassignedId(uint8_t start_package_id) {
- return (start_package_id < next_package_id_) ? next_package_id_ : start_package_id;
-}
-
-} // namespace android
diff --git a/libs/androidfw/include/androidfw/AssetManager2.h b/libs/androidfw/include/androidfw/AssetManager2.h
index b2cec2a42994..e21abade99a4 100644
--- a/libs/androidfw/include/androidfw/AssetManager2.h
+++ b/libs/androidfw/include/androidfw/AssetManager2.h
@@ -27,7 +27,6 @@
#include "androidfw/ApkAssets.h"
#include "androidfw/Asset.h"
#include "androidfw/AssetManager.h"
-#include "androidfw/DynamicLibManager.h"
#include "androidfw/ResourceTypes.h"
#include "androidfw/Util.h"
@@ -95,7 +94,6 @@ class AssetManager2 {
};
AssetManager2();
- explicit AssetManager2(DynamicLibManager* dynamic_lib_manager);
// Sets/resets the underlying ApkAssets for this AssetManager. The ApkAssets
// are not owned by the AssetManager, and must have a longer lifetime.
@@ -126,6 +124,9 @@ class AssetManager2 {
// This may be nullptr if the APK represented by `cookie` has no resource table.
std::shared_ptr<const DynamicRefTable> GetDynamicRefTableForCookie(ApkAssetsCookie cookie) const;
+ // Retrieve the assigned package id of the package if loaded into this AssetManager
+ uint8_t GetAssignedPackageId(const LoadedPackage* package) const;
+
// Returns a string representation of the overlayable API of a package.
bool GetOverlayablesToString(const android::StringPiece& package_name,
std::string* out) const;
@@ -370,11 +371,6 @@ class AssetManager2 {
// been seen while traversing bag parents.
const ResolvedBag* GetBag(uint32_t resid, std::vector<uint32_t>& child_resids);
- // Retrieve the assigned package id of the package if loaded into this AssetManager
- uint8_t GetAssignedPackageId(const LoadedPackage* package) const;
-
- DynamicLibManager* GetDynamicLibManager() const;
-
// The ordered list of ApkAssets to search. These are not owned by the AssetManager, and must
// have a longer lifetime.
std::vector<const ApkAssets*> apk_assets_;
@@ -393,9 +389,6 @@ class AssetManager2 {
// may need to be purged.
ResTable_config configuration_;
- // Component responsible for assigning package ids to shared libraries.
- std::variant<std::unique_ptr<DynamicLibManager>, DynamicLibManager*> dynamic_lib_manager_;
-
// Cached set of bags. These are cached because they can inherit keys from parent bags,
// which involves some calculation.
std::unordered_map<uint32_t, util::unique_cptr<ResolvedBag>> cached_bags_;
diff --git a/libs/androidfw/include/androidfw/DynamicLibManager.h b/libs/androidfw/include/androidfw/DynamicLibManager.h
deleted file mode 100644
index 1ff7079573d2..000000000000
--- a/libs/androidfw/include/androidfw/DynamicLibManager.h
+++ /dev/null
@@ -1,48 +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.
- */
-
-#ifndef ANDROIDFW_DYNAMICLIBMANAGER_H
-#define ANDROIDFW_DYNAMICLIBMANAGER_H
-
-#include <string>
-#include <unordered_map>
-
-#include "android-base/macros.h"
-
-namespace android {
-
-// Manages assigning resource ids for dynamic resources.
-class DynamicLibManager {
- public:
- DynamicLibManager() = default;
-
- // Retrieves the assigned package id for the library.
- uint8_t GetAssignedId(const std::string& library_package_name);
-
- // Queries in ascending order for the first available package id that is not currently assigned to
- // a library.
- uint8_t FindUnassignedId(uint8_t start_package_id);
-
- private:
- DISALLOW_COPY_AND_ASSIGN(DynamicLibManager);
-
- uint8_t next_package_id_ = 0x02;
- std::unordered_map<std::string, uint8_t> shared_lib_package_ids_;
-};
-
-} // namespace android
-
-#endif //ANDROIDFW_DYNAMICLIBMANAGER_H
diff --git a/libs/androidfw/include/androidfw/MutexGuard.h b/libs/androidfw/include/androidfw/MutexGuard.h
index 8891512958f0..64924f433245 100644
--- a/libs/androidfw/include/androidfw/MutexGuard.h
+++ b/libs/androidfw/include/androidfw/MutexGuard.h
@@ -47,8 +47,7 @@ class Guarded {
static_assert(!std::is_pointer<T>::value, "T must not be a raw pointer");
public:
- template <typename ...Args>
- explicit Guarded(Args&& ...args) : guarded_(std::forward<Args>(args)...) {
+ explicit Guarded() : guarded_() {
}
template <typename U = T>
diff --git a/libs/androidfw/tests/AssetManager2_test.cpp b/libs/androidfw/tests/AssetManager2_test.cpp
index ac32699c6dfd..8c255d16fe1f 100644
--- a/libs/androidfw/tests/AssetManager2_test.cpp
+++ b/libs/androidfw/tests/AssetManager2_test.cpp
@@ -17,9 +17,9 @@
#include "androidfw/AssetManager2.h"
#include "androidfw/AssetManager.h"
-#include "android-base/logging.h"
-
#include "TestHelpers.h"
+#include "android-base/file.h"
+#include "android-base/logging.h"
#include "androidfw/ResourceUtils.h"
#include "data/appaslib/R.h"
#include "data/basic/R.h"
@@ -45,37 +45,43 @@ namespace android {
class AssetManager2Test : public ::testing::Test {
public:
void SetUp() override {
- basic_assets_ = ApkAssets::Load(GetTestDataPath() + "/basic/basic.apk");
+ // Move to the test data directory so the idmap can locate the overlay APK.
+ std::string original_path = base::GetExecutableDirectory();
+ chdir(GetTestDataPath().c_str());
+
+ basic_assets_ = ApkAssets::Load("basic/basic.apk");
ASSERT_NE(nullptr, basic_assets_);
- basic_de_fr_assets_ = ApkAssets::Load(GetTestDataPath() + "/basic/basic_de_fr.apk");
+ basic_de_fr_assets_ = ApkAssets::Load("basic/basic_de_fr.apk");
ASSERT_NE(nullptr, basic_de_fr_assets_);
- style_assets_ = ApkAssets::Load(GetTestDataPath() + "/styles/styles.apk");
+ style_assets_ = ApkAssets::Load("styles/styles.apk");
ASSERT_NE(nullptr, style_assets_);
- lib_one_assets_ = ApkAssets::Load(GetTestDataPath() + "/lib_one/lib_one.apk");
+ lib_one_assets_ = ApkAssets::Load("lib_one/lib_one.apk");
ASSERT_NE(nullptr, lib_one_assets_);
- lib_two_assets_ = ApkAssets::Load(GetTestDataPath() + "/lib_two/lib_two.apk");
+ lib_two_assets_ = ApkAssets::Load("lib_two/lib_two.apk");
ASSERT_NE(nullptr, lib_two_assets_);
- libclient_assets_ = ApkAssets::Load(GetTestDataPath() + "/libclient/libclient.apk");
+ libclient_assets_ = ApkAssets::Load("libclient/libclient.apk");
ASSERT_NE(nullptr, libclient_assets_);
- appaslib_assets_ = ApkAssets::Load(GetTestDataPath() + "/appaslib/appaslib.apk",
- PROPERTY_DYNAMIC);
+ appaslib_assets_ = ApkAssets::Load("appaslib/appaslib.apk", PROPERTY_DYNAMIC);
ASSERT_NE(nullptr, appaslib_assets_);
- system_assets_ = ApkAssets::Load(GetTestDataPath() + "/system/system.apk",
- PROPERTY_SYSTEM);
+ system_assets_ = ApkAssets::Load("system/system.apk", PROPERTY_SYSTEM);
ASSERT_NE(nullptr, system_assets_);
- app_assets_ = ApkAssets::Load(GetTestDataPath() + "/app/app.apk");
+ app_assets_ = ApkAssets::Load("app/app.apk");
ASSERT_THAT(app_assets_, NotNull());
- overlayable_assets_ = ApkAssets::Load(GetTestDataPath() + "/overlayable/overlayable.apk");
+ overlay_assets_ = ApkAssets::LoadOverlay("overlay/overlay.idmap");
+ ASSERT_NE(nullptr, overlay_assets_);
+
+ overlayable_assets_ = ApkAssets::Load("overlayable/overlayable.apk");
ASSERT_THAT(overlayable_assets_, NotNull());
+ chdir(original_path.c_str());
}
protected:
@@ -88,6 +94,7 @@ class AssetManager2Test : public ::testing::Test {
std::unique_ptr<const ApkAssets> appaslib_assets_;
std::unique_ptr<const ApkAssets> system_assets_;
std::unique_ptr<const ApkAssets> app_assets_;
+ std::unique_ptr<const ApkAssets> overlay_assets_;
std::unique_ptr<const ApkAssets> overlayable_assets_;
};
@@ -216,23 +223,24 @@ TEST_F(AssetManager2Test, FindsResourceFromAppLoadedAsSharedLibrary) {
EXPECT_EQ(fix_package_id(appaslib::R::array::integerArray1, 0x02), value.data);
}
-TEST_F(AssetManager2Test, AssignsUnchangingPackageIdToSharedLibrary) {
- DynamicLibManager lib_manager;
- AssetManager2 assetmanager(&lib_manager);
+TEST_F(AssetManager2Test, AssignsOverlayPackageIdLast) {
+ AssetManager2 assetmanager;
assetmanager.SetApkAssets(
- {lib_one_assets_.get(), lib_two_assets_.get(), libclient_assets_.get()});
-
- AssetManager2 assetmanager2(&lib_manager);
- assetmanager2.SetApkAssets(
- {lib_two_assets_.get(), lib_one_assets_.get(), libclient_assets_.get()});
+ {overlayable_assets_.get(), overlay_assets_.get(), lib_one_assets_.get()});
- uint32_t res_id = assetmanager.GetResourceId("com.android.lib_one:string/foo");
- ASSERT_NE(0U, res_id);
+ auto apk_assets = assetmanager.GetApkAssets();
+ ASSERT_EQ(3, apk_assets.size());
+ ASSERT_EQ(overlayable_assets_.get(), apk_assets[0]);
+ ASSERT_EQ(overlay_assets_.get(), apk_assets[1]);
+ ASSERT_EQ(lib_one_assets_.get(), apk_assets[2]);
- uint32_t res_id_2 = assetmanager2.GetResourceId("com.android.lib_one:string/foo");
- ASSERT_NE(0U, res_id_2);
+ auto get_first_package_id = [&assetmanager](const ApkAssets* apkAssets) -> uint8_t {
+ return assetmanager.GetAssignedPackageId(apkAssets->GetLoadedArsc()->GetPackages()[0].get());
+ };
- ASSERT_EQ(res_id, res_id_2);
+ ASSERT_EQ(get_first_package_id(overlayable_assets_.get()), 0x7f);
+ ASSERT_EQ(get_first_package_id(overlay_assets_.get()), 0x03);
+ ASSERT_EQ(get_first_package_id(lib_one_assets_.get()), 0x02);
}
TEST_F(AssetManager2Test, GetSharedLibraryResourceName) {
@@ -770,7 +778,6 @@ TEST_F(AssetManager2Test, GetOverlayablesToString) {
ASSERT_EQ(api.find("not_overlayable"), std::string::npos);
ASSERT_NE(api.find("resource='com.android.overlayable:string/overlayable2' overlayable='OverlayableResources1' actor='overlay://theme' policy='0x0000000a'\n"),
std::string::npos);
-
}
} // namespace android
diff --git a/libs/hwui/renderthread/CanvasContext.cpp b/libs/hwui/renderthread/CanvasContext.cpp
index 4299dd3b46fe..c19b1878ad45 100644
--- a/libs/hwui/renderthread/CanvasContext.cpp
+++ b/libs/hwui/renderthread/CanvasContext.cpp
@@ -555,9 +555,11 @@ void CanvasContext::draw() {
FrameInfo* forthBehind = mLast4FrameInfos.front().first;
int64_t composedFrameId = mLast4FrameInfos.front().second;
nsecs_t acquireTime = -1;
- native_window_get_frame_timestamps(mNativeSurface->getNativeWindow(), composedFrameId,
- nullptr, &acquireTime, nullptr, nullptr, nullptr,
- nullptr, nullptr, nullptr, nullptr);
+ if (mNativeSurface) {
+ native_window_get_frame_timestamps(mNativeSurface->getNativeWindow(), composedFrameId,
+ nullptr, &acquireTime, nullptr, nullptr, nullptr,
+ nullptr, nullptr, nullptr, nullptr);
+ }
// Ignore default -1, NATIVE_WINDOW_TIMESTAMP_INVALID and NATIVE_WINDOW_TIMESTAMP_PENDING
forthBehind->set(FrameInfoIndex::GpuCompleted) = acquireTime > 0 ? acquireTime : -1;
mJankTracker.finishGpuDraw(*forthBehind);
diff --git a/media/java/android/media/AudioDeviceInfo.java b/media/java/android/media/AudioDeviceInfo.java
index 9950f05560d7..db2a1e8b6e7c 100644
--- a/media/java/android/media/AudioDeviceInfo.java
+++ b/media/java/android/media/AudioDeviceInfo.java
@@ -432,7 +432,7 @@ public final class AudioDeviceInfo {
* @return An array of supported encapsulation modes for the device. This
* may be an empty array if no encapsulation modes are supported.
*/
- public @NonNull int[] getEncapsulationModes() {
+ public @NonNull @AudioTrack.EncapsulationMode int[] getEncapsulationModes() {
// Implement a getter in r-dev or r-tv-dev as needed.
return new int[0]; // be careful of returning a copy of any internal data.
}
@@ -451,7 +451,7 @@ public final class AudioDeviceInfo {
* @return An array of supported encapsulation metadata types for the device. This
* may be an empty array if no metadata types are supported.
*/
- public @NonNull int[] getEncapsulationMetadataTypes() {
+ public @NonNull @AudioTrack.EncapsulationMetadataType int[] getEncapsulationMetadataTypes() {
// Implement a getter in r-dev or r-tv-dev as needed.
return new int[0]; // be careful of returning a copy of any internal data.
}
diff --git a/media/java/android/media/AudioManager.java b/media/java/android/media/AudioManager.java
index fffdd683f22c..7408987e465e 100644
--- a/media/java/android/media/AudioManager.java
+++ b/media/java/android/media/AudioManager.java
@@ -4769,7 +4769,7 @@ public class AudioManager {
* opened on that device.
*
* @param device an instance of {@link AudioDeviceInfo} returned from {@link getDevices()}.
- * @param delayMs delay in milliseconds desired. This should be in range of {@code 0}
+ * @param delayMillis delay in milliseconds desired. This should be in range of {@code 0}
* to the value returned by {@link #getMaxAdditionalOutputDeviceDelay()}.
* @return true if successful, false if the device does not support output device delay
* or the delay is not in range of {@link #getMaxAdditionalOutputDeviceDelay()}.
@@ -4777,7 +4777,7 @@ public class AudioManager {
@SystemApi
@RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING)
public boolean setAdditionalOutputDeviceDelay(
- @NonNull AudioDeviceInfo device, @IntRange(from = 0) int delayMs) {
+ @NonNull AudioDeviceInfo device, @IntRange(from = 0) long delayMillis) {
Objects.requireNonNull(device);
// Implement the setter in r-dev or r-tv-dev as needed.
return false;
@@ -4793,7 +4793,7 @@ public class AudioManager {
*/
@SystemApi
@IntRange(from = 0)
- public int getAdditionalOutputDeviceDelay(@NonNull AudioDeviceInfo device) {
+ public long getAdditionalOutputDeviceDelay(@NonNull AudioDeviceInfo device) {
Objects.requireNonNull(device);
// Implement the getter in r-dev or r-tv-dev as needed.
return 0;
@@ -4811,7 +4811,7 @@ public class AudioManager {
*/
@SystemApi
@IntRange(from = 0)
- public int getMaxAdditionalOutputDeviceDelay(@NonNull AudioDeviceInfo device) {
+ public long getMaxAdditionalOutputDeviceDelay(@NonNull AudioDeviceInfo device) {
Objects.requireNonNull(device);
// Implement the getter in r-dev or r-tv-dev as needed.
return 0;
@@ -5987,6 +5987,20 @@ public class AudioManager {
}
}
+ /**
+ * Set whether or not there is an active RTT call.
+ * This method should be called by Telecom service.
+ * @hide
+ * TODO: make this a @SystemApi
+ */
+ public static void setRttEnabled(boolean rttEnabled) {
+ try {
+ getService().setRttEnabled(rttEnabled);
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
+
//---------------------------------------------------------
// Inner classes
//--------------------
diff --git a/media/java/android/media/AudioMetadata.java b/media/java/android/media/AudioMetadata.java
index 1a9517cafdde..c91ff0d099cf 100644
--- a/media/java/android/media/AudioMetadata.java
+++ b/media/java/android/media/AudioMetadata.java
@@ -79,96 +79,11 @@ public final class AudioMetadata {
}
/**
- * A read only {@code Map} interface of {@link Key} value pairs.
- *
- * <p>Using a {@link Key} interface, the map looks up the corresponding value.</p>
- */
- public interface ReadMap {
- /**
- * Returns true if the key exists in the map.
- *
- * @param key interface for requesting the value.
- * @param <T> type of value.
- * @return true if key exists in the Map.
- */
- <T> boolean containsKey(@NonNull Key<T> key);
-
- /**
- * Returns a copy of the map.
- *
- * This is intended for safe conversion between a {@link ReadMap}
- * interface and a {@link Map} interface.
- * Currently only simple objects are used for key values which
- * means a shallow copy is sufficient.
- *
- * @return a Map copied from the existing map.
- */
- @NonNull
- Map dup(); // lint checker doesn't like clone().
-
- /**
- * Returns the value associated with the key.
- *
- * @param key interface for requesting the value.
- * @param <T> type of value.
- * @return returns the value of associated with key or null if it doesn't exist.
- */
- @Nullable
- <T> T get(@NonNull Key<T> key);
-
- /**
- * Returns a {@code Set} of keys associated with the map.
- * @hide
- */
- @NonNull
- Set<Key<?>> keySet();
-
- /**
- * Returns the number of elements in the map.
- */
- int size();
- }
-
- /**
- * A writeable {@link Map} interface of {@link Key} value pairs.
- * This interface is not guaranteed to be thread-safe
- * unless the supplier for the {@code Map} states it as thread safe.
- */
- // TODO: Create a wrapper like java.util.Collections.synchronizedMap?
- public interface Map extends ReadMap {
- /**
- * Removes the value associated with the key.
- * @param key interface for storing the value.
- * @param <T> type of value.
- * @return the value of the key, null if it doesn't exist.
- */
- @Nullable
- <T> T remove(@NonNull Key<T> key);
-
- /**
- * Sets a value for the key.
- *
- * @param key interface for storing the value.
- * @param <T> type of value.
- * @param value a non-null value of type T.
- * @return the previous value associated with key or null if it doesn't exist.
- */
- // See automatic Kotlin overloading for Java interoperability.
- // https://kotlinlang.org/docs/reference/java-interop.html#operators
- // See also Kotlin set for overloaded operator indexing.
- // https://kotlinlang.org/docs/reference/operator-overloading.html#indexed
- // Also the Kotlin mutable-list set.
- // https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.collections/-mutable-list/set.html
- @Nullable
- <T> T set(@NonNull Key<T> key, @NonNull T value);
- }
-
- /**
- * Creates a {@link Map} suitable for adding keys.
- * @return an empty {@link Map} instance.
+ * Creates a {@link AudioMetadataMap} suitable for adding keys.
+ * @return an empty {@link AudioMetadataMap} instance.
*/
@NonNull
- public static Map createMap() {
+ public static AudioMetadataMap createMap() {
return new BaseMap();
}
@@ -339,7 +254,7 @@ public final class AudioMetadata {
* It is possible to require the keys to be of a certain class
* before allowing a set or get operation.
*/
- public static class BaseMap implements Map {
+ public static class BaseMap implements AudioMetadataMap {
@Override
public <T> boolean containsKey(@NonNull Key<T> key) {
Pair<Key<?>, Object> valuePair = mHashMap.get(pairFromKey(key));
@@ -348,7 +263,7 @@ public final class AudioMetadata {
@Override
@NonNull
- public Map dup() {
+ public AudioMetadataMap dup() {
BaseMap map = new BaseMap();
map.mHashMap.putAll(this.mHashMap);
return map;
diff --git a/media/java/android/media/AudioMetadataMap.java b/media/java/android/media/AudioMetadataMap.java
new file mode 100644
index 000000000000..196193174754
--- /dev/null
+++ b/media/java/android/media/AudioMetadataMap.java
@@ -0,0 +1,59 @@
+/*
+ * 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.media;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+
+/**
+ * AudioMetadataMap is a writeable {@code Map}-style
+ * interface of {@link AudioMetadata.Key} value pairs.
+ * This interface is not guaranteed to be thread-safe
+ * unless the underlying implementation for the {@code AudioMetadataMap}
+ * states it as thread safe.
+ *
+ * {@see AudioMetadataReadMap}
+ */
+// TODO: Create a wrapper like java.util.Collections.synchronizedMap?
+
+public interface AudioMetadataMap extends AudioMetadataReadMap {
+ /**
+ * Removes the value associated with the key.
+ * @param key interface for storing the value.
+ * @param <T> type of value.
+ * @return the value of the key, null if it doesn't exist.
+ */
+ @Nullable
+ <T> T remove(@NonNull AudioMetadata.Key<T> key);
+
+ /**
+ * Sets a value for the key.
+ *
+ * @param key interface for storing the value.
+ * @param <T> type of value.
+ * @param value a non-null value of type T.
+ * @return the previous value associated with key or null if it doesn't exist.
+ */
+ // See automatic Kotlin overloading for Java interoperability.
+ // https://kotlinlang.org/docs/reference/java-interop.html#operators
+ // See also Kotlin set for overloaded operator indexing.
+ // https://kotlinlang.org/docs/reference/operator-overloading.html#indexed
+ // Also the Kotlin mutable-list set.
+ // https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.collections/-mutable-list/set.html
+ @Nullable
+ <T> T set(@NonNull AudioMetadata.Key<T> key, @NonNull T value);
+}
diff --git a/media/java/android/media/AudioMetadataReadMap.java b/media/java/android/media/AudioMetadataReadMap.java
new file mode 100644
index 000000000000..e74242a292d4
--- /dev/null
+++ b/media/java/android/media/AudioMetadataReadMap.java
@@ -0,0 +1,81 @@
+/*
+ * 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.media;
+
+import android.annotation.IntRange;
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+
+import java.util.Set;
+
+/**
+ * A read only {@code Map}-style interface of {@link AudioMetadata.Key} value pairs used
+ * for {@link AudioMetadata}.
+ *
+ * <p>Using a {@link AudioMetadata.Key} interface,
+ * this map looks up the corresponding value.
+ * Read-only maps are thread-safe for lookup, but the underlying object
+ * values may need their own thread protection if mutable.</p>
+ *
+ * {@see AudioMetadataMap}
+ */
+public interface AudioMetadataReadMap {
+ /**
+ * Returns true if the key exists in the map.
+ *
+ * @param key interface for requesting the value.
+ * @param <T> type of value.
+ * @return true if key exists in the Map.
+ */
+ <T> boolean containsKey(@NonNull AudioMetadata.Key<T> key);
+
+ /**
+ * Returns a copy of the map.
+ *
+ * This is intended for safe conversion between a {@link AudioMetadataReadMap}
+ * interface and a {@link AudioMetadataMap} interface.
+ * Currently only simple objects are used for key values which
+ * means a shallow copy is sufficient.
+ *
+ * @return a Map copied from the existing map.
+ */
+ @NonNull
+ AudioMetadataMap dup(); // lint checker doesn't like clone().
+
+ /**
+ * Returns the value associated with the key.
+ *
+ * @param key interface for requesting the value.
+ * @param <T> type of value.
+ * @return returns the value of associated with key or null if it doesn't exist.
+ */
+ @Nullable
+ <T> T get(@NonNull AudioMetadata.Key<T> key);
+
+ /**
+ * Returns a {@code Set} of keys associated with the map.
+ * @hide
+ */
+ @NonNull
+ Set<AudioMetadata.Key<?>> keySet();
+
+ /**
+ * Returns the number of elements in the map.
+ */
+ @IntRange(from = 0)
+ int size();
+}
diff --git a/media/java/android/media/AudioTrack.java b/media/java/android/media/AudioTrack.java
index d17e42996726..1d229b80cb2c 100644
--- a/media/java/android/media/AudioTrack.java
+++ b/media/java/android/media/AudioTrack.java
@@ -918,7 +918,29 @@ public class AudioTrack extends PlayerBase
private final int mContentId;
private final int mSyncId;
- private TunerConfiguration(int contentId, int syncId) {
+ /**
+ * Constructs a TunerConfiguration instance for use in {@link AudioTrack.Builder}
+ *
+ * @param contentId selects the audio stream to use.
+ * The contentId may be obtained from
+ * {@link android.media.tv.tuner.filter.Filter#getId()}.
+ * This is always a positive number.
+ * @param syncId selects the clock to use for synchronization
+ * of audio with other streams such as video.
+ * The syncId may be obtained from
+ * {@link android.media.tv.tuner.Tuner#getAvSyncHwId()}.
+ * This is always a positive number.
+ */
+ @RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING)
+ public TunerConfiguration(
+ @IntRange(from = 1) int contentId, @IntRange(from = 1)int syncId) {
+ if (contentId < 1) {
+ throw new IllegalArgumentException(
+ "contentId " + contentId + " must be positive");
+ }
+ if (syncId < 1) {
+ throw new IllegalArgumentException("syncId " + syncId + " must be positive");
+ }
mContentId = contentId;
mSyncId = syncId;
}
@@ -938,73 +960,6 @@ public class AudioTrack extends PlayerBase
public @IntRange(from = 1) int getSyncId() {
return mSyncId; // The Builder ensures this is > 0.
}
-
- /**
- * Builder class for {@link AudioTrack.TunerConfiguration} objects.
- */
- public static class Builder {
- private int mContentId;
- private int mSyncId;
-
- /**
- * Sets the contentId from the Tuner filter.
- *
- * @param contentId selects the audio stream to use.
- * The contentId may be obtained from
- * {@link android.media.tv.tuner.filter.Filter#getId()}.
- * This is always a positive number.
- *
- * @return the same Builder instance.
- */
- @RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING)
- public @NonNull Builder setContentId(@IntRange(from = 1) int contentId) {
- if (contentId < 1) {
- throw new IllegalArgumentException(
- "contentId " + contentId + " must be positive");
- }
- mContentId = contentId;
- return this;
- }
-
- /**
- * Sets the syncId from the Tuner filter.
- *
- * @param syncId selects the clock to use for synchronization
- * of audio with other streams such as video.
- * The syncId may be obtained from
- * {@link android.media.tv.tuner.Tuner#getAvSyncHwId()}.
- * This is always a positive number.
- *
- * @return the same Builder instance.
- */
- @RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING)
- public @NonNull Builder setSyncId(@IntRange(from = 1) int syncId) {
- if (syncId < 1) {
- throw new IllegalArgumentException("syncId " + syncId + " must be positive");
- }
- mSyncId = syncId;
- return this;
- }
-
- /**
- * Builds a {@link AudioTrack.TunerConfiguration} instance initialized with
- * the parameters set on this {@code Builder}.
- *
- * @return a new successfully initialized {@link AudioTrack.TunerConfiguration}.
- * @throws UnsupportedOperationException if the parameters set on the
- * {@code Builder} are incompatible.
- */
- @RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING)
- public @NonNull TunerConfiguration build() {
- if (mContentId < 1 || mSyncId < 1) {
- throw new UnsupportedOperationException(
- "mContentId " + mContentId
- + " mSyncId " + mSyncId
- + " must be set");
- }
- return new TunerConfiguration(mContentId, mSyncId);
- }
- }
}
/**
@@ -3673,7 +3628,7 @@ public class AudioTrack extends PlayerBase
// OnCodecFormatChangedListener notifications uses an instance
// of ListenerList to manage its listeners.
- private final Utils.ListenerList<AudioMetadata.ReadMap> mCodecFormatChangedListeners =
+ private final Utils.ListenerList<AudioMetadataReadMap> mCodecFormatChangedListeners =
new Utils.ListenerList();
/**
@@ -3684,13 +3639,13 @@ public class AudioTrack extends PlayerBase
* Called when the compressed codec format changes.
*
* @param audioTrack is the {@code AudioTrack} instance associated with the codec.
- * @param info is a {@link AudioMetadata.ReadMap} of values which contains decoded format
+ * @param info is a {@link AudioMetadataReadMap} of values which contains decoded format
* changes reported by the codec. Not all hardware
* codecs indicate codec format changes. Acceptable keys are taken from
* {@code AudioMetadata.Format.KEY_*} range, with the associated value type.
*/
void onCodecFormatChanged(
- @NonNull AudioTrack audioTrack, @Nullable AudioMetadata.ReadMap info);
+ @NonNull AudioTrack audioTrack, @Nullable AudioMetadataReadMap info);
}
/**
@@ -3708,7 +3663,7 @@ public class AudioTrack extends PlayerBase
mCodecFormatChangedListeners.add(
listener, /* key for removal */
executor,
- (int eventCode, AudioMetadata.ReadMap readMap) -> {
+ (int eventCode, AudioMetadataReadMap readMap) -> {
// eventCode is unused by this implementation.
listener.onCodecFormatChanged(this, readMap);
}
@@ -4067,7 +4022,7 @@ public class AudioTrack extends PlayerBase
ByteBuffer buffer = (ByteBuffer) obj;
buffer.order(ByteOrder.nativeOrder());
buffer.rewind();
- AudioMetadata.ReadMap audioMetaData = AudioMetadata.fromByteBuffer(buffer);
+ AudioMetadataReadMap audioMetaData = AudioMetadata.fromByteBuffer(buffer);
if (audioMetaData == null) {
Log.e(TAG, "Unable to get audio metadata from byte buffer");
return;
diff --git a/media/java/android/media/IAudioService.aidl b/media/java/android/media/IAudioService.aidl
index 5f320cd052c9..453a5d8a5b7e 100644
--- a/media/java/android/media/IAudioService.aidl
+++ b/media/java/android/media/IAudioService.aidl
@@ -292,6 +292,8 @@ interface IAudioService {
oneway void unregisterStrategyPreferredDeviceDispatcher(
IStrategyPreferredDeviceDispatcher dispatcher);
+ oneway void setRttEnabled(in boolean rttEnabled);
+
// WARNING: read warning at top of file, new methods that need to be used by native
// code via IAudioManager.h need to be added to the top section.
}
diff --git a/media/java/android/media/MediaRoute2Info.java b/media/java/android/media/MediaRoute2Info.java
index 998561316dd4..e5ad569bb24f 100644
--- a/media/java/android/media/MediaRoute2Info.java
+++ b/media/java/android/media/MediaRoute2Info.java
@@ -663,8 +663,8 @@ public final class MediaRoute2Info implements Parcelable {
}
/**
- * Constructor for builder to create {@link MediaRoute2Info} with
- * existing {@link MediaRoute2Info} instance.
+ * Constructor for builder to create {@link MediaRoute2Info} with existing
+ * {@link MediaRoute2Info} instance.
*
* @param routeInfo the existing instance to copy data from.
*/
@@ -690,6 +690,38 @@ public final class MediaRoute2Info implements Parcelable {
}
/**
+ * Constructor for builder to create {@link MediaRoute2Info} with existing
+ * {@link MediaRoute2Info} instance and replace ID with the given {@code id}.
+ *
+ * @param id The ID of the new route. Must not be empty.
+ * @param routeInfo the existing instance to copy data from.
+ * @hide
+ */
+ public Builder(@NonNull String id, @NonNull MediaRoute2Info routeInfo) {
+ if (TextUtils.isEmpty(id)) {
+ throw new IllegalArgumentException("id must not be empty");
+ }
+ Objects.requireNonNull(routeInfo, "routeInfo must not be null");
+
+ mId = id;
+ mName = routeInfo.mName;
+ mFeatures = new ArrayList<>(routeInfo.mFeatures);
+ mType = routeInfo.mType;
+ mIsSystem = routeInfo.mIsSystem;
+ mIconUri = routeInfo.mIconUri;
+ mDescription = routeInfo.mDescription;
+ mConnectionState = routeInfo.mConnectionState;
+ mClientPackageName = routeInfo.mClientPackageName;
+ mVolumeHandling = routeInfo.mVolumeHandling;
+ mVolumeMax = routeInfo.mVolumeMax;
+ mVolume = routeInfo.mVolume;
+ if (routeInfo.mExtras != null) {
+ mExtras = new Bundle(routeInfo.mExtras);
+ }
+ mProviderId = routeInfo.mProviderId;
+ }
+
+ /**
* Adds a feature for the route.
* @param feature a feature that the route has. May be one of predefined features
* such as {@link #FEATURE_LIVE_AUDIO}, {@link #FEATURE_LIVE_VIDEO} or
diff --git a/media/java/android/media/soundtrigger/SoundTriggerManager.java b/media/java/android/media/soundtrigger/SoundTriggerManager.java
index 6a8483c58276..7d51b104a47d 100644
--- a/media/java/android/media/soundtrigger/SoundTriggerManager.java
+++ b/media/java/android/media/soundtrigger/SoundTriggerManager.java
@@ -211,7 +211,7 @@ public final class SoundTriggerManager {
*/
@NonNull
public UUID getModelUuid() {
- return mGenericSoundModel.uuid;
+ return mGenericSoundModel.getUuid();
}
/**
@@ -221,7 +221,7 @@ public final class SoundTriggerManager {
*/
@NonNull
public UUID getVendorUuid() {
- return mGenericSoundModel.vendorUuid;
+ return mGenericSoundModel.getVendorUuid();
}
/**
@@ -230,7 +230,7 @@ public final class SoundTriggerManager {
* @return Version associated with the model
*/
public int getVersion() {
- return mGenericSoundModel.version;
+ return mGenericSoundModel.getVersion();
}
/**
@@ -240,7 +240,7 @@ public final class SoundTriggerManager {
*/
@Nullable
public byte[] getModelData() {
- return mGenericSoundModel.data;
+ return mGenericSoundModel.getData();
}
/**
@@ -307,7 +307,7 @@ public final class SoundTriggerManager {
}
try {
- switch (soundModel.type) {
+ switch (soundModel.getType()) {
case SoundModel.TYPE_GENERIC_SOUND:
return mSoundTriggerService.loadGenericSoundModel(
(GenericSoundModel) soundModel);
diff --git a/media/packages/BluetoothMidiService/src/com/android/bluetoothmidiservice/BluetoothPacketDecoder.java b/media/packages/BluetoothMidiService/src/com/android/bluetoothmidiservice/BluetoothPacketDecoder.java
index ea95a01c1f78..c51c8fa73c4e 100644
--- a/media/packages/BluetoothMidiService/src/com/android/bluetoothmidiservice/BluetoothPacketDecoder.java
+++ b/media/packages/BluetoothMidiService/src/com/android/bluetoothmidiservice/BluetoothPacketDecoder.java
@@ -22,24 +22,41 @@ import android.util.Log;
import java.io.IOException;
/**
- * This is an abstract base class that decodes a packet buffer and passes it to a
- * {@link android.media.midi.MidiReceiver}
+ * This is an abstract base class that decodes a BLE-MIDI packet
+ * buffer and passes it to a {@link android.media.midi.MidiReceiver}
*/
public class BluetoothPacketDecoder extends PacketDecoder {
private static final String TAG = "BluetoothPacketDecoder";
private final byte[] mBuffer;
+ private int mBytesInBuffer;
private MidiBtleTimeTracker mTimeTracker;
- private final int TIMESTAMP_MASK_HIGH = 0x1F80;
- private final int TIMESTAMP_MASK_LOW = 0x7F;
- private final int HEADER_TIMESTAMP_MASK = 0x3F;
+ private int mLowTimestamp;
+ private long mNanoTimestamp;
+
+ private static final int TIMESTAMP_MASK_HIGH = 0x1F80; // top 7 bits
+ private static final int TIMESTAMP_MASK_LOW = 0x7F; // bottom 7 bits
+ private static final int HEADER_TIMESTAMP_MASK = 0x3F; // bottom 6 bits
public BluetoothPacketDecoder(int maxPacketSize) {
mBuffer = new byte[maxPacketSize];
}
+ private void flushOutput(MidiReceiver receiver) {
+ if (mBytesInBuffer > 0) {
+ try {
+ receiver.send(mBuffer, 0, mBytesInBuffer, mNanoTimestamp);
+ } catch (IOException e) {
+ // ???
+ }
+ mBytesInBuffer = 0;
+ }
+ }
+
+ // NOTE: this code allows running status across packets,
+ // although the specification does not allow that.
@Override
public void decodePacket(byte[] buffer, MidiReceiver receiver) {
if (mTimeTracker == null) {
@@ -47,14 +64,11 @@ public class BluetoothPacketDecoder extends PacketDecoder {
}
int length = buffer.length;
-
- // NOTE his code allows running status across packets,
- // although the specification does not allow that.
-
if (length < 1) {
Log.e(TAG, "empty packet");
return;
}
+
byte header = buffer[0];
if ((header & 0xC0) != 0x80) {
Log.e(TAG, "packet does not start with header");
@@ -64,52 +78,46 @@ public class BluetoothPacketDecoder extends PacketDecoder {
// shift bits 0 - 5 to bits 7 - 12
int highTimestamp = (header & HEADER_TIMESTAMP_MASK) << 7;
boolean lastWasTimestamp = false;
- int dataCount = 0;
int previousLowTimestamp = 0;
- long nanoTimestamp = 0;
- int currentTimestamp = 0;
+ int currentTimestamp = highTimestamp | mLowTimestamp;
- // iterate through the rest of the packet, separating MIDI data from timestamps
+ // Iterate through the rest of the packet, separating MIDI data from timestamps.
for (int i = 1; i < buffer.length; i++) {
byte b = buffer[i];
+ // Is this a timestamp byte?
if ((b & 0x80) != 0 && !lastWasTimestamp) {
lastWasTimestamp = true;
- int lowTimestamp = b & TIMESTAMP_MASK_LOW;
- if (lowTimestamp < previousLowTimestamp) {
+ mLowTimestamp = b & TIMESTAMP_MASK_LOW;
+
+ // If the low timestamp byte wraps within the packet then
+ // increment the high timestamp byte.
+ if (mLowTimestamp < previousLowTimestamp) {
highTimestamp = (highTimestamp + 0x0080) & TIMESTAMP_MASK_HIGH;
}
- previousLowTimestamp = lowTimestamp;
+ previousLowTimestamp = mLowTimestamp;
- int newTimestamp = highTimestamp | lowTimestamp;
+ // If the timestamp advances then send any pending data.
+ int newTimestamp = highTimestamp | mLowTimestamp;
if (newTimestamp != currentTimestamp) {
- if (dataCount > 0) {
- // send previous message separately since it has a different timestamp
- try {
- receiver.send(mBuffer, 0, dataCount, nanoTimestamp);
- } catch (IOException e) {
- // ???
- }
- dataCount = 0;
- }
+ // Send previous message separately since it has a different timestamp.
+ flushOutput(receiver);
currentTimestamp = newTimestamp;
}
- // calculate nanoTimestamp
+ // Calculate MIDI nanosecond timestamp from BLE timestamp.
long now = System.nanoTime();
- nanoTimestamp = mTimeTracker.convertTimestampToNanotime(currentTimestamp, now);
+ mNanoTimestamp = mTimeTracker.convertTimestampToNanotime(currentTimestamp, now);
} else {
lastWasTimestamp = false;
- mBuffer[dataCount++] = b;
+ // Flush if full before adding more data.
+ if (mBytesInBuffer == mBuffer.length) {
+ flushOutput(receiver);
+ }
+ mBuffer[mBytesInBuffer++] = b;
}
}
- if (dataCount > 0) {
- try {
- receiver.send(mBuffer, 0, dataCount, nanoTimestamp);
- } catch (IOException e) {
- // ???
- }
- }
+ flushOutput(receiver);
}
}
diff --git a/packages/SettingsLib/res/values/strings.xml b/packages/SettingsLib/res/values/strings.xml
index 3f59f896a82e..e61d70fcf7e6 100644
--- a/packages/SettingsLib/res/values/strings.xml
+++ b/packages/SettingsLib/res/values/strings.xml
@@ -1291,10 +1291,18 @@
<string name="shared_data_title">Shared data</string>
<!-- Storage: shared data summary [CHAR LIMIT=80] -->
<string name="shared_data_summary">View and modify shared data</string>
+ <!-- Shared data: display text when there are no shared data blobs available [CHAR LIMIT=NONE] -->
+ <string name="shared_data_no_blobs_text">There is no shared data for this user.</string>
+ <!-- Shared data: text to display when there was an error while fetching shared data for the user [CHAR LIMIT=NONE] -->
+ <string name="shared_data_query_failure_text">There was an error fetching shared data. Try again.</string>
<!-- Shared data: shared data id [CHAR LIMIT=50] -->
<string name="blob_id_text">Shared data ID: <xliff:g id="blob_id" example="100">%d</xliff:g></string>
<!-- Shared data: label to indicate when the shared data expires [CHAR LIMIT=80] -->
<string name="blob_expires_text">Expires at <xliff:g id="date" example="Mar 20, 2020 11:59:59 GMT">%s</xliff:g></string>
+ <!-- Shared data: text to display when there was an error while deleting a shared data object [CHAR LIMIT=NONE] -->
+ <string name="shared_data_delete_failure_text">There was an error deleting the shared data.</string>
+ <!-- Shared data: dialog text when there are no acquired leases for a blob [CHAR LIMIT=NONE] -->
+ <string name="shared_data_no_accessors_dialog_text">There are no leases acquired for this shared data. Would you like to delete it?</string>
<!-- Shared data: title for screen showing list of packages accessing some shared data [CHAR LIMIT=50] -->
<string name="accessor_info_title">Apps sharing data</string>
<!-- Shared data: text indicating that no description was provided by the app for this shared data [CHAR LIMIT=80] -->
diff --git a/packages/SettingsLib/src/com/android/settingslib/media/LocalMediaManager.java b/packages/SettingsLib/src/com/android/settingslib/media/LocalMediaManager.java
index 922caeb0a817..df0de68b1fb9 100644
--- a/packages/SettingsLib/src/com/android/settingslib/media/LocalMediaManager.java
+++ b/packages/SettingsLib/src/com/android/settingslib/media/LocalMediaManager.java
@@ -69,9 +69,9 @@ public class LocalMediaManager implements BluetoothCallback {
private MediaDevice mOnTransferBluetoothDevice;
@VisibleForTesting
- List<MediaDevice> mMediaDevices = new ArrayList<>();
+ List<MediaDevice> mMediaDevices = new CopyOnWriteArrayList<>();
@VisibleForTesting
- List<MediaDevice> mDisconnectedMediaDevices = new ArrayList<>();
+ List<MediaDevice> mDisconnectedMediaDevices = new CopyOnWriteArrayList<>();
@VisibleForTesting
MediaDevice mPhoneDevice;
@VisibleForTesting
@@ -207,6 +207,7 @@ public class LocalMediaManager implements BluetoothCallback {
public void stopScan() {
mInfoMediaManager.unregisterCallback(mMediaDeviceCallback);
mInfoMediaManager.stopScan();
+ unRegisterDeviceAttributeChangeCallback();
}
/**
@@ -397,32 +398,34 @@ public class LocalMediaManager implements BluetoothCallback {
}
private List<MediaDevice> buildDisconnectedBluetoothDevice() {
- for (MediaDevice device : mDisconnectedMediaDevices) {
- ((BluetoothMediaDevice) device).getCachedDevice()
- .unregisterCallback(mDeviceAttributeChangeCallback);
- }
- mDisconnectedMediaDevices.clear();
final List<BluetoothDevice> bluetoothDevices =
mBluetoothAdapter.getMostRecentlyConnectedDevices();
final CachedBluetoothDeviceManager cachedDeviceManager =
mLocalBluetoothManager.getCachedDeviceManager();
+ final List<CachedBluetoothDevice> cachedBluetoothDeviceList = new ArrayList<>();
for (BluetoothDevice device : bluetoothDevices) {
final CachedBluetoothDevice cachedDevice =
cachedDeviceManager.findDevice(device);
if (cachedDevice != null) {
if (cachedDevice.getBondState() == BluetoothDevice.BOND_BONDED
&& !cachedDevice.isConnected()) {
- final MediaDevice mediaDevice = new BluetoothMediaDevice(mContext,
- cachedDevice,
- null, null, mPackageName);
- if (!mMediaDevices.contains(mediaDevice)) {
- cachedDevice.registerCallback(mDeviceAttributeChangeCallback);
- mDisconnectedMediaDevices.add(mediaDevice);
- }
+ cachedBluetoothDeviceList.add(cachedDevice);
}
}
}
+
+ unRegisterDeviceAttributeChangeCallback();
+ mDisconnectedMediaDevices.clear();
+ for (CachedBluetoothDevice cachedDevice : cachedBluetoothDeviceList) {
+ final MediaDevice mediaDevice = new BluetoothMediaDevice(mContext,
+ cachedDevice,
+ null, null, mPackageName);
+ if (!mMediaDevices.contains(mediaDevice)) {
+ cachedDevice.registerCallback(mDeviceAttributeChangeCallback);
+ mDisconnectedMediaDevices.add(mediaDevice);
+ }
+ }
return new ArrayList<>(mDisconnectedMediaDevices);
}
@@ -473,6 +476,12 @@ public class LocalMediaManager implements BluetoothCallback {
}
}
+ private void unRegisterDeviceAttributeChangeCallback() {
+ for (MediaDevice device : mDisconnectedMediaDevices) {
+ ((BluetoothMediaDevice) device).getCachedDevice()
+ .unregisterCallback(mDeviceAttributeChangeCallback);
+ }
+ }
/**
* Callback for notifying device information updating
diff --git a/packages/SettingsProvider/src/android/provider/settings/backup/SecureSettings.java b/packages/SettingsProvider/src/android/provider/settings/backup/SecureSettings.java
index d320df9c24ba..736e995451cd 100644
--- a/packages/SettingsProvider/src/android/provider/settings/backup/SecureSettings.java
+++ b/packages/SettingsProvider/src/android/provider/settings/backup/SecureSettings.java
@@ -96,6 +96,7 @@ public class SecureSettings {
Settings.Secure.CAMERA_DOUBLE_TAP_POWER_GESTURE_DISABLED,
Settings.Secure.SYSTEM_NAVIGATION_KEYS_ENABLED,
Settings.Secure.QS_TILES,
+ Settings.Secure.CONTROLS_ENABLED,
Settings.Secure.DOZE_ENABLED,
Settings.Secure.DOZE_ALWAYS_ON,
Settings.Secure.DOZE_PICK_UP_GESTURE,
@@ -163,6 +164,6 @@ public class SecureSettings {
Settings.Secure.AWARE_TAP_PAUSE_TOUCH_COUNT,
Settings.Secure.PEOPLE_STRIP,
Settings.Secure.ACCESSIBILITY_MAGNIFICATION_MODE,
- Settings.Secure.ACCESSIBILITY_BUTTON_LONG_PRESS_TARGETS,
+ Settings.Secure.ACCESSIBILITY_BUTTON_TARGETS,
};
}
diff --git a/packages/SettingsProvider/src/android/provider/settings/validators/SecureSettingsValidators.java b/packages/SettingsProvider/src/android/provider/settings/validators/SecureSettingsValidators.java
index 8801a9c32a36..b413e8e9dda2 100644
--- a/packages/SettingsProvider/src/android/provider/settings/validators/SecureSettingsValidators.java
+++ b/packages/SettingsProvider/src/android/provider/settings/validators/SecureSettingsValidators.java
@@ -78,9 +78,7 @@ public class SecureSettingsValidators {
ACCESSIBILITY_SHORTCUT_TARGET_LIST_VALIDATOR);
// technically either ComponentName or class name, but there's proper value
// validation at callsites, so allow any non-null string
- VALIDATORS.put(
- Secure.ACCESSIBILITY_BUTTON_TARGET_COMPONENT,
- ACCESSIBILITY_SHORTCUT_TARGET_LIST_VALIDATOR);
+ VALIDATORS.put(Secure.ACCESSIBILITY_BUTTON_TARGET_COMPONENT, value -> value != null);
VALIDATORS.put(Secure.ACCESSIBILITY_SHORTCUT_DIALOG_SHOWN, BOOLEAN_VALIDATOR);
VALIDATORS.put(Secure.ACCESSIBILITY_SHORTCUT_ON_LOCK_SCREEN, BOOLEAN_VALIDATOR);
VALIDATORS.put(Secure.ACCESSIBILITY_HIGH_TEXT_CONTRAST_ENABLED, BOOLEAN_VALIDATOR);
@@ -143,6 +141,7 @@ public class SecureSettingsValidators {
VALIDATORS.put(Secure.CAMERA_DOUBLE_TAP_POWER_GESTURE_DISABLED, BOOLEAN_VALIDATOR);
VALIDATORS.put(Secure.SYSTEM_NAVIGATION_KEYS_ENABLED, BOOLEAN_VALIDATOR);
VALIDATORS.put(Secure.QS_TILES, TILE_LIST_VALIDATOR);
+ VALIDATORS.put(Secure.CONTROLS_ENABLED, BOOLEAN_VALIDATOR);
VALIDATORS.put(Secure.DOZE_ENABLED, BOOLEAN_VALIDATOR);
VALIDATORS.put(Secure.DOZE_ALWAYS_ON, BOOLEAN_VALIDATOR);
VALIDATORS.put(Secure.DOZE_PICK_UP_GESTURE, BOOLEAN_VALIDATOR);
@@ -248,7 +247,7 @@ public class SecureSettingsValidators {
Secure.ACCESSIBILITY_MAGNIFICATION_MODE_FULLSCREEN,
Secure.ACCESSIBILITY_MAGNIFICATION_MODE_WINDOW));
VALIDATORS.put(
- Secure.ACCESSIBILITY_BUTTON_LONG_PRESS_TARGETS,
+ Secure.ACCESSIBILITY_BUTTON_TARGETS,
ACCESSIBILITY_SHORTCUT_TARGET_LIST_VALIDATOR);
}
}
diff --git a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java
index b22caf0edc66..8a7b9134a5d9 100644
--- a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java
+++ b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java
@@ -1811,8 +1811,8 @@ class SettingsProtoDumpUtil {
Settings.Secure.ACCESSIBILITY_MAGNIFICATION_MODE,
SecureSettingsProto.Accessibility.ACCESSIBILITY_MAGNIFICATION_MODE);
dumpSetting(s, p,
- Settings.Secure.ACCESSIBILITY_BUTTON_LONG_PRESS_TARGETS,
- SecureSettingsProto.Accessibility.BUTTON_LONG_PRESS_TARGETS);
+ Settings.Secure.ACCESSIBILITY_BUTTON_TARGETS,
+ SecureSettingsProto.Accessibility.BUTTON_TARGETS);
p.end(accessibilityToken);
final long adaptiveSleepToken = p.start(SecureSettingsProto.ADAPTIVE_SLEEP);
@@ -1972,6 +1972,13 @@ class SettingsProtoDumpUtil {
dumpSetting(s, p,
Settings.Secure.CONNECTIVITY_RELEASE_PENDING_INTENT_DELAY_MS,
SecureSettingsProto.CONNECTIVITY_RELEASE_PENDING_INTENT_DELAY_MS);
+
+ final long controlsToken = p.start(SecureSettingsProto.CONTROLS);
+ dumpSetting(s, p,
+ Settings.Secure.CONTROLS_ENABLED,
+ SecureSettingsProto.Controls.ENABLED);
+ p.end(controlsToken);
+
dumpSetting(s, p,
Settings.Secure.DEVICE_PAIRED,
SecureSettingsProto.DEVICE_PAIRED);
diff --git a/packages/Shell/src/com/android/shell/BugreportProgressService.java b/packages/Shell/src/com/android/shell/BugreportProgressService.java
index 0ae00e1ac8b5..a1376c3203f5 100644
--- a/packages/Shell/src/com/android/shell/BugreportProgressService.java
+++ b/packages/Shell/src/com/android/shell/BugreportProgressService.java
@@ -1808,13 +1808,13 @@ public class BugreportProgressService extends Service {
* Current value of progress (in percentage) of the bugreport generation as
* displayed by the UI.
*/
- AtomicInteger progress;
+ AtomicInteger progress = new AtomicInteger(0);
/**
* Last value of progress (in percentage) of the bugreport generation for which
* system notification was updated.
*/
- AtomicInteger lastProgress;
+ AtomicInteger lastProgress = new AtomicInteger(0);
/**
* Time of the last progress update.
diff --git a/packages/SystemUI/res/drawable/control_background_ripple.xml b/packages/SystemUI/res/drawable/control_background_ripple.xml
new file mode 100644
index 000000000000..37914e272811
--- /dev/null
+++ b/packages/SystemUI/res/drawable/control_background_ripple.xml
@@ -0,0 +1,23 @@
+<!--
+ ~ 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.
+ -->
+
+<ripple xmlns:android="http://schemas.android.com/apk/res/android"
+ android:color="?android:attr/colorControlHighlight">
+ <item android:id="@android:id/mask">
+ <color android:color="@android:color/white" />
+ </item>
+ <item android:drawable="@drawable/control_background" />
+</ripple> \ No newline at end of file
diff --git a/packages/SystemUI/res/drawable/ic_device_air_freshener_off.xml b/packages/SystemUI/res/drawable/ic_device_air_freshener_off.xml
new file mode 100644
index 000000000000..c343020925eb
--- /dev/null
+++ b/packages/SystemUI/res/drawable/ic_device_air_freshener_off.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
+ -->
+<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="M12,5C12.5523,5 13,4.5523 13,4C13,3.4477 12.5523,3 12,3C11.4477,3 11,3.4477 11,4C11,4.5523 11.4477,5 12,5Z"
+ android:fillColor="#FF000000" />
+ <path
+ android:pathData="M12,2C12.5523,2 13,1.5523 13,1C13,0.4477 12.5523,0 12,0C11.4477,0 11,0.4477 11,1C11,1.5523 11.4477,2 12,2Z"
+ android:fillColor="#FF000000" />
+ <path
+ android:pathData="M9.707,4.707C9.8469,4.5671 9.9421,4.389 9.9808,4.195C10.0194,4.001 9.9996,3.7999 9.9239,3.6172C9.8482,3.4344 9.72,3.2782 9.5556,3.1683C9.3911,3.0584 9.1978,2.9998 9,2.9998C8.8022,2.9998 8.6088,3.0584 8.4444,3.1683C8.2799,3.2782 8.1518,3.4344 8.0761,3.6172C8.0004,3.7999 7.9806,4.001 8.0192,4.195C8.0578,4.389 8.1531,4.5671 8.293,4.707C8.4805,4.8944 8.7348,4.9998 9,4.9998C9.2652,4.9998 9.5195,4.8944 9.707,4.707Z"
+ android:fillColor="#FF000000" />
+ <path
+ android:pathData="M7.707,2.707C7.8469,2.5671 7.9422,2.389 7.9808,2.195C8.0194,2.001 7.9996,1.7999 7.9239,1.6172C7.8482,1.4344 7.7201,1.2782 7.5556,1.1683C7.3911,1.0584 7.1978,0.9998 7,0.9998C6.8022,0.9998 6.6089,1.0584 6.4444,1.1683C6.2799,1.2782 6.1518,1.4344 6.0761,1.6172C6.0004,1.7999 5.9806,2.001 6.0192,2.195C6.0578,2.389 6.1531,2.5671 6.293,2.707C6.4805,2.8944 6.7348,2.9998 7,2.9998C7.2652,2.9998 7.5195,2.8944 7.707,2.707Z"
+ android:fillColor="#FF000000" />
+ <path
+ android:pathData="M15.707,4.707C15.8469,4.5671 15.9421,4.389 15.9808,4.195C16.0194,4.001 15.9996,3.7999 15.9239,3.6172C15.8482,3.4344 15.7201,3.2782 15.5556,3.1683C15.3911,3.0584 15.1978,2.9998 15,2.9998C14.8022,2.9998 14.6088,3.0584 14.4444,3.1683C14.2799,3.2782 14.1518,3.4344 14.0761,3.6172C14.0004,3.7999 13.9806,4.001 14.0192,4.195C14.0578,4.389 14.1531,4.5671 14.293,4.707C14.4805,4.8944 14.7348,4.9998 15,4.9998C15.2652,4.9998 15.5195,4.8944 15.707,4.707Z"
+ android:fillColor="#FF000000" />
+ <path
+ android:pathData="M17.707,2.707C17.8469,2.5671 17.9421,2.389 17.9808,2.195C18.0194,2.001 17.9996,1.7999 17.9239,1.6172C17.8482,1.4344 17.7201,1.2782 17.5556,1.1683C17.3911,1.0584 17.1978,0.9998 17,0.9998C16.8022,0.9998 16.6088,1.0584 16.4444,1.1683C16.2799,1.2782 16.1518,1.4344 16.0761,1.6172C16.0004,1.7999 15.9806,2.001 16.0192,2.195C16.0578,2.389 16.1531,2.5671 16.293,2.707C16.4805,2.8944 16.7348,2.9998 17,2.9998C17.2652,2.9998 17.5195,2.8944 17.707,2.707Z"
+ android:fillColor="#FF000000" />
+ <path
+ android:pathData="M15,9.683V7C15,6.7348 14.8946,6.4804 14.7071,6.2929C14.5196,6.1054 14.2652,6 14,6H10C9.7348,6 9.4804,6.1054 9.2929,6.2929C9.1053,6.4804 9,6.7348 9,7V9.683C7.855,10.2245 6.8787,11.067 6.1756,12.1205C5.4725,13.174 5.0689,14.3988 5.0081,15.6639C4.9473,16.929 5.2315,18.1868 5.8304,19.3029C6.4292,20.4189 7.3202,21.3512 8.408,22H15.592C16.6798,21.3512 17.5707,20.4189 18.1696,19.3029C18.7685,18.1868 19.0527,16.929 18.9919,15.6639C18.9311,14.3988 18.5275,13.174 17.8244,12.1205C17.1212,11.067 16.145,10.2245 15,9.683ZM14.989,20H9.011C8.3852,19.5381 7.877,18.9352 7.5276,18.2402C7.1783,17.5453 6.9975,16.7778 7,16C7.0041,15.0553 7.2746,14.131 7.7803,13.3331C8.286,12.5351 9.0065,11.896 9.859,11.489L11,10.946V8H13V10.946L14.141,11.489C14.9935,11.896 15.714,12.5351 16.2197,13.3331C16.7254,14.131 16.9959,15.0553 17,16C17.0025,16.7778 16.8217,17.5453 16.4723,18.2402C16.123,18.9352 15.6148,19.5381 14.989,20Z"
+ android:fillColor="#FF000000" />
+</vector>
diff --git a/packages/SystemUI/res/drawable/ic_device_air_freshener_on.xml b/packages/SystemUI/res/drawable/ic_device_air_freshener_on.xml
new file mode 100644
index 000000000000..4f3434d3fbc5
--- /dev/null
+++ b/packages/SystemUI/res/drawable/ic_device_air_freshener_on.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
+ -->
+<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="M12,5C12.5523,5 13,4.5523 13,4C13,3.4477 12.5523,3 12,3C11.4477,3 11,3.4477 11,4C11,4.5523 11.4477,5 12,5Z"
+ android:fillColor="#FF000000" />
+ <path
+ android:pathData="M12,2C12.5523,2 13,1.5523 13,1C13,0.4477 12.5523,0 12,0C11.4477,0 11,0.4477 11,1C11,1.5523 11.4477,2 12,2Z"
+ android:fillColor="#FF000000" />
+ <path
+ android:pathData="M9.707,4.707C9.8469,4.5671 9.9422,4.389 9.9808,4.195C10.0194,4.001 9.9996,3.7999 9.9239,3.6172C9.8482,3.4344 9.7201,3.2782 9.5556,3.1683C9.3912,3.0584 9.1978,2.9998 9,2.9998C8.8022,2.9998 8.6088,3.0584 8.4444,3.1683C8.2799,3.2782 8.1518,3.4344 8.0761,3.6172C8.0004,3.7999 7.9806,4.001 8.0192,4.195C8.0578,4.389 8.1531,4.5671 8.293,4.707C8.4805,4.8944 8.7348,4.9998 9,4.9998C9.2652,4.9998 9.5195,4.8944 9.707,4.707Z"
+ android:fillColor="#FF000000" />
+ <path
+ android:pathData="M7.707,2.707C7.8469,2.5671 7.9422,2.389 7.9808,2.195C8.0194,2.001 7.9996,1.7999 7.9239,1.6172C7.8482,1.4344 7.7201,1.2782 7.5556,1.1683C7.3911,1.0584 7.1978,0.9998 7,0.9998C6.8022,0.9998 6.6089,1.0584 6.4444,1.1683C6.2799,1.2782 6.1518,1.4344 6.0761,1.6172C6.0004,1.7999 5.9806,2.001 6.0192,2.195C6.0578,2.389 6.1531,2.5671 6.293,2.707C6.4805,2.8944 6.7348,2.9998 7,2.9998C7.2652,2.9998 7.5195,2.8944 7.707,2.707Z"
+ android:fillColor="#FF000000" />
+ <path
+ android:pathData="M15.707,4.707C15.8469,4.5671 15.9422,4.389 15.9808,4.195C16.0194,4.001 15.9996,3.7999 15.9239,3.6172C15.8482,3.4344 15.7201,3.2782 15.5556,3.1683C15.3911,3.0584 15.1978,2.9998 15,2.9998C14.8022,2.9998 14.6089,3.0584 14.4444,3.1683C14.2799,3.2782 14.1518,3.4344 14.0761,3.6172C14.0004,3.7999 13.9806,4.001 14.0192,4.195C14.0578,4.389 14.1531,4.5671 14.293,4.707C14.4805,4.8944 14.7348,4.9998 15,4.9998C15.2652,4.9998 15.5195,4.8944 15.707,4.707Z"
+ android:fillColor="#FF000000" />
+ <path
+ android:pathData="M17.707,2.707C17.8469,2.5671 17.9422,2.389 17.9808,2.195C18.0194,2.001 17.9996,1.7999 17.9239,1.6172C17.8482,1.4344 17.7201,1.2782 17.5556,1.1683C17.3911,1.0584 17.1978,0.9998 17,0.9998C16.8022,0.9998 16.6089,1.0584 16.4444,1.1683C16.2799,1.2782 16.1518,1.4344 16.0761,1.6172C16.0004,1.7999 15.9806,2.001 16.0192,2.195C16.0578,2.389 16.1531,2.5671 16.293,2.707C16.4805,2.8944 16.7348,2.9998 17,2.9998C17.2652,2.9998 17.5195,2.8944 17.707,2.707Z"
+ android:fillColor="#FF000000" />
+ <path
+ android:pathData="M15,9.683V7C15,6.7348 14.8946,6.4804 14.7071,6.2929C14.5196,6.1054 14.2652,6 14,6H10C9.7348,6 9.4804,6.1054 9.2929,6.2929C9.1053,6.4804 9,6.7348 9,7V9.683C7.855,10.2245 6.8787,11.067 6.1756,12.1205C5.4725,13.174 5.0689,14.3988 5.0081,15.6639C4.9473,16.929 5.2315,18.1868 5.8304,19.3029C6.4292,20.4189 7.3202,21.3512 8.408,22H15.592C16.6798,21.3512 17.5707,20.4189 18.1696,19.3029C18.7685,18.1868 19.0527,16.929 18.9919,15.6639C18.9311,14.3988 18.5275,13.174 17.8244,12.1205C17.1213,11.067 16.145,10.2245 15,9.683Z"
+ android:fillColor="#FF000000" />
+</vector>
diff --git a/packages/SystemUI/res/drawable/ic_device_air_purifier_off.xml b/packages/SystemUI/res/drawable/ic_device_air_purifier_off.xml
new file mode 100644
index 000000000000..b18c3e77ef10
--- /dev/null
+++ b/packages/SystemUI/res/drawable/ic_device_air_purifier_off.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
+ -->
+<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="M16,19H5V7C5.0016,6.47 5.2128,5.9623 5.5875,5.5875C5.9623,5.2128 6.47,5.0016 7,5H14C14.5299,5.0016 15.0377,5.2128 15.4125,5.5875C15.7872,5.9623 15.9984,6.47 16,7V8H18V7C18,5.9391 17.5786,4.9217 16.8284,4.1716C16.0783,3.4214 15.0609,3 14,3H7C5.9391,3 4.9217,3.4214 4.1716,4.1716C3.4214,4.9217 3,5.9391 3,7V21H18V17H16V19Z"
+ android:fillColor="#FF000000" />
+ <path
+ android:pathData="M19,13C18.6049,13.378 18.1309,13.6638 17.6122,13.8367C17.0935,14.0096 16.5429,14.0653 16,14V16C16.5429,16.0653 17.0935,16.0096 17.6122,15.8367C18.1309,15.6638 18.6049,15.378 19,15C19.93,14.02 20,14 21,14V12C20,12 19.93,12.02 19,13Z"
+ android:fillColor="#FF000000" />
+ <path
+ android:pathData="M19,9C18.6049,9.378 18.1309,9.6638 17.6122,9.8367C17.0935,10.0096 16.5429,10.0653 16,10V12C16.5429,12.0653 17.0935,12.0096 17.6122,11.8367C18.1309,11.6638 18.6049,11.378 19,11C19.93,10.02 20,10 21,10V8C20,8 19.93,8.02 19,9Z"
+ android:fillColor="#FF000000" />
+ <path
+ android:pathData="M10.5,8C9.7089,8 8.9355,8.2346 8.2777,8.6741C7.6199,9.1137 7.1072,9.7383 6.8045,10.4692C6.5017,11.2001 6.4225,12.0044 6.5769,12.7803C6.7312,13.5563 7.1122,14.269 7.6716,14.8284C8.231,15.3878 8.9437,15.7688 9.7196,15.9232C10.4956,16.0775 11.2998,15.9982 12.0307,15.6955C12.7616,15.3927 13.3864,14.8801 13.8259,14.2223C14.2654,13.5645 14.5,12.7911 14.5,12C14.5,10.9391 14.0786,9.9217 13.3284,9.1716C12.5783,8.4214 11.5609,8 10.5,8ZM10.5,14C10.1044,14 9.7178,13.8827 9.3889,13.663C9.06,13.4432 8.8036,13.1308 8.6522,12.7654C8.5009,12.3999 8.4613,11.9978 8.5384,11.6098C8.6156,11.2218 8.8061,10.8655 9.0858,10.5858C9.3655,10.3061 9.7219,10.1156 10.1098,10.0385C10.4978,9.9613 10.8999,10.0008 11.2654,10.1522C11.6308,10.3036 11.9432,10.56 12.1629,10.8889C12.3827,11.2178 12.5,11.6044 12.5,12C12.5,12.5304 12.2893,13.0391 11.9142,13.4142C11.5391,13.7893 11.0304,14 10.5,14Z"
+ android:fillColor="#FF000000" />
+</vector>
diff --git a/packages/SystemUI/res/drawable/ic_device_air_purifier_on.xml b/packages/SystemUI/res/drawable/ic_device_air_purifier_on.xml
new file mode 100644
index 000000000000..b18c3e77ef10
--- /dev/null
+++ b/packages/SystemUI/res/drawable/ic_device_air_purifier_on.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
+ -->
+<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="M16,19H5V7C5.0016,6.47 5.2128,5.9623 5.5875,5.5875C5.9623,5.2128 6.47,5.0016 7,5H14C14.5299,5.0016 15.0377,5.2128 15.4125,5.5875C15.7872,5.9623 15.9984,6.47 16,7V8H18V7C18,5.9391 17.5786,4.9217 16.8284,4.1716C16.0783,3.4214 15.0609,3 14,3H7C5.9391,3 4.9217,3.4214 4.1716,4.1716C3.4214,4.9217 3,5.9391 3,7V21H18V17H16V19Z"
+ android:fillColor="#FF000000" />
+ <path
+ android:pathData="M19,13C18.6049,13.378 18.1309,13.6638 17.6122,13.8367C17.0935,14.0096 16.5429,14.0653 16,14V16C16.5429,16.0653 17.0935,16.0096 17.6122,15.8367C18.1309,15.6638 18.6049,15.378 19,15C19.93,14.02 20,14 21,14V12C20,12 19.93,12.02 19,13Z"
+ android:fillColor="#FF000000" />
+ <path
+ android:pathData="M19,9C18.6049,9.378 18.1309,9.6638 17.6122,9.8367C17.0935,10.0096 16.5429,10.0653 16,10V12C16.5429,12.0653 17.0935,12.0096 17.6122,11.8367C18.1309,11.6638 18.6049,11.378 19,11C19.93,10.02 20,10 21,10V8C20,8 19.93,8.02 19,9Z"
+ android:fillColor="#FF000000" />
+ <path
+ android:pathData="M10.5,8C9.7089,8 8.9355,8.2346 8.2777,8.6741C7.6199,9.1137 7.1072,9.7383 6.8045,10.4692C6.5017,11.2001 6.4225,12.0044 6.5769,12.7803C6.7312,13.5563 7.1122,14.269 7.6716,14.8284C8.231,15.3878 8.9437,15.7688 9.7196,15.9232C10.4956,16.0775 11.2998,15.9982 12.0307,15.6955C12.7616,15.3927 13.3864,14.8801 13.8259,14.2223C14.2654,13.5645 14.5,12.7911 14.5,12C14.5,10.9391 14.0786,9.9217 13.3284,9.1716C12.5783,8.4214 11.5609,8 10.5,8ZM10.5,14C10.1044,14 9.7178,13.8827 9.3889,13.663C9.06,13.4432 8.8036,13.1308 8.6522,12.7654C8.5009,12.3999 8.4613,11.9978 8.5384,11.6098C8.6156,11.2218 8.8061,10.8655 9.0858,10.5858C9.3655,10.3061 9.7219,10.1156 10.1098,10.0385C10.4978,9.9613 10.8999,10.0008 11.2654,10.1522C11.6308,10.3036 11.9432,10.56 12.1629,10.8889C12.3827,11.2178 12.5,11.6044 12.5,12C12.5,12.5304 12.2893,13.0391 11.9142,13.4142C11.5391,13.7893 11.0304,14 10.5,14Z"
+ android:fillColor="#FF000000" />
+</vector>
diff --git a/packages/SystemUI/res/drawable/ic_device_blinds_off.xml b/packages/SystemUI/res/drawable/ic_device_blinds_off.xml
new file mode 100644
index 000000000000..a511ad22c73e
--- /dev/null
+++ b/packages/SystemUI/res/drawable/ic_device_blinds_off.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="24dp"
+ android:height="24dp"
+ android:viewportWidth="24"
+ android:viewportHeight="24">
+ <path
+ android:pathData="M20,18V4H4V18H2V20H22V18H20ZM18,6V9H6V6H18ZM6,18V11H11V13.2771C10.6187,13.4972 10.3207,13.8369 10.1522,14.2437C9.9838,14.6504 9.9542,15.1013 10.0681,15.5266C10.1821,15.9519 10.4332,16.3277 10.7825,16.5957C11.1318,16.8637 11.5597,17.009 12,17.009C12.4403,17.009 12.8682,16.8637 13.2175,16.5957C13.5668,16.3277 13.8179,15.9519 13.9319,15.5266C14.0458,15.1013 14.0162,14.6504 13.8478,14.2437C13.6793,13.8369 13.3813,13.4972 13,13.2771V11H18V18H6Z"
+ android:fillColor="#FF000000" />
+</vector>
diff --git a/packages/SystemUI/res/drawable/ic_device_blinds_on.xml b/packages/SystemUI/res/drawable/ic_device_blinds_on.xml
new file mode 100644
index 000000000000..81662741c468
--- /dev/null
+++ b/packages/SystemUI/res/drawable/ic_device_blinds_on.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="24dp"
+ android:height="24dp"
+ android:viewportWidth="24"
+ android:viewportHeight="24">
+ <path
+ android:pathData="M20,18V4H4V18H2V20H22V18H20ZM6,18V11H11V13.2771C10.6187,13.4972 10.3207,13.8369 10.1522,14.2437C9.9838,14.6504 9.9542,15.1013 10.0681,15.5266C10.1821,15.9519 10.4332,16.3277 10.7825,16.5957C11.1318,16.8637 11.5597,17.009 12,17.009C12.4403,17.009 12.8682,16.8637 13.2175,16.5957C13.5668,16.3277 13.8179,15.9519 13.9319,15.5266C14.0458,15.1013 14.0162,14.6504 13.8478,14.2437C13.6793,13.8369 13.3813,13.4972 13,13.2771V11H18V18H6Z"
+ android:fillColor="#FF000000" />
+</vector>
diff --git a/packages/SystemUI/res/drawable/ic_device_camera_off.xml b/packages/SystemUI/res/drawable/ic_device_camera_off.xml
new file mode 100644
index 000000000000..32cad145e989
--- /dev/null
+++ b/packages/SystemUI/res/drawable/ic_device_camera_off.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="24dp"
+ android:height="24dp"
+ android:viewportWidth="24"
+ android:viewportHeight="24">
+ <path
+ android:pathData="M18,10.48V6C17.9984,5.47 17.7872,4.9624 17.4125,4.5876C17.0377,4.2129 16.5299,4.0016 16,4H4C3.4701,4.0016 2.9623,4.2129 2.5875,4.5876C2.2128,4.9624 2.0016,5.47 2,6V18C2.0016,18.5299 2.2128,19.0376 2.5875,19.4124C2.9623,19.7871 3.4701,19.9984 4,20H16C16.5299,19.9984 17.0377,19.7871 17.4125,19.4124C17.7872,19.0376 17.9984,18.5299 18,18V13.52L22,17.5V6.5L18,10.48ZM16,9.6899V18H4V6H16V9.6899Z"
+ android:fillColor="#FF000000" />
+</vector>
diff --git a/packages/SystemUI/res/drawable/ic_device_camera_on.xml b/packages/SystemUI/res/drawable/ic_device_camera_on.xml
new file mode 100644
index 000000000000..93c50f050d81
--- /dev/null
+++ b/packages/SystemUI/res/drawable/ic_device_camera_on.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="24dp"
+ android:height="24dp"
+ android:viewportWidth="24"
+ android:viewportHeight="24">
+ <path
+ android:pathData="M18,10.48V6C17.9984,5.47 17.7872,4.9624 17.4125,4.5876C17.0377,4.2129 16.5299,4.0016 16,4H4C3.4701,4.0016 2.9623,4.2129 2.5875,4.5876C2.2128,4.9624 2.0016,5.47 2,6V18C2.0016,18.5299 2.2128,19.0376 2.5875,19.4124C2.9623,19.7871 3.4701,19.9984 4,20H16C16.5299,19.9984 17.0377,19.7871 17.4125,19.4124C17.7872,19.0376 17.9984,18.5299 18,18V13.52L22,17.5V6.5L18,10.48Z"
+ android:fillColor="#FF000000" />
+</vector>
diff --git a/packages/SystemUI/res/drawable/ic_device_dishwasher_off.xml b/packages/SystemUI/res/drawable/ic_device_dishwasher_off.xml
new file mode 100644
index 000000000000..16ad90b2d13e
--- /dev/null
+++ b/packages/SystemUI/res/drawable/ic_device_dishwasher_off.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
+ -->
+<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.01L6,2C5.7371,1.9991 5.4766,2.0502 5.2335,2.1504C4.9905,2.2506 4.7696,2.3979 4.5837,2.5838C4.3978,2.7696 4.2505,2.9905 4.1504,3.2335C4.0502,3.4766 3.9991,3.7371 4,4V20C3.9991,20.2629 4.0502,20.5234 4.1504,20.7665C4.2505,21.0096 4.3978,21.2304 4.5837,21.4163C4.7696,21.6022 4.9905,21.7494 5.2335,21.8496C5.4766,21.9498 5.7371,22.0009 6,22H18C18.2629,22.0009 18.5234,21.9498 18.7665,21.8496C19.0095,21.7494 19.2304,21.6022 19.4163,21.4163C19.6022,21.2304 19.7495,21.0096 19.8496,20.7665C19.9498,20.5234 20.0009,20.2629 20,20V4C20.0007,3.7376 19.9493,3.4778 19.8489,3.2354C19.7485,2.993 19.6011,2.7728 19.4151,2.5878C19.2291,2.4027 19.0083,2.2564 18.7654,2.1572C18.5225,2.0581 18.2624,2.008 18,2.01ZM18,20H6L5.993,4H18V20Z"
+ android:fillColor="#FF000000" />
+ <path
+ android:pathData="M11,7C11.5523,7 12,6.5523 12,6C12,5.4477 11.5523,5 11,5C10.4477,5 10,5.4477 10,6C10,6.5523 10.4477,7 11,7Z"
+ android:fillColor="#FF000000" />
+ <path
+ android:pathData="M8,7C8.5523,7 9,6.5523 9,6C9,5.4477 8.5523,5 8,5C7.4477,5 7,5.4477 7,6C7,6.5523 7.4477,7 8,7Z"
+ android:fillColor="#FF000000" />
+ <path
+ android:pathData="M8.211,14.272C8.2337,15.2618 8.6429,16.2035 9.351,16.8955C10.0591,17.5875 11.0099,17.975 12,17.975C12.9901,17.975 13.9409,17.5875 14.649,16.8955C15.3571,16.2035 15.7663,15.2618 15.789,14.272C15.7891,13.7805 15.6908,13.2941 15.5,12.8412C15.3092,12.3883 15.0297,11.9782 14.678,11.635L12,9L9.322,11.635C8.9703,11.9782 8.6908,12.3883 8.5,12.8412C8.3092,13.2941 8.2109,13.7805 8.211,14.272ZM10.724,13.061L12,11.806L13.276,13.061C13.4381,13.2184 13.567,13.4065 13.6551,13.6145C13.7432,13.8225 13.7888,14.0461 13.789,14.272C13.7735,14.7361 13.5782,15.1761 13.2444,15.4989C12.9106,15.8217 12.4644,16.0022 12,16.0022C11.5356,16.0022 11.0894,15.8217 10.7556,15.4989C10.4218,15.1761 10.2265,14.7361 10.211,14.272C10.2111,14.0461 10.2566,13.8225 10.3447,13.6145C10.4328,13.4065 10.5618,13.2183 10.724,13.061Z"
+ android:fillColor="#FF000000" />
+</vector>
diff --git a/packages/SystemUI/res/drawable/ic_device_dishwasher_on.xml b/packages/SystemUI/res/drawable/ic_device_dishwasher_on.xml
new file mode 100644
index 000000000000..63f99ce5ec2c
--- /dev/null
+++ b/packages/SystemUI/res/drawable/ic_device_dishwasher_on.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="24dp"
+ android:height="24dp"
+ android:viewportWidth="24"
+ android:viewportHeight="24">
+ <path
+ android:pathData="M18,2.01L6,2C5.7371,1.9991 5.4766,2.0502 5.2335,2.1504C4.9905,2.2506 4.7696,2.3979 4.5837,2.5838C4.3978,2.7696 4.2505,2.9905 4.1504,3.2335C4.0502,3.4766 3.9991,3.7371 4,4V20C3.9991,20.2629 4.0502,20.5234 4.1504,20.7665C4.2505,21.0096 4.3978,21.2304 4.5837,21.4163C4.7696,21.6022 4.9905,21.7494 5.2335,21.8496C5.4766,21.9498 5.7371,22.0009 6,22H18C18.2629,22.0009 18.5234,21.9498 18.7665,21.8496C19.0095,21.7494 19.2304,21.6022 19.4163,21.4163C19.6022,21.2304 19.7495,21.0096 19.8496,20.7665C19.9498,20.5234 20.0009,20.2629 20,20V4C20.0007,3.7376 19.9493,3.4778 19.8489,3.2354C19.7485,2.993 19.6011,2.7728 19.4151,2.5878C19.2291,2.4027 19.0083,2.2564 18.7654,2.1572C18.5225,2.0581 18.2624,2.008 18,2.01ZM11,5C11.1978,5 11.3911,5.0587 11.5556,5.1686C11.72,5.2785 11.8482,5.4346 11.9239,5.6173C11.9996,5.8 12.0194,6.0011 11.9808,6.1951C11.9422,6.3891 11.847,6.5673 11.7071,6.7072C11.5673,6.847 11.3891,6.9423 11.1951,6.9809C11.0011,7.0194 10.8,6.9995 10.6173,6.9238C10.4346,6.8481 10.2784,6.72 10.1685,6.5556C10.0586,6.3911 10,6.1978 10,6C10,5.7348 10.1054,5.4804 10.2929,5.2929C10.4804,5.1053 10.7348,5 11,5ZM7,6C7,5.8022 7.0587,5.6089 7.1685,5.4445C7.2784,5.28 7.4346,5.1519 7.6173,5.0762C7.8,5.0005 8.0011,4.9806 8.1951,5.0192C8.3891,5.0578 8.5673,5.153 8.7071,5.2929C8.847,5.4327 8.9422,5.611 8.9808,5.8049C9.0194,5.9989 8.9996,6.2 8.9239,6.3827C8.8482,6.5654 8.72,6.7215 8.5556,6.8314C8.3911,6.9413 8.1978,7 8,7C7.7348,7 7.4804,6.8947 7.2929,6.7072C7.1054,6.5196 7,6.2652 7,6ZM12,18C11.0032,18.008 10.0441,17.6198 9.3335,16.9207C8.623,16.2216 8.2192,15.2688 8.211,14.272C8.2109,13.7806 8.3092,13.2941 8.5,12.8412C8.6908,12.3883 8.9703,11.9782 9.322,11.635L12,9L14.678,11.635C15.0297,11.9782 15.3092,12.3883 15.5,12.8412C15.6908,13.2941 15.7891,13.7806 15.789,14.272C15.7808,15.2688 15.377,16.2216 14.6665,16.9207C13.9559,17.6198 12.9968,18.008 12,18Z"
+ android:fillColor="#FF000000" />
+</vector>
diff --git a/packages/SystemUI/res/drawable/ic_device_doorbell_off.xml b/packages/SystemUI/res/drawable/ic_device_doorbell_off.xml
new file mode 100644
index 000000000000..6c03a4bfb883
--- /dev/null
+++ b/packages/SystemUI/res/drawable/ic_device_doorbell_off.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
+ -->
+<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="M17,2H7C6.4696,2 5.9609,2.2106 5.5858,2.5857C5.2107,2.9608 5,3.4696 5,4V20C5,20.5304 5.2107,21.0392 5.5858,21.4143C5.9609,21.7894 6.4696,22 7,22H17C17.5304,22 18.0391,21.7894 18.4142,21.4143C18.7893,21.0392 19,20.5304 19,20V4C19,3.4696 18.7893,2.9608 18.4142,2.5857C18.0391,2.2106 17.5304,2 17,2ZM17,20H7V4H17V20Z"
+ android:fillColor="#FF000000" />
+ <path
+ android:pathData="M12,15C11.6044,15 11.2177,15.1174 10.8889,15.3372C10.56,15.5569 10.3036,15.8692 10.1522,16.2346C10.0009,16.6001 9.9613,17.0022 10.0384,17.3901C10.1156,17.7781 10.3061,18.1346 10.5858,18.4143C10.8655,18.694 11.2219,18.8845 11.6098,18.9617C11.9978,19.0388 12.3999,18.999 12.7654,18.8477C13.1308,18.6963 13.4432,18.44 13.6629,18.1111C13.8827,17.7822 14,17.3956 14,17C14,16.4696 13.7893,15.9608 13.4142,15.5857C13.0391,15.2106 12.5304,15 12,15ZM12,18C11.8022,18 11.6089,17.9414 11.4444,17.8315C11.28,17.7217 11.1518,17.5653 11.0761,17.3826C11.0004,17.1998 10.9806,16.9989 11.0192,16.8049C11.0578,16.611 11.153,16.4328 11.2929,16.293C11.4327,16.1531 11.6109,16.0579 11.8049,16.0193C11.9989,15.9807 12.2,16.0005 12.3827,16.0762C12.5654,16.1519 12.7216,16.2799 12.8315,16.4443C12.9413,16.6088 13,16.8022 13,17C13,17.2652 12.8946,17.5195 12.7071,17.707C12.5196,17.8946 12.2652,18 12,18Z"
+ android:fillColor="#FF000000" />
+ <path
+ android:pathData="M13,12.5H11C11,12.7652 11.1054,13.0195 11.2929,13.207C11.4804,13.3946 11.7348,13.5 12,13.5C12.2652,13.5 12.5196,13.3946 12.7071,13.207C12.8946,13.0195 13,12.7652 13,12.5Z"
+ android:fillColor="#FF000000" />
+ <path
+ android:pathData="M16,11H15V8.6599C15.0532,7.9533 14.8572,7.2506 14.4462,6.6733C14.0352,6.0961 13.4351,5.6809 12.75,5.5V5.25C12.75,5.0511 12.671,4.8604 12.5303,4.7197C12.3897,4.5791 12.1989,4.5 12,4.5C11.8011,4.5 11.6103,4.5791 11.4697,4.7197C11.329,4.8604 11.25,5.0511 11.25,5.25V5.5C10.5659,5.6827 9.9669,6.0982 9.5562,6.675C9.1455,7.2519 8.9488,7.9537 9,8.6599V11H8V12H16V11Z"
+ android:fillColor="#FF000000" />
+</vector>
diff --git a/packages/SystemUI/res/drawable/ic_device_doorbell_on.xml b/packages/SystemUI/res/drawable/ic_device_doorbell_on.xml
new file mode 100644
index 000000000000..d08393a05f93
--- /dev/null
+++ b/packages/SystemUI/res/drawable/ic_device_doorbell_on.xml
@@ -0,0 +1,28 @@
+<?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="24dp"
+ android:height="24dp"
+ android:viewportWidth="24"
+ android:viewportHeight="24">
+ <path
+ android:pathData="M12,18C12.5523,18 13,17.5523 13,17C13,16.4477 12.5523,16 12,16C11.4477,16 11,16.4477 11,17C11,17.5523 11.4477,18 12,18Z"
+ android:fillColor="#FF000000" />
+ <path
+ android:pathData="M17,2H7C6.4696,2 5.9609,2.2106 5.5858,2.5857C5.2107,2.9608 5,3.4696 5,4V20C5,20.5304 5.2107,21.0392 5.5858,21.4143C5.9609,21.7894 6.4696,22 7,22H17C17.5304,22 18.0391,21.7894 18.4142,21.4143C18.7893,21.0392 19,20.5304 19,20V4C19,3.4696 18.7893,2.9608 18.4142,2.5857C18.0391,2.2106 17.5304,2 17,2ZM12,19C11.6044,19 11.2178,18.8826 10.8889,18.6628C10.56,18.4431 10.3036,18.1308 10.1522,17.7654C10.0009,17.3999 9.9613,16.9978 10.0384,16.6099C10.1156,16.2219 10.3061,15.8654 10.5858,15.5857C10.8655,15.306 11.2219,15.1155 11.6098,15.0383C11.9978,14.9612 12.3999,15.001 12.7654,15.1523C13.1308,15.3037 13.4432,15.56 13.6629,15.8889C13.8827,16.2178 14,16.6044 14,17C14,17.5304 13.7893,18.0392 13.4142,18.4143C13.0391,18.7894 12.5304,19 12,19ZM11,12.5H13C13,12.7652 12.8946,13.0195 12.7071,13.207C12.5196,13.3946 12.2652,13.5 12,13.5C11.7348,13.5 11.4804,13.3946 11.2929,13.207C11.1054,13.0195 11,12.7652 11,12.5ZM16,12H8V11H9V8.6599C8.9488,7.9537 9.1455,7.2519 9.5562,6.675C9.9669,6.0982 10.5659,5.6827 11.25,5.5V5.25C11.25,5.0511 11.329,4.8604 11.4697,4.7197C11.6103,4.5791 11.8011,4.5 12,4.5C12.1989,4.5 12.3897,4.5791 12.5303,4.7197C12.671,4.8604 12.75,5.0511 12.75,5.25V5.5C13.4351,5.6809 14.0352,6.0961 14.4462,6.6733C14.8572,7.2506 15.0532,7.9533 15,8.6599V11H16V12Z"
+ android:fillColor="#FF000000" />
+</vector>
diff --git a/packages/SystemUI/res/drawable/ic_device_drawer_off.xml b/packages/SystemUI/res/drawable/ic_device_drawer_off.xml
new file mode 100644
index 000000000000..bcab534eb0c9
--- /dev/null
+++ b/packages/SystemUI/res/drawable/ic_device_drawer_off.xml
@@ -0,0 +1,28 @@
+<?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="24dp"
+ android:height="24dp"
+ android:viewportWidth="24"
+ android:viewportHeight="24">
+ <path
+ android:pathData="M18,3H6C5.4696,3 4.9609,3.2109 4.5858,3.5859C4.2107,3.961 4,4.4696 4,5V21H6V19H18V21H20V5C20,4.4696 19.7893,3.961 19.4142,3.5859C19.0391,3.2109 18.5304,3 18,3ZM18,11H13V9H18V11ZM18,7H13V5H18V7ZM11,5V11H6V5H11ZM6,17V13H18V17H6Z"
+ android:fillColor="#FF000000" />
+ <path
+ android:pathData="M14,14H10V16H14V14Z"
+ android:fillColor="#FF000000" />
+</vector>
diff --git a/packages/SystemUI/res/drawable/ic_device_drawer_on.xml b/packages/SystemUI/res/drawable/ic_device_drawer_on.xml
new file mode 100644
index 000000000000..800e9f1fed41
--- /dev/null
+++ b/packages/SystemUI/res/drawable/ic_device_drawer_on.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="24dp"
+ android:height="24dp"
+ android:viewportWidth="24"
+ android:viewportHeight="24">
+ <path
+ android:pathData="M18,3H6C5.4696,3 4.9609,3.2109 4.5858,3.5859C4.2107,3.961 4,4.4696 4,5V21H6V19H18V21H20V5C20,4.4696 19.7893,3.961 19.4142,3.5859C19.0391,3.2109 18.5304,3 18,3ZM6,5H11V11H6V5ZM14,16H10V14H14V16ZM18,11H13V9H18V11ZM18,7H13V5H18V7Z"
+ android:fillColor="#FF000000" />
+</vector>
diff --git a/packages/SystemUI/res/drawable/ic_device_fan_off.xml b/packages/SystemUI/res/drawable/ic_device_fan_off.xml
new file mode 100644
index 000000000000..c90d5741736d
--- /dev/null
+++ b/packages/SystemUI/res/drawable/ic_device_fan_off.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="24dp"
+ android:height="24dp"
+ android:viewportWidth="24"
+ android:viewportHeight="24">
+ <path
+ android:pathData="M16.345,8.3611L14.055,9.1791C13.8731,9.0458 13.6785,8.9309 13.474,8.8361C13.6398,7.9956 14.1302,7.2543 14.839,6.7731C15.3079,6.465 15.6646,6.0136 15.8558,5.4861C16.047,4.9587 16.0625,4.3836 15.8999,3.8466C15.7374,3.3097 15.4055,2.8397 14.9538,2.5069C14.5022,2.1741 13.955,1.9963 13.394,2.0001C8.994,2.0001 7.157,5.0071 8.361,7.6551L9.179,9.9451C9.0458,10.1269 8.9309,10.3215 8.836,10.5261C7.9954,10.3606 7.254,9.8701 6.773,9.1611C6.465,8.6922 6.0135,8.3355 5.4861,8.1443C4.9587,7.9531 4.3835,7.9375 3.8466,8.1001C3.3096,8.2627 2.8396,8.5946 2.5068,9.0462C2.174,9.4979 1.9962,10.0451 2,10.6061C2,15.0061 5.007,16.843 7.655,15.639L9.945,14.821C10.1267,14.9541 10.3209,15.069 10.525,15.1641C10.3598,16.0048 9.8692,16.7463 9.16,17.227C8.691,17.5351 8.3343,17.9867 8.1431,18.5142C7.9519,19.0418 7.9365,19.617 8.0992,20.154C8.2619,20.691 8.5939,21.161 9.0457,21.4937C9.4976,21.8264 10.0449,22.004 10.606,22.0001C15.006,22.0001 16.843,18.993 15.639,16.345L14.821,14.0551C14.954,13.8734 15.0689,13.6791 15.164,13.475C16.0048,13.6402 16.7462,14.1309 17.227,14.8401C17.5351,15.3091 17.9866,15.6657 18.5141,15.8569C19.0417,16.0481 19.6169,16.0636 20.1539,15.9009C20.6909,15.7382 21.1609,15.4061 21.4936,14.9543C21.8264,14.5025 22.004,13.9551 22,13.394C22,9 18.993,7.1571 16.345,8.3611ZM12,13.5001C11.7033,13.5001 11.4133,13.4121 11.1666,13.2473C10.92,13.0824 10.7277,12.8482 10.6142,12.5741C10.5006,12.3 10.4709,11.9984 10.5288,11.7074C10.5867,11.4164 10.7296,11.1492 10.9393,10.9394C11.1491,10.7296 11.4164,10.5867 11.7074,10.5289C11.9983,10.471 12.2999,10.5007 12.574,10.6143C12.8481,10.7278 13.0824,10.92 13.2472,11.1667C13.412,11.4134 13.5,11.7034 13.5,12.0001C13.5,12.3979 13.342,12.7794 13.0607,13.0607C12.7793,13.342 12.3978,13.5001 12,13.5001ZM10.245,5.2161C10.6327,4.7742 11.1217,4.4328 11.6701,4.2211C12.2184,4.0093 12.8099,3.9335 13.394,4.0001C13.5259,3.9959 13.6555,4.0354 13.7627,4.1124C13.8699,4.1893 13.9487,4.2995 13.987,4.4258C14.0253,4.5521 14.0208,4.6875 13.9744,4.811C13.9279,4.9346 13.842,5.0393 13.73,5.1091C13.1418,5.5017 12.6392,6.0092 12.2521,6.601C11.8651,7.1929 11.6018,7.8568 11.478,8.553C11.2666,8.5847 11.0587,8.6362 10.857,8.707L10.181,6.8271C10.0515,6.576 9.9893,6.2955 10.0005,6.0131C10.0117,5.7308 10.0959,5.4561 10.245,5.2161ZM6.827,13.816C6.576,13.9458 6.2956,14.0083 6.0132,13.9973C5.7308,13.9862 5.4561,13.902 5.216,13.753C4.7745,13.3655 4.4332,12.8769 4.2215,12.3289C4.0098,11.7809 3.9338,11.1898 4,10.6061C3.9959,10.4742 4.0353,10.3446 4.1123,10.2374C4.1893,10.1302 4.2994,10.0513 4.4257,10.0131C4.552,9.9748 4.6874,9.9792 4.8109,10.0257C4.9345,10.0722 5.0392,10.1581 5.109,10.2701C5.5015,10.8581 6.0088,11.3607 6.6005,11.7477C7.1922,12.1347 7.8559,12.3981 8.552,12.522C8.5844,12.7334 8.6363,12.9413 8.707,13.1431L6.827,13.816ZM13.755,18.782C13.3675,19.2242 12.8786,19.566 12.3302,19.7781C11.7818,19.9902 11.1902,20.0664 10.606,20.0001C10.4741,20.0042 10.3445,19.9647 10.2373,19.8878C10.1301,19.8108 10.0512,19.7006 10.013,19.5743C9.9747,19.448 9.9791,19.3126 10.0256,19.1891C10.0721,19.0656 10.158,18.9608 10.27,18.8911C10.8581,18.4987 11.3606,17.9914 11.7475,17.3997C12.1343,16.808 12.3974,16.1441 12.521,15.4481C12.7327,15.4156 12.9409,15.3638 13.143,15.2931L13.818,17.173C13.9477,17.4241 14.0101,17.7045 13.999,17.9869C13.988,18.2692 13.9039,18.5439 13.755,18.7841V18.782ZM18.891,13.7281C18.4985,13.1399 17.991,12.6373 17.3992,12.2504C16.8073,11.8636 16.1432,11.6005 15.447,11.477C15.4154,11.2653 15.3639,11.057 15.293,10.855L17.173,10.1801C17.424,10.0503 17.7044,9.9879 17.9868,9.9989C18.2692,10.0099 18.5439,10.094 18.784,10.243C19.2261,10.631 19.5677,11.1202 19.7795,11.669C19.9912,12.2178 20.0669,12.8097 20,13.394C20.0041,13.5259 19.9647,13.6555 19.8877,13.7628C19.8107,13.87 19.7006,13.9488 19.5743,13.9871C19.448,14.0253 19.3126,14.0209 19.1891,13.9744C19.0655,13.928 18.9608,13.8421 18.891,13.73V13.7281Z"
+ android:fillColor="#FF000000" />
+</vector>
diff --git a/packages/SystemUI/res/drawable/ic_device_fan_on.xml b/packages/SystemUI/res/drawable/ic_device_fan_on.xml
new file mode 100644
index 000000000000..79950ea1bae9
--- /dev/null
+++ b/packages/SystemUI/res/drawable/ic_device_fan_on.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="24dp"
+ android:height="24dp"
+ android:viewportWidth="24"
+ android:viewportHeight="24">
+ <path
+ android:pathData="M16.345,8.3611L14.055,9.1791C13.8731,9.0458 13.6785,8.9309 13.474,8.8361C13.6398,7.9956 14.1302,7.2543 14.839,6.7731C15.3079,6.465 15.6646,6.0136 15.8558,5.4861C16.047,4.9587 16.0625,4.3836 15.8999,3.8466C15.7374,3.3097 15.4055,2.8397 14.9538,2.5069C14.5022,2.1741 13.955,1.9963 13.394,2.0001C8.994,2.0001 7.157,5.0071 8.361,7.6551L9.179,9.9451C9.0457,10.1269 8.9309,10.3215 8.836,10.5261C7.9954,10.3606 7.254,9.8701 6.773,9.1611C6.465,8.6922 6.0135,8.3355 5.4861,8.1443C4.9587,7.9531 4.3835,7.9375 3.8466,8.1001C3.3096,8.2627 2.8396,8.5946 2.5068,9.0462C2.174,9.4979 1.9962,10.0451 2,10.6061C2,15.0061 5.007,16.843 7.655,15.639L9.945,14.821C10.1267,14.9541 10.3209,15.069 10.525,15.1641C10.3598,16.0048 9.8692,16.7463 9.16,17.227C8.691,17.5351 8.3343,17.9867 8.1431,18.5142C7.9519,19.0418 7.9365,19.617 8.0992,20.154C8.2619,20.691 8.5939,21.161 9.0457,21.4937C9.4976,21.8264 10.0449,22.004 10.606,22.0001C15.006,22.0001 16.843,18.993 15.639,16.345L14.821,14.0551C14.954,13.8734 15.0689,13.6791 15.164,13.475C16.0048,13.6402 16.7462,14.1309 17.227,14.8401C17.5351,15.3091 17.9866,15.6657 18.5141,15.8569C19.0417,16.0481 19.6169,16.0636 20.1539,15.9009C20.6909,15.7382 21.1609,15.4061 21.4936,14.9543C21.8264,14.5025 22.004,13.9551 22,13.394C22,9 18.993,7.1571 16.345,8.3611ZM12,13.5001C11.7033,13.5001 11.4133,13.4121 11.1666,13.2473C10.92,13.0824 10.7277,12.8482 10.6142,12.5741C10.5006,12.3 10.4709,11.9984 10.5288,11.7074C10.5867,11.4164 10.7296,11.1492 10.9393,10.9394C11.1491,10.7296 11.4164,10.5867 11.7074,10.5289C11.9983,10.471 12.2999,10.5007 12.574,10.6143C12.8481,10.7278 13.0824,10.92 13.2472,11.1667C13.412,11.4134 13.5,11.7034 13.5,12.0001C13.5,12.3979 13.342,12.7794 13.0607,13.0607C12.7794,13.342 12.3978,13.5001 12,13.5001Z"
+ android:fillColor="#FF000000" />
+</vector>
diff --git a/packages/SystemUI/res/drawable/ic_device_garage_off.xml b/packages/SystemUI/res/drawable/ic_device_garage_off.xml
new file mode 100644
index 000000000000..8865983f0d7d
--- /dev/null
+++ b/packages/SystemUI/res/drawable/ic_device_garage_off.xml
@@ -0,0 +1,28 @@
+<?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="24dp"
+ android:height="24dp"
+ android:viewportWidth="24"
+ android:viewportHeight="24">
+ <path
+ android:pathData="M20,9L12,3L4,9V21H6V10L12,5.5L18,10V21H20V9Z"
+ android:fillColor="#FF000000" />
+ <path
+ android:pathData="M7,11V21H17V11H7ZM15,13V15H9V13H15ZM9,19V17H15V19H9Z"
+ android:fillColor="#FF000000" />
+</vector>
diff --git a/packages/SystemUI/res/drawable/ic_device_garage_on.xml b/packages/SystemUI/res/drawable/ic_device_garage_on.xml
new file mode 100644
index 000000000000..8865983f0d7d
--- /dev/null
+++ b/packages/SystemUI/res/drawable/ic_device_garage_on.xml
@@ -0,0 +1,28 @@
+<?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="24dp"
+ android:height="24dp"
+ android:viewportWidth="24"
+ android:viewportHeight="24">
+ <path
+ android:pathData="M20,9L12,3L4,9V21H6V10L12,5.5L18,10V21H20V9Z"
+ android:fillColor="#FF000000" />
+ <path
+ android:pathData="M7,11V21H17V11H7ZM15,13V15H9V13H15ZM9,19V17H15V19H9Z"
+ android:fillColor="#FF000000" />
+</vector>
diff --git a/packages/SystemUI/res/drawable/ic_device_gate_off.xml b/packages/SystemUI/res/drawable/ic_device_gate_off.xml
new file mode 100644
index 000000000000..9f7d9edfae31
--- /dev/null
+++ b/packages/SystemUI/res/drawable/ic_device_gate_off.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
+ -->
+<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="M4,7H2V17H4V7Z"
+ android:fillColor="#FF000000" />
+ <path
+ android:pathData="M15,5H9C7.9391,5 6.9217,5.4215 6.1716,6.1716C5.4214,6.9218 5,7.9391 5,9V19H19V9C19,7.9391 18.5786,6.9218 17.8284,6.1716C17.0783,5.4215 16.0609,5 15,5ZM7,9C7,8.4696 7.2107,7.9608 7.5858,7.5857C7.9609,7.2106 8.4696,7 9,7H11V11H9V13H11V17H7V9ZM17,17H13V13H15V11H13V7H15C15.5304,7 16.0391,7.2106 16.4142,7.5857C16.7893,7.9608 17,8.4696 17,9V17Z"
+ android:fillColor="#FF000000" />
+ <path
+ android:pathData="M22,7H20V17H22V7Z"
+ android:fillColor="#FF000000" />
+</vector>
diff --git a/packages/SystemUI/res/drawable/ic_device_gate_on.xml b/packages/SystemUI/res/drawable/ic_device_gate_on.xml
new file mode 100644
index 000000000000..1a005ac090dc
--- /dev/null
+++ b/packages/SystemUI/res/drawable/ic_device_gate_on.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
+ -->
+<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="M4,7H2V17H4V7Z"
+ android:fillColor="#FF000000" />
+ <path
+ android:pathData="M22,7H20V17H22V7Z"
+ android:fillColor="#FF000000" />
+ <path
+ android:pathData="M5,9V19H11V13H9V11H11V5H9C7.9391,5 6.9217,5.4215 6.1716,6.1716C5.4214,6.9218 5,7.9391 5,9Z"
+ android:fillColor="#FF000000" />
+ <path
+ android:pathData="M15,5H13V11H15V13H13V19H19V9C19,7.9391 18.5786,6.9218 17.8284,6.1716C17.0783,5.4215 16.0609,5 15,5Z"
+ android:fillColor="#FF000000" />
+</vector>
diff --git a/packages/SystemUI/res/drawable/ic_device_hood_off.xml b/packages/SystemUI/res/drawable/ic_device_hood_off.xml
new file mode 100644
index 000000000000..71d5f24b2489
--- /dev/null
+++ b/packages/SystemUI/res/drawable/ic_device_hood_off.xml
@@ -0,0 +1,28 @@
+<?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="24dp"
+ android:height="24dp"
+ android:viewportWidth="24"
+ android:viewportHeight="24">
+ <path
+ android:pathData="M21.414,12.414L17,8V3H7V8L2.586,12.414C2.2109,12.789 2.0001,13.2976 2,13.828V18C2,18.5304 2.2107,19.0391 2.5858,19.4142C2.9609,19.7893 3.4696,20 4,20H20C20.5304,20 21.0391,19.7893 21.4142,19.4142C21.7893,19.0391 22,18.5304 22,18V13.828C21.9999,13.2976 21.7891,12.789 21.414,12.414ZM9,8.828V5H15V8.828L18.172,12H5.828L9,8.828ZM20,18H4V14H20V18Z"
+ android:fillColor="#FF000000" />
+ <path
+ android:pathData="M14,15.25H10V16.75H14V15.25Z"
+ android:fillColor="#FF000000" />
+</vector>
diff --git a/packages/SystemUI/res/drawable/ic_device_hood_on.xml b/packages/SystemUI/res/drawable/ic_device_hood_on.xml
new file mode 100644
index 000000000000..721e68bde32b
--- /dev/null
+++ b/packages/SystemUI/res/drawable/ic_device_hood_on.xml
@@ -0,0 +1,28 @@
+<?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="24dp"
+ android:height="24dp"
+ android:viewportWidth="24"
+ android:viewportHeight="24">
+ <path
+ android:pathData="M21,12L17,8V3H7V8L3,12H21Z"
+ android:fillColor="#FF000000" />
+ <path
+ android:pathData="M2,14V18C2,18.5304 2.2107,19.0391 2.5858,19.4142C2.9609,19.7893 3.4696,20 4,20H20C20.5304,20 21.0391,19.7893 21.4142,19.4142C21.7893,19.0391 22,18.5304 22,18V14H2ZM14,16.75H10V15.25H14V16.75Z"
+ android:fillColor="#FF000000" />
+</vector>
diff --git a/packages/SystemUI/res/drawable/ic_device_kettle_off.xml b/packages/SystemUI/res/drawable/ic_device_kettle_off.xml
new file mode 100644
index 000000000000..94ad254a79bc
--- /dev/null
+++ b/packages/SystemUI/res/drawable/ic_device_kettle_off.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
+ -->
+<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="M20,5H18V2H3L6,6V19H18V14H20C20.5304,14 21.0391,13.7893 21.4142,13.4142C21.7893,13.0391 22,12.5304 22,12V7C22,6.4696 21.7893,5.9609 21.4142,5.5858C21.0391,5.2107 20.5304,5 20,5ZM16,17H8V5.333L7,4H16V17ZM20,12H18V7H20V12Z"
+ android:fillColor="#FF000000" />
+ <path
+ android:pathData="M15,5H12V16H15V5Z"
+ android:fillColor="#FF000000" />
+ <path
+ android:pathData="M21,20H3V22H21V20Z"
+ android:fillColor="#FF000000" />
+</vector>
diff --git a/packages/SystemUI/res/drawable/ic_device_kettle_on.xml b/packages/SystemUI/res/drawable/ic_device_kettle_on.xml
new file mode 100644
index 000000000000..11081e85fa90
--- /dev/null
+++ b/packages/SystemUI/res/drawable/ic_device_kettle_on.xml
@@ -0,0 +1,28 @@
+<?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="24dp"
+ android:height="24dp"
+ android:viewportWidth="24"
+ android:viewportHeight="24">
+ <path
+ android:pathData="M20,5H18V2H3L6,6V19H18V14H20C20.5304,14 21.0391,13.7893 21.4142,13.4142C21.7893,13.0391 22,12.5304 22,12V7C22,6.4696 21.7893,5.9609 21.4142,5.5858C21.0391,5.2107 20.5304,5 20,5ZM15,16H12V5H15V16ZM20,12H18V7H20V12Z"
+ android:fillColor="#FF000000" />
+ <path
+ android:pathData="M21,20H3V22H21V20Z"
+ android:fillColor="#FF000000" />
+</vector>
diff --git a/packages/SystemUI/res/drawable/ic_device_light_off.xml b/packages/SystemUI/res/drawable/ic_device_light_off.xml
new file mode 100644
index 000000000000..62fa631c5706
--- /dev/null
+++ b/packages/SystemUI/res/drawable/ic_device_light_off.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
+ -->
+<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="M12,22C12.5304,22 13.0391,21.7894 13.4142,21.4143C13.7893,21.0392 14,20.5304 14,20H10C10,20.5304 10.2107,21.0392 10.5858,21.4143C10.9609,21.7894 11.4696,22 12,22Z"
+ android:fillColor="#FF000000" />
+ <path
+ android:pathData="M16,17H8V19H16V17Z"
+ android:fillColor="#FF000000" />
+ <path
+ android:pathData="M12,2C10.3491,2.0023 8.7451,2.5493 7.4367,3.5561C6.1283,4.563 5.1887,5.9734 4.7636,7.5686C4.3385,9.1638 4.4516,10.8547 5.0854,12.3792C5.7191,13.9036 6.8382,15.1764 8.269,16H15.731C17.1618,15.1764 18.2809,13.9036 18.9147,12.3792C19.5485,10.8547 19.6616,9.1638 19.2364,7.5686C18.8113,5.9734 17.8717,4.563 16.5633,3.5561C15.2549,2.5493 13.6509,2.0023 12,2ZM15.148,14H8.848C8.1191,13.4982 7.5239,12.826 7.114,12.0417C6.7041,11.2575 6.4919,10.3849 6.496,9.5C6.496,8.0413 7.0755,6.6423 8.1069,5.6108C9.1384,4.5794 10.5373,4 11.996,4C13.4547,4 14.8536,4.5794 15.8851,5.6108C16.9165,6.6423 17.496,8.0413 17.496,9.5C17.5005,10.3846 17.289,11.2568 16.8798,12.041C16.4706,12.8252 15.8761,13.4977 15.148,14Z"
+ android:fillColor="#FF000000" />
+</vector>
diff --git a/packages/SystemUI/res/drawable/ic_device_light_on.xml b/packages/SystemUI/res/drawable/ic_device_light_on.xml
new file mode 100644
index 000000000000..08f05fca4e8b
--- /dev/null
+++ b/packages/SystemUI/res/drawable/ic_device_light_on.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
+ -->
+<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="M12,22C12.5304,22 13.0391,21.7894 13.4142,21.4143C13.7893,21.0392 14,20.5304 14,20H10C10,20.5304 10.2107,21.0392 10.5858,21.4143C10.9609,21.7894 11.4696,22 12,22Z"
+ android:fillColor="#FF000000" />
+ <path
+ android:pathData="M16,17H8V19H16V17Z"
+ android:fillColor="#FF000000" />
+ <path
+ android:pathData="M12,2C10.3491,2.0023 8.7451,2.5493 7.4367,3.5561C6.1283,4.563 5.1887,5.9734 4.7636,7.5686C4.3385,9.1638 4.4516,10.8547 5.0854,12.3792C5.7191,13.9036 6.8382,15.1764 8.269,16H15.731C17.1618,15.1764 18.2809,13.9036 18.9147,12.3792C19.5485,10.8547 19.6616,9.1638 19.2364,7.5686C18.8113,5.9734 17.8717,4.563 16.5633,3.5561C15.2549,2.5493 13.6509,2.0023 12,2Z"
+ android:fillColor="#FF000000" />
+</vector>
diff --git a/packages/SystemUI/res/drawable/ic_device_lock_off.xml b/packages/SystemUI/res/drawable/ic_device_lock_off.xml
new file mode 100644
index 000000000000..a2662ff7f6bb
--- /dev/null
+++ b/packages/SystemUI/res/drawable/ic_device_lock_off.xml
@@ -0,0 +1,28 @@
+<?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="24dp"
+ android:height="24dp"
+ android:viewportWidth="24"
+ android:viewportHeight="24">
+ <path
+ android:pathData="M18,8H17V6C17,4.6739 16.4732,3.402 15.5355,2.4644C14.5979,1.5267 13.3261,1 12,1C10.6739,1 9.4021,1.5267 8.4645,2.4644C7.5268,3.402 7,4.6739 7,6V8H6C5.47,8.0016 4.9623,8.2127 4.5875,8.5874C4.2128,8.9621 4.0016,9.47 4,10V20C4.0016,20.5299 4.2128,21.0379 4.5875,21.4126C4.9623,21.7873 5.47,21.9984 6,22H18C18.5299,21.9984 19.0377,21.7873 19.4125,21.4126C19.7872,21.0379 19.9984,20.5299 20,20V10C19.9984,9.47 19.7872,8.9621 19.4125,8.5874C19.0377,8.2127 18.5299,8.0016 18,8ZM9,6C9,5.2043 9.3161,4.4415 9.8787,3.8789C10.4413,3.3163 11.2044,3 12,3C12.7956,3 13.5587,3.3163 14.1213,3.8789C14.6839,4.4415 15,5.2043 15,6V8H9V6ZM18,20H6V10H18V20Z"
+ android:fillColor="#FF000000" />
+ <path
+ android:pathData="M12,17C13.1046,17 14,16.1046 14,15C14,13.8954 13.1046,13 12,13C10.8954,13 10,13.8954 10,15C10,16.1046 10.8954,17 12,17Z"
+ android:fillColor="#FF000000" />
+</vector>
diff --git a/packages/SystemUI/res/drawable/ic_device_lock_on.xml b/packages/SystemUI/res/drawable/ic_device_lock_on.xml
new file mode 100644
index 000000000000..5ae7090a2a69
--- /dev/null
+++ b/packages/SystemUI/res/drawable/ic_device_lock_on.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="24dp"
+ android:height="24dp"
+ android:viewportWidth="24"
+ android:viewportHeight="24">
+ <path
+ android:pathData="M18,8H17V6C17,4.6739 16.4732,3.402 15.5355,2.4644C14.5979,1.5267 13.3261,1 12,1C10.6739,1 9.4022,1.5267 8.4645,2.4644C7.5268,3.402 7,4.6739 7,6V8H6C5.47,8.0016 4.9623,8.2127 4.5875,8.5874C4.2128,8.9621 4.0016,9.47 4,10V20C4.0016,20.5299 4.2128,21.0379 4.5875,21.4126C4.9623,21.7873 5.47,21.9984 6,22H18C18.5299,21.9984 19.0377,21.7873 19.4125,21.4126C19.7872,21.0379 19.9984,20.5299 20,20V10C19.9984,9.47 19.7872,8.9621 19.4125,8.5874C19.0377,8.2127 18.5299,8.0016 18,8ZM12,17C11.6044,17 11.2178,16.8828 10.8889,16.6631C10.56,16.4433 10.3036,16.1306 10.1522,15.7651C10.0009,15.3997 9.9613,14.9978 10.0384,14.6099C10.1156,14.2219 10.3061,13.8656 10.5858,13.5859C10.8655,13.3062 11.2219,13.1157 11.6098,13.0386C11.9978,12.9614 12.3999,13.001 12.7654,13.1523C13.1308,13.3037 13.4432,13.5598 13.6629,13.8887C13.8827,14.2176 14,14.6044 14,15C13.9984,15.5299 13.7872,16.0379 13.4125,16.4126C13.0377,16.7873 12.5299,16.9984 12,17ZM15,8H9V6C9,5.2043 9.3161,4.4415 9.8787,3.8789C10.4413,3.3163 11.2044,3 12,3C12.7956,3 13.5587,3.3163 14.1213,3.8789C14.6839,4.4415 15,5.2043 15,6V8Z"
+ android:fillColor="#FF000000" />
+</vector>
diff --git a/packages/SystemUI/res/drawable/ic_device_microwave_off.xml b/packages/SystemUI/res/drawable/ic_device_microwave_off.xml
new file mode 100644
index 000000000000..771afbb72589
--- /dev/null
+++ b/packages/SystemUI/res/drawable/ic_device_microwave_off.xml
@@ -0,0 +1,37 @@
+<?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="24dp"
+ android:height="24dp"
+ android:viewportWidth="24"
+ android:viewportHeight="24">
+ <path
+ android:pathData="M20,4H4C3.4696,4 2.9609,4.2107 2.5858,4.5858C2.2107,4.9609 2,5.4696 2,6V18C2,18.5304 2.2107,19.0391 2.5858,19.4142C2.9609,19.7893 3.4696,20 4,20H20C20.5304,20 21.0391,19.7893 21.4142,19.4142C21.7893,19.0391 22,18.5304 22,18V6C22,5.4696 21.7893,4.9609 21.4142,4.5858C21.0391,4.2107 20.5304,4 20,4ZM20,18H4V6H20V18Z"
+ android:fillColor="#FF000000" />
+ <path
+ android:pathData="M18,9C18.5523,9 19,8.5523 19,8C19,7.4477 18.5523,7 18,7C17.4477,7 17,7.4477 17,8C17,8.5523 17.4477,9 18,9Z"
+ android:fillColor="#FF000000" />
+ <path
+ android:pathData="M18,13C18.5523,13 19,12.5523 19,12C19,11.4477 18.5523,11 18,11C17.4477,11 17,11.4477 17,12C17,12.5523 17.4477,13 18,13Z"
+ android:fillColor="#FF000000" />
+ <path
+ android:pathData="M18,17C18.5523,17 19,16.5523 19,16C19,15.4477 18.5523,15 18,15C17.4477,15 17,15.4477 17,16C17,16.5523 17.4477,17 18,17Z"
+ android:fillColor="#FF000000" />
+ <path
+ android:pathData="M15,7H5V17H15V7ZM13,15H7V9H13V15Z"
+ android:fillColor="#FF000000" />
+</vector>
diff --git a/packages/SystemUI/res/drawable/ic_device_microwave_on.xml b/packages/SystemUI/res/drawable/ic_device_microwave_on.xml
new file mode 100644
index 000000000000..b05f681398c9
--- /dev/null
+++ b/packages/SystemUI/res/drawable/ic_device_microwave_on.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="24dp"
+ android:height="24dp"
+ android:viewportWidth="24"
+ android:viewportHeight="24">
+ <path
+ android:pathData="M20,4H4C3.4696,4 2.9609,4.2107 2.5858,4.5858C2.2107,4.9609 2,5.4696 2,6V18C2,18.5304 2.2107,19.0391 2.5858,19.4142C2.9609,19.7893 3.4696,20 4,20H20C20.5304,20 21.0391,19.7893 21.4142,19.4142C21.7893,19.0391 22,18.5304 22,18V6C22,5.4696 21.7893,4.9609 21.4142,4.5858C21.0391,4.2107 20.5304,4 20,4ZM15,17H5V7H15V17ZM18,17C17.8022,17 17.6089,16.9413 17.4444,16.8314C17.28,16.7215 17.1518,16.5654 17.0761,16.3827C17.0004,16.2 16.9806,15.9989 17.0192,15.8049C17.0578,15.611 17.153,15.4327 17.2929,15.2928C17.4327,15.153 17.6109,15.0578 17.8049,15.0192C17.9989,14.9806 18.2,15.0005 18.3827,15.0762C18.5654,15.1519 18.7216,15.28 18.8315,15.4445C18.9414,15.6089 19,15.8022 19,16C19,16.2652 18.8946,16.5196 18.7071,16.7072C18.5196,16.8947 18.2652,17 18,17ZM18,13C17.8022,13 17.6089,12.9413 17.4444,12.8314C17.28,12.7215 17.1518,12.5654 17.0761,12.3827C17.0004,12.2 16.9806,11.9989 17.0192,11.8049C17.0578,11.611 17.153,11.4327 17.2929,11.2928C17.4327,11.153 17.6109,11.0578 17.8049,11.0192C17.9989,10.9806 18.2,11.0005 18.3827,11.0762C18.5654,11.1519 18.7216,11.28 18.8315,11.4445C18.9414,11.6089 19,11.8022 19,12C19,12.2652 18.8946,12.5196 18.7071,12.7072C18.5196,12.8947 18.2652,13 18,13ZM18,9C17.8022,9 17.6089,8.9413 17.4444,8.8314C17.28,8.7215 17.1518,8.5654 17.0761,8.3827C17.0004,8.2 16.9806,7.9989 17.0192,7.8049C17.0578,7.6109 17.153,7.4327 17.2929,7.2929C17.4327,7.153 17.6109,7.0578 17.8049,7.0192C17.9989,6.9806 18.2,7.0005 18.3827,7.0762C18.5654,7.1519 18.7216,7.28 18.8315,7.4445C18.9414,7.6089 19,7.8022 19,8C19,8.2652 18.8946,8.5196 18.7071,8.7072C18.5196,8.8947 18.2652,9 18,9Z"
+ android:fillColor="#FF000000" />
+</vector>
diff --git a/packages/SystemUI/res/drawable/ic_device_mop_off.xml b/packages/SystemUI/res/drawable/ic_device_mop_off.xml
new file mode 100644
index 000000000000..7fdaaea8b2a5
--- /dev/null
+++ b/packages/SystemUI/res/drawable/ic_device_mop_off.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="24dp"
+ android:height="24dp"
+ android:viewportWidth="24"
+ android:viewportHeight="24">
+ <path
+ android:pathData="M22.379,20.515L21,15V13C21,12.4696 20.7893,11.9609 20.4142,11.5858C20.0391,11.2107 19.5304,11 19,11H15V4C15,3.2043 14.6839,2.4413 14.1213,1.8787C13.5587,1.3161 12.7956,1 12,1C11.2043,1 10.4413,1.3161 9.8786,1.8787C9.316,2.4413 9,3.2043 9,4V11H5C4.4695,11 3.9608,11.2107 3.5858,11.5858C3.2107,11.9609 3,12.4696 3,13V15L1.621,20.515C1.5473,20.8099 1.5417,21.1178 1.6048,21.4151C1.6679,21.7125 1.798,21.9916 1.9851,22.2311C2.1722,22.4707 2.4115,22.6645 2.6847,22.7977C2.958,22.9309 3.258,23.0001 3.562,23H20.438C20.742,23.0001 21.042,22.9309 21.3152,22.7977C21.5884,22.6645 21.8277,22.4707 22.0149,22.2311C22.202,21.9916 22.332,21.7125 22.3951,21.4151C22.4582,21.1178 22.4527,20.8099 22.379,20.515ZM11,4C11,3.7348 11.1053,3.4804 11.2929,3.2929C11.4804,3.1054 11.7348,3 12,3C12.2652,3 12.5195,3.1054 12.7071,3.2929C12.8946,3.4804 13,3.7348 13,4V11H11V4ZM5,13H19V15H5V13ZM18,21V19C18,18.7348 17.8946,18.4804 17.7071,18.2929C17.5195,18.1054 17.2652,18 17,18C16.7348,18 16.4804,18.1054 16.2929,18.2929C16.1053,18.4804 16,18.7348 16,19V21H13V19C13,18.7348 12.8946,18.4804 12.7071,18.2929C12.5195,18.1054 12.2652,18 12,18C11.7348,18 11.4804,18.1054 11.2929,18.2929C11.1053,18.4804 11,18.7348 11,19V21H8V19C8,18.7348 7.8946,18.4804 7.7071,18.2929C7.5195,18.1054 7.2652,18 7,18C6.7348,18 6.4804,18.1054 6.2929,18.2929C6.1053,18.4804 6,18.7348 6,19V21H3.562L4.562,17H19.438L20.438,21H18Z"
+ android:fillColor="#FF000000" />
+</vector>
diff --git a/packages/SystemUI/res/drawable/ic_device_mop_on.xml b/packages/SystemUI/res/drawable/ic_device_mop_on.xml
new file mode 100644
index 000000000000..8350ca190737
--- /dev/null
+++ b/packages/SystemUI/res/drawable/ic_device_mop_on.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="24dp"
+ android:height="24dp"
+ android:viewportWidth="24"
+ android:viewportHeight="24">
+ <path
+ android:pathData="M22.379,20.515L21,15V13C21,12.4696 20.7893,11.9609 20.4142,11.5858C20.0391,11.2107 19.5304,11 19,11H15V4C15,3.2043 14.6839,2.4413 14.1213,1.8787C13.5587,1.3161 12.7956,1 12,1C11.2043,1 10.4413,1.3161 9.8787,1.8787C9.316,2.4413 9,3.2043 9,4V11H5C4.4695,11 3.9608,11.2107 3.5858,11.5858C3.2107,11.9609 3,12.4696 3,13V15L1.621,20.515C1.5473,20.8099 1.5417,21.1178 1.6048,21.4151C1.6679,21.7125 1.798,21.9916 1.9851,22.2311C2.1722,22.4707 2.4115,22.6645 2.6847,22.7977C2.958,22.9309 3.258,23.0001 3.562,23H20.438C20.742,23.0001 21.042,22.9309 21.3152,22.7977C21.5885,22.6645 21.8277,22.4707 22.0148,22.2311C22.202,21.9916 22.332,21.7125 22.3951,21.4151C22.4582,21.1178 22.4527,20.8099 22.379,20.515ZM18,21V19C18,18.7348 17.8946,18.4804 17.7071,18.2929C17.5195,18.1054 17.2652,18 17,18C16.7348,18 16.4804,18.1054 16.2929,18.2929C16.1053,18.4804 16,18.7348 16,19V21H13V19C13,18.7348 12.8946,18.4804 12.7071,18.2929C12.5195,18.1054 12.2652,18 12,18C11.7348,18 11.4804,18.1054 11.2929,18.2929C11.1053,18.4804 11,18.7348 11,19V21H8V19C8,18.7348 7.8946,18.4804 7.7071,18.2929C7.5195,18.1054 7.2652,18 7,18C6.7348,18 6.4804,18.1054 6.2929,18.2929C6.1053,18.4804 6,18.7348 6,19V21H3.562L4.562,17H19.438L20.438,21H18Z"
+ android:fillColor="#FF000000" />
+</vector>
diff --git a/packages/SystemUI/res/drawable/ic_device_multicooker_off.xml b/packages/SystemUI/res/drawable/ic_device_multicooker_off.xml
new file mode 100644
index 000000000000..8a79b0d553ef
--- /dev/null
+++ b/packages/SystemUI/res/drawable/ic_device_multicooker_off.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
+ -->
+<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,5H16V4C16,3.4696 15.7893,2.9609 15.4142,2.5858C15.0391,2.2107 14.5304,2 14,2H10C9.4696,2 8.9609,2.2107 8.5858,2.5858C8.2107,2.9609 8,3.4696 8,4V5H5C4.4696,5 3.9609,5.2107 3.5858,5.5858C3.2107,5.9609 3,6.4696 3,7V19C3,19.5304 3.2107,20.0391 3.5858,20.4142C3.9609,20.7893 4.4696,21 5,21H19C19.5304,21 20.0391,20.7893 20.4142,20.4142C20.7893,20.0391 21,19.5304 21,19V7C21,6.4696 20.7893,5.9609 20.4142,5.5858C20.0391,5.2107 19.5304,5 19,5ZM10,4H14V5H10V4ZM19,19H5V10H7V12C7,12.5304 7.2107,13.0391 7.5858,13.4142C7.9609,13.7893 8.4696,14 9,14H15C15.5304,14 16.0391,13.7893 16.4142,13.4142C16.7893,13.0391 17,12.5304 17,12V10H19V19ZM9,12V10H15V12H9ZM5,8V7H19V8H5Z"
+ android:fillColor="#FF000000" />
+ <path
+ android:pathData="M16,18C16.5523,18 17,17.5523 17,17C17,16.4477 16.5523,16 16,16C15.4477,16 15,16.4477 15,17C15,17.5523 15.4477,18 16,18Z"
+ android:fillColor="#FF000000" />
+ <path
+ android:pathData="M12,18C12.5523,18 13,17.5523 13,17C13,16.4477 12.5523,16 12,16C11.4477,16 11,16.4477 11,17C11,17.5523 11.4477,18 12,18Z"
+ android:fillColor="#FF000000" />
+ <path
+ android:pathData="M8,18C8.5523,18 9,17.5523 9,17C9,16.4477 8.5523,16 8,16C7.4477,16 7,16.4477 7,17C7,17.5523 7.4477,18 8,18Z"
+ android:fillColor="#FF000000" />
+</vector>
diff --git a/packages/SystemUI/res/drawable/ic_device_multicooker_on.xml b/packages/SystemUI/res/drawable/ic_device_multicooker_on.xml
new file mode 100644
index 000000000000..90ede523b11a
--- /dev/null
+++ b/packages/SystemUI/res/drawable/ic_device_multicooker_on.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
+ -->
+<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="M17,12C17,12.5304 16.7893,13.0391 16.4142,13.4142C16.0391,13.7893 15.5304,14 15,14H9C8.4696,14 7.9609,13.7893 7.5858,13.4142C7.2107,13.0391 7,12.5304 7,12V10H3V19C3,19.5304 3.2107,20.0391 3.5858,20.4142C3.9609,20.7893 4.4696,21 5,21H19C19.5304,21 20.0391,20.7893 20.4142,20.4142C20.7893,20.0391 21,19.5304 21,19V10H17V12ZM8,18C7.8022,18 7.6089,17.9413 7.4444,17.8314C7.28,17.7215 7.1518,17.5654 7.0761,17.3827C7.0004,17.2 6.9806,16.9989 7.0192,16.8049C7.0578,16.611 7.153,16.4327 7.2929,16.2928C7.4328,16.153 7.6109,16.0578 7.8049,16.0192C7.9989,15.9806 8.2,16.0005 8.3827,16.0762C8.5654,16.1519 8.7216,16.28 8.8315,16.4445C8.9413,16.6089 9,16.8022 9,17C9,17.2652 8.8946,17.5196 8.7071,17.7072C8.5196,17.8947 8.2652,18 8,18ZM12,18C11.8022,18 11.6089,17.9413 11.4444,17.8314C11.28,17.7215 11.1518,17.5654 11.0761,17.3827C11.0004,17.2 10.9806,16.9989 11.0192,16.8049C11.0578,16.611 11.153,16.4327 11.2929,16.2928C11.4327,16.153 11.6109,16.0578 11.8049,16.0192C11.9989,15.9806 12.2,16.0005 12.3827,16.0762C12.5654,16.1519 12.7216,16.28 12.8315,16.4445C12.9414,16.6089 13,16.8022 13,17C13,17.2652 12.8946,17.5196 12.7071,17.7072C12.5196,17.8947 12.2652,18 12,18ZM16,18C15.8022,18 15.6089,17.9413 15.4444,17.8314C15.28,17.7215 15.1518,17.5654 15.0761,17.3827C15.0004,17.2 14.9806,16.9989 15.0192,16.8049C15.0578,16.611 15.153,16.4327 15.2929,16.2928C15.4327,16.153 15.6109,16.0578 15.8049,16.0192C15.9989,15.9806 16.2,16.0005 16.3827,16.0762C16.5654,16.1519 16.7216,16.28 16.8315,16.4445C16.9414,16.6089 17,16.8022 17,17C17,17.2652 16.8946,17.5196 16.7071,17.7072C16.5196,17.8947 16.2652,18 16,18Z"
+ android:fillColor="#FF000000" />
+ <path
+ android:pathData="M15,10H9V12H15V10Z"
+ android:fillColor="#FF000000" />
+ <path
+ android:pathData="M21,8V7C21,6.4696 20.7893,5.9609 20.4142,5.5858C20.0391,5.2107 19.5304,5 19,5H16V4C16,3.4696 15.7893,2.9609 15.4142,2.5858C15.0391,2.2107 14.5304,2 14,2H10C9.4696,2 8.9609,2.2107 8.5858,2.5858C8.2107,2.9609 8,3.4696 8,4V5H5C4.4696,5 3.9609,5.2107 3.5858,5.5858C3.2107,5.9609 3,6.4696 3,7V8H21ZM10,4H14V5H10V4Z"
+ android:fillColor="#FF000000" />
+</vector>
diff --git a/packages/SystemUI/res/drawable/ic_device_outlet_off.xml b/packages/SystemUI/res/drawable/ic_device_outlet_off.xml
new file mode 100644
index 000000000000..6fe7d120af47
--- /dev/null
+++ b/packages/SystemUI/res/drawable/ic_device_outlet_off.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
+ -->
+<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="M12,2C10.0222,2 8.0888,2.5865 6.4443,3.6853C4.7998,4.7841 3.5181,6.346 2.7612,8.1732C2.0043,10.0005 1.8063,12.0111 2.1922,13.9509C2.578,15.8907 3.5304,17.6725 4.9289,19.071C6.3275,20.4696 8.1093,21.422 10.0491,21.8079C11.9889,22.1937 13.9996,21.9956 15.8268,21.2388C17.6541,20.4819 19.2159,19.2002 20.3147,17.5557C21.4135,15.9112 22,13.9778 22,12C22,9.3478 20.9464,6.8043 19.0711,4.929C17.1957,3.0536 14.6522,2 12,2ZM12,20C10.4178,20 8.871,19.5308 7.5554,18.6517C6.2399,17.7727 5.2145,16.5233 4.609,15.0615C4.0035,13.5997 3.845,11.9912 4.1537,10.4393C4.4624,8.8875 5.2243,7.462 6.3432,6.3431C7.462,5.2243 8.8874,4.4624 10.4393,4.1537C11.9911,3.845 13.5997,4.0035 15.0615,4.609C16.5233,5.2145 17.7727,6.2398 18.6518,7.5554C19.5308,8.871 20,10.4177 20,12C20,14.1217 19.1572,16.1566 17.6569,17.6569C16.1566,19.1572 14.1217,20 12,20Z"
+ android:fillColor="#FF000000" />
+ <path
+ android:pathData="M9,9H7V13H9V9Z"
+ android:fillColor="#FF000000" />
+ <path
+ android:pathData="M12,15C11.7348,15 11.4804,15.1053 11.2929,15.2928C11.1054,15.4804 11,15.7348 11,16V17H13V16C13,15.7348 12.8946,15.4804 12.7071,15.2928C12.5196,15.1053 12.2652,15 12,15Z"
+ android:fillColor="#FF000000" />
+ <path
+ android:pathData="M17,9H15V13H17V9Z"
+ android:fillColor="#FF000000" />
+</vector>
diff --git a/packages/SystemUI/res/drawable/ic_device_outlet_on.xml b/packages/SystemUI/res/drawable/ic_device_outlet_on.xml
new file mode 100644
index 000000000000..e9d80cf04483
--- /dev/null
+++ b/packages/SystemUI/res/drawable/ic_device_outlet_on.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="24dp"
+ android:height="24dp"
+ android:viewportWidth="24"
+ android:viewportHeight="24">
+ <path
+ android:pathData="M12,2C10.0222,2 8.0888,2.5865 6.4443,3.6853C4.7998,4.7841 3.5181,6.346 2.7612,8.1732C2.0043,10.0005 1.8063,12.0111 2.1922,13.9509C2.578,15.8907 3.5304,17.6725 4.9289,19.071C6.3275,20.4696 8.1093,21.422 10.0491,21.8079C11.9889,22.1937 13.9996,21.9956 15.8268,21.2388C17.6541,20.4819 19.2159,19.2002 20.3147,17.5557C21.4135,15.9112 22,13.9778 22,12C22,9.3478 20.9464,6.8043 19.0711,4.929C17.1957,3.0536 14.6522,2 12,2ZM9,13H7V9H9V13ZM13,17H11V16C11,15.7348 11.1054,15.4804 11.2929,15.2928C11.4804,15.1053 11.7348,15 12,15C12.2652,15 12.5196,15.1053 12.7071,15.2928C12.8946,15.4804 13,15.7348 13,16V17ZM17,13H15V9H17V13Z"
+ android:fillColor="#FF000000" />
+</vector>
diff --git a/packages/SystemUI/res/drawable/ic_device_pergola_off.xml b/packages/SystemUI/res/drawable/ic_device_pergola_off.xml
new file mode 100644
index 000000000000..b7113dcd042f
--- /dev/null
+++ b/packages/SystemUI/res/drawable/ic_device_pergola_off.xml
@@ -0,0 +1,28 @@
+<?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="24dp"
+ android:height="24dp"
+ android:viewportWidth="24"
+ android:viewportHeight="24">
+ <path
+ android:pathData="M20,2C19.7348,2 19.4804,2.1054 19.2929,2.293C19.1054,2.4805 19,2.7348 19,3V4H5V3C5,2.7348 4.8946,2.4805 4.7071,2.293C4.5196,2.1054 4.2652,2 4,2C3.7348,2 3.4804,2.1054 3.2929,2.293C3.1054,2.4805 3,2.7348 3,3V21H5V10H19V21H21V3C21,2.7348 20.8946,2.4805 20.7071,2.293C20.5196,2.1054 20.2652,2 20,2ZM5,8V6H19V8H5Z"
+ android:fillColor="#FF000000" />
+ <path
+ android:pathData="M8,18H11V21H13V18H16V16H8V18Z"
+ android:fillColor="#FF000000" />
+</vector>
diff --git a/packages/SystemUI/res/drawable/ic_device_pergola_on.xml b/packages/SystemUI/res/drawable/ic_device_pergola_on.xml
new file mode 100644
index 000000000000..b7113dcd042f
--- /dev/null
+++ b/packages/SystemUI/res/drawable/ic_device_pergola_on.xml
@@ -0,0 +1,28 @@
+<?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="24dp"
+ android:height="24dp"
+ android:viewportWidth="24"
+ android:viewportHeight="24">
+ <path
+ android:pathData="M20,2C19.7348,2 19.4804,2.1054 19.2929,2.293C19.1054,2.4805 19,2.7348 19,3V4H5V3C5,2.7348 4.8946,2.4805 4.7071,2.293C4.5196,2.1054 4.2652,2 4,2C3.7348,2 3.4804,2.1054 3.2929,2.293C3.1054,2.4805 3,2.7348 3,3V21H5V10H19V21H21V3C21,2.7348 20.8946,2.4805 20.7071,2.293C20.5196,2.1054 20.2652,2 20,2ZM5,8V6H19V8H5Z"
+ android:fillColor="#FF000000" />
+ <path
+ android:pathData="M8,18H11V21H13V18H16V16H8V18Z"
+ android:fillColor="#FF000000" />
+</vector>
diff --git a/packages/SystemUI/res/drawable/ic_device_refrigerator_off.xml b/packages/SystemUI/res/drawable/ic_device_refrigerator_off.xml
new file mode 100644
index 000000000000..33ad44c9f253
--- /dev/null
+++ b/packages/SystemUI/res/drawable/ic_device_refrigerator_off.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="24dp"
+ android:height="24dp"
+ android:viewportWidth="24"
+ android:viewportHeight="24">
+ <path
+ android:pathData="M18,2.01L6,2C5.4696,2 4.9609,2.2107 4.5858,2.5858C4.2107,2.9609 4,3.4696 4,4V20C4.0016,20.5299 4.2128,21.0377 4.5875,21.4125C4.9623,21.7872 5.47,21.9984 6,22H18C18.5299,21.9984 19.0377,21.7872 19.4125,21.4125C19.7872,21.0377 19.9984,20.5299 20,20V4C19.9999,3.7379 19.948,3.4784 19.8473,3.2363C19.7466,2.9943 19.5991,2.7745 19.4133,2.5896C19.2275,2.4047 19.007,2.2583 18.7645,2.1588C18.5219,2.0594 18.2621,2.0088 18,2.01ZM18,20H6V10.98H18V20ZM18,9H6V4H18V9ZM8,5H10V8H8V5ZM8,12H10V17H8V12Z"
+ android:fillColor="#FF000000" />
+</vector>
diff --git a/packages/SystemUI/res/drawable/ic_device_refrigerator_on.xml b/packages/SystemUI/res/drawable/ic_device_refrigerator_on.xml
new file mode 100644
index 000000000000..fe7a4b6a6c61
--- /dev/null
+++ b/packages/SystemUI/res/drawable/ic_device_refrigerator_on.xml
@@ -0,0 +1,28 @@
+<?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="24dp"
+ android:height="24dp"
+ android:viewportWidth="24"
+ android:viewportHeight="24">
+ <path
+ android:pathData="M20,9V4C20,3.4696 19.7893,2.9609 19.4142,2.5858C19.0391,2.2107 18.5304,2 18,2H6C5.4696,2 4.9609,2.2107 4.5858,2.5858C4.2107,2.9609 4,3.4696 4,4V9H20ZM8,5H10V8H8V5Z"
+ android:fillColor="#FF000000" />
+ <path
+ android:pathData="M4,11V20C4,20.5304 4.2107,21.0391 4.5858,21.4142C4.9609,21.7893 5.4696,22 6,22H18C18.5304,22 19.0391,21.7893 19.4142,21.4142C19.7893,21.0391 20,20.5304 20,20V11H4ZM10,17H8V12H10V17Z"
+ android:fillColor="#FF000000" />
+</vector>
diff --git a/packages/SystemUI/res/drawable/ic_device_remote_control_off.xml b/packages/SystemUI/res/drawable/ic_device_remote_control_off.xml
new file mode 100644
index 000000000000..761f6430c88e
--- /dev/null
+++ b/packages/SystemUI/res/drawable/ic_device_remote_control_off.xml
@@ -0,0 +1,46 @@
+<?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="24dp"
+ android:height="24dp"
+ android:viewportWidth="24"
+ android:viewportHeight="24">
+ <path
+ android:pathData="M16,1H8C7.4696,1 6.9609,1.2107 6.5858,1.5858C6.2107,1.9609 6,2.4696 6,3V21C6,21.5304 6.2107,22.0391 6.5858,22.4142C6.9609,22.7893 7.4696,23 8,23H16C16.5304,23 17.0391,22.7893 17.4142,22.4142C17.7893,22.0391 18,21.5304 18,21V3C18,2.4696 17.7893,1.9609 17.4142,1.5858C17.0391,1.2107 16.5304,1 16,1ZM16,21H8V3H16V21Z"
+ android:fillColor="#FF000000" />
+ <path
+ android:pathData="M12,10C12.5933,10 13.1734,9.824 13.6667,9.4944C14.1601,9.1648 14.5446,8.6963 14.7716,8.1481C14.9987,7.5999 15.0581,6.9966 14.9424,6.4147C14.8266,5.8327 14.5409,5.2982 14.1213,4.8787C13.7018,4.4591 13.1672,4.1734 12.5853,4.0576C12.0033,3.9419 11.4001,4.0013 10.8519,4.2284C10.3038,4.4555 9.8352,4.8399 9.5056,5.3333C9.1759,5.8266 9,6.4067 9,7C9,7.7957 9.3161,8.5587 9.8787,9.1214C10.4413,9.684 11.2044,10 12,10ZM12,6C12.1978,6 12.3911,6.0587 12.5556,6.1686C12.72,6.2785 12.8482,6.4346 12.9239,6.6173C12.9996,6.8 13.0194,7.0011 12.9808,7.1951C12.9422,7.3891 12.847,7.5673 12.7071,7.7072C12.5673,7.847 12.3891,7.9423 12.1951,7.9809C12.0011,8.0194 11.8,7.9995 11.6173,7.9238C11.4346,7.8481 11.2784,7.72 11.1685,7.5556C11.0587,7.3911 11,7.1978 11,7C11,6.7348 11.1054,6.4804 11.2929,6.2929C11.4804,6.1053 11.7348,6 12,6Z"
+ android:fillColor="#FF000000" />
+ <path
+ android:pathData="M10,14C10.5523,14 11,13.5523 11,13C11,12.4477 10.5523,12 10,12C9.4477,12 9,12.4477 9,13C9,13.5523 9.4477,14 10,14Z"
+ android:fillColor="#FF000000" />
+ <path
+ android:pathData="M14,14C14.5523,14 15,13.5523 15,13C15,12.4477 14.5523,12 14,12C13.4477,12 13,12.4477 13,13C13,13.5523 13.4477,14 14,14Z"
+ android:fillColor="#FF000000" />
+ <path
+ android:pathData="M10,17C10.5523,17 11,16.5523 11,16C11,15.4477 10.5523,15 10,15C9.4477,15 9,15.4477 9,16C9,16.5523 9.4477,17 10,17Z"
+ android:fillColor="#FF000000" />
+ <path
+ android:pathData="M14,17C14.5523,17 15,16.5523 15,16C15,15.4477 14.5523,15 14,15C13.4477,15 13,15.4477 13,16C13,16.5523 13.4477,17 14,17Z"
+ android:fillColor="#FF000000" />
+ <path
+ android:pathData="M10,20C10.5523,20 11,19.5523 11,19C11,18.4477 10.5523,18 10,18C9.4477,18 9,18.4477 9,19C9,19.5523 9.4477,20 10,20Z"
+ android:fillColor="#FF000000" />
+ <path
+ android:pathData="M14,20C14.5523,20 15,19.5523 15,19C15,18.4477 14.5523,18 14,18C13.4477,18 13,18.4477 13,19C13,19.5523 13.4477,20 14,20Z"
+ android:fillColor="#FF000000" />
+</vector>
diff --git a/packages/SystemUI/res/drawable/ic_device_remote_control_on.xml b/packages/SystemUI/res/drawable/ic_device_remote_control_on.xml
new file mode 100644
index 000000000000..b2c55a6e8eff
--- /dev/null
+++ b/packages/SystemUI/res/drawable/ic_device_remote_control_on.xml
@@ -0,0 +1,28 @@
+<?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="24dp"
+ android:height="24dp"
+ android:viewportWidth="24"
+ android:viewportHeight="24">
+ <path
+ android:pathData="M12,8C12.5523,8 13,7.5523 13,7C13,6.4477 12.5523,6 12,6C11.4477,6 11,6.4477 11,7C11,7.5523 11.4477,8 12,8Z"
+ android:fillColor="#FF000000" />
+ <path
+ android:pathData="M16,1H8C7.4696,1 6.9609,1.2107 6.5858,1.5858C6.2107,1.9609 6,2.4696 6,3V21C6,21.5304 6.2107,22.0391 6.5858,22.4142C6.9609,22.7893 7.4696,23 8,23H16C16.5304,23 17.0391,22.7893 17.4142,22.4142C17.7893,22.0391 18,21.5304 18,21V3C18,2.4696 17.7893,1.9609 17.4142,1.5858C17.0391,1.2107 16.5304,1 16,1ZM10,20C9.8022,20 9.6089,19.9413 9.4444,19.8314C9.28,19.7215 9.1518,19.5654 9.0761,19.3827C9.0004,19.2 8.9806,18.9989 9.0192,18.8049C9.0578,18.611 9.153,18.4327 9.2929,18.2928C9.4327,18.153 9.6109,18.0578 9.8049,18.0192C9.9989,17.9806 10.2,18.0005 10.3827,18.0762C10.5654,18.1519 10.7216,18.28 10.8315,18.4445C10.9414,18.6089 11,18.8022 11,19C11,19.2652 10.8946,19.5196 10.7071,19.7072C10.5196,19.8947 10.2652,20 10,20ZM10,17C9.8022,17 9.6089,16.9413 9.4444,16.8314C9.28,16.7215 9.1518,16.5654 9.0761,16.3827C9.0004,16.2 8.9806,15.9989 9.0192,15.8049C9.0578,15.611 9.153,15.4327 9.2929,15.2928C9.4327,15.153 9.6109,15.0578 9.8049,15.0192C9.9989,14.9806 10.2,15.0005 10.3827,15.0762C10.5654,15.1519 10.7216,15.28 10.8315,15.4445C10.9414,15.6089 11,15.8022 11,16C11,16.2652 10.8946,16.5196 10.7071,16.7072C10.5196,16.8947 10.2652,17 10,17ZM10,14C9.8022,14 9.6089,13.9413 9.4444,13.8314C9.28,13.7215 9.1518,13.5654 9.0761,13.3827C9.0004,13.2 8.9806,12.9989 9.0192,12.8049C9.0578,12.611 9.153,12.4327 9.2929,12.2928C9.4327,12.153 9.6109,12.0578 9.8049,12.0192C9.9989,11.9806 10.2,12.0005 10.3827,12.0762C10.5654,12.1519 10.7216,12.28 10.8315,12.4445C10.9414,12.6089 11,12.8022 11,13C11,13.2652 10.8946,13.5196 10.7071,13.7072C10.5196,13.8947 10.2652,14 10,14ZM14,20C13.8022,20 13.6089,19.9413 13.4444,19.8314C13.28,19.7215 13.1518,19.5654 13.0761,19.3827C13.0004,19.2 12.9806,18.9989 13.0192,18.8049C13.0578,18.611 13.153,18.4327 13.2929,18.2928C13.4327,18.153 13.6109,18.0578 13.8049,18.0192C13.9989,17.9806 14.2,18.0005 14.3827,18.0762C14.5654,18.1519 14.7216,18.28 14.8315,18.4445C14.9414,18.6089 15,18.8022 15,19C15,19.2652 14.8946,19.5196 14.7071,19.7072C14.5196,19.8947 14.2652,20 14,20ZM14,17C13.8022,17 13.6089,16.9413 13.4444,16.8314C13.28,16.7215 13.1518,16.5654 13.0761,16.3827C13.0004,16.2 12.9806,15.9989 13.0192,15.8049C13.0578,15.611 13.153,15.4327 13.2929,15.2928C13.4327,15.153 13.6109,15.0578 13.8049,15.0192C13.9989,14.9806 14.2,15.0005 14.3827,15.0762C14.5654,15.1519 14.7216,15.28 14.8315,15.4445C14.9414,15.6089 15,15.8022 15,16C15,16.2652 14.8946,16.5196 14.7071,16.7072C14.5196,16.8947 14.2652,17 14,17ZM14,14C13.8022,14 13.6089,13.9413 13.4444,13.8314C13.28,13.7215 13.1518,13.5654 13.0761,13.3827C13.0004,13.2 12.9806,12.9989 13.0192,12.8049C13.0578,12.611 13.153,12.4327 13.2929,12.2928C13.4327,12.153 13.6109,12.0578 13.8049,12.0192C13.9989,11.9806 14.2,12.0005 14.3827,12.0762C14.5654,12.1519 14.7216,12.28 14.8315,12.4445C14.9414,12.6089 15,12.8022 15,13C15,13.2652 14.8946,13.5196 14.7071,13.7072C14.5196,13.8947 14.2652,14 14,14ZM12,10C11.4067,10 10.8266,9.824 10.3333,9.4944C9.8399,9.1647 9.4554,8.6962 9.2284,8.1481C9.0013,7.5999 8.9419,6.9966 9.0576,6.4147C9.1734,5.8327 9.4591,5.2982 9.8787,4.8787C10.2982,4.4591 10.8328,4.1734 11.4147,4.0576C11.9967,3.9419 12.5999,4.0013 13.1481,4.2284C13.6962,4.4555 14.1648,4.8399 14.4944,5.3333C14.8241,5.8266 15,6.4067 15,7C15,7.7957 14.6839,8.5587 14.1213,9.1213C13.5587,9.684 12.7956,10 12,10Z"
+ android:fillColor="#FF000000" />
+</vector>
diff --git a/packages/SystemUI/res/drawable/ic_device_security_system_off.xml b/packages/SystemUI/res/drawable/ic_device_security_system_off.xml
new file mode 100644
index 000000000000..7a987b215b0a
--- /dev/null
+++ b/packages/SystemUI/res/drawable/ic_device_security_system_off.xml
@@ -0,0 +1,28 @@
+<?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="24dp"
+ android:height="24dp"
+ android:viewportWidth="24"
+ android:viewportHeight="24">
+ <path
+ android:pathData="M12,2L4,5V11.0911C4,16.1361 7.413,20.854 12,22C16.587,20.854 20,16.1361 20,11.0911V5L12,2ZM18,11.0911C18.0051,12.9956 17.4351,14.8572 16.3645,16.4324C15.294,18.0075 13.7727,19.2227 12,19.9189C10.2273,19.2227 8.706,18.0075 7.6355,16.4324C6.5649,14.8572 5.9949,12.9956 6,11.0911V6.386L12,4.136L18,6.386V11.0911Z"
+ android:fillColor="#FF000000" />
+ <path
+ android:pathData="M8.464,10.939L7.05,12.353L10.586,15.8879L16.949,9.5249L15.535,8.1111L10.586,13.0601L8.464,10.939Z"
+ android:fillColor="#FF000000" />
+</vector>
diff --git a/packages/SystemUI/res/drawable/ic_device_security_system_on.xml b/packages/SystemUI/res/drawable/ic_device_security_system_on.xml
new file mode 100644
index 000000000000..f23106808826
--- /dev/null
+++ b/packages/SystemUI/res/drawable/ic_device_security_system_on.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="24dp"
+ android:height="24dp"
+ android:viewportWidth="24"
+ android:viewportHeight="24">
+ <path
+ android:pathData="M12,2L4,5V11.0911C4,16.1361 7.413,20.854 12,22C16.587,20.854 20,16.1361 20,11.0911V5L12,2ZM10.586,15.8889L7.05,12.354L8.464,10.9399L10.586,13.061L15.536,8.1111L16.95,9.5249L10.586,15.8889Z"
+ android:fillColor="#FF000000" />
+</vector>
diff --git a/packages/SystemUI/res/drawable/ic_device_set_top_off.xml b/packages/SystemUI/res/drawable/ic_device_set_top_off.xml
new file mode 100644
index 000000000000..7c9d9cef5df4
--- /dev/null
+++ b/packages/SystemUI/res/drawable/ic_device_set_top_off.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
+ -->
+<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="M2,7V17H22V7H2ZM20,15H4V9H20V15Z"
+ android:fillColor="#FF000000" />
+ <path
+ android:pathData="M11,11H5V13H11V11Z"
+ android:fillColor="#FF000000" />
+ <path
+ android:pathData="M14,13C14.5523,13 15,12.5523 15,12C15,11.4477 14.5523,11 14,11C13.4477,11 13,11.4477 13,12C13,12.5523 13.4477,13 14,13Z"
+ android:fillColor="#FF000000" />
+ <path
+ android:pathData="M17,13C17.5523,13 18,12.5523 18,12C18,11.4477 17.5523,11 17,11C16.4477,11 16,11.4477 16,12C16,12.5523 16.4477,13 17,13Z"
+ android:fillColor="#FF000000" />
+</vector>
diff --git a/packages/SystemUI/res/drawable/ic_device_set_top_on.xml b/packages/SystemUI/res/drawable/ic_device_set_top_on.xml
new file mode 100644
index 000000000000..c8727941f5d7
--- /dev/null
+++ b/packages/SystemUI/res/drawable/ic_device_set_top_on.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="24dp"
+ android:height="24dp"
+ android:viewportWidth="24"
+ android:viewportHeight="24">
+ <path
+ android:pathData="M2,7V17H22V7H2ZM11,13H5V11H11V13ZM14,13C13.8022,13 13.6089,12.9414 13.4444,12.8315C13.28,12.7217 13.1518,12.5653 13.0761,12.3826C13.0004,12.1998 12.9806,11.9989 13.0192,11.8049C13.0578,11.611 13.153,11.4328 13.2929,11.293C13.4327,11.1531 13.6109,11.0579 13.8049,11.0193C13.9989,10.9807 14.2,11.0005 14.3827,11.0762C14.5654,11.1519 14.7216,11.2799 14.8315,11.4443C14.9414,11.6088 15,11.8022 15,12C15,12.2652 14.8946,12.5195 14.7071,12.707C14.5196,12.8946 14.2652,13 14,13ZM17,13C16.8022,13 16.6089,12.9414 16.4444,12.8315C16.28,12.7217 16.1518,12.5653 16.0761,12.3826C16.0004,12.1998 15.9806,11.9989 16.0192,11.8049C16.0578,11.611 16.153,11.4328 16.2929,11.293C16.4327,11.1531 16.6109,11.0579 16.8049,11.0193C16.9989,10.9807 17.2,11.0005 17.3827,11.0762C17.5654,11.1519 17.7216,11.2799 17.8315,11.4443C17.9414,11.6088 18,11.8022 18,12C18,12.2652 17.8946,12.5195 17.7071,12.707C17.5196,12.8946 17.2652,13 17,13Z"
+ android:fillColor="#FF000000" />
+</vector>
diff --git a/packages/SystemUI/res/drawable/ic_device_sprinkler_off.xml b/packages/SystemUI/res/drawable/ic_device_sprinkler_off.xml
new file mode 100644
index 000000000000..fb6e34eee86e
--- /dev/null
+++ b/packages/SystemUI/res/drawable/ic_device_sprinkler_off.xml
@@ -0,0 +1,52 @@
+<?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="24dp"
+ android:height="24dp"
+ android:viewportWidth="24"
+ android:viewportHeight="24">
+ <path
+ android:pathData="M7.5,18H11V21H13V18H16.5V16H7.5V18Z"
+ android:fillColor="#FF000000" />
+ <path
+ android:pathData="M12,13C12.5523,13 13,12.5523 13,12C13,11.4477 12.5523,11 12,11C11.4477,11 11,11.4477 11,12C11,12.5523 11.4477,13 12,13Z"
+ android:fillColor="#FF000000" />
+ <path
+ android:pathData="M12,9C12.5523,9 13,8.5523 13,8C13,7.4477 12.5523,7 12,7C11.4477,7 11,7.4477 11,8C11,8.5523 11.4477,9 12,9Z"
+ android:fillColor="#FF000000" />
+ <path
+ android:pathData="M12,5C12.5523,5 13,4.5523 13,4C13,3.4477 12.5523,3 12,3C11.4477,3 11,3.4477 11,4C11,4.5523 11.4477,5 12,5Z"
+ android:fillColor="#FF000000" />
+ <path
+ android:pathData="M15.707,14.707C15.8469,14.5672 15.9421,14.3891 15.9808,14.1951C16.0194,14.0011 15.9996,13.7999 15.9239,13.6172C15.8482,13.4344 15.7201,13.2784 15.5556,13.1685C15.3911,13.0586 15.1978,12.9998 15,12.9998C14.8022,12.9998 14.6088,13.0586 14.4444,13.1685C14.2799,13.2784 14.1518,13.4344 14.0761,13.6172C14.0004,13.7999 13.9806,14.0011 14.0192,14.1951C14.0578,14.3891 14.1531,14.5672 14.293,14.707C14.4805,14.8945 14.7348,14.9998 15,14.9998C15.2652,14.9998 15.5195,14.8945 15.707,14.707Z"
+ android:fillColor="#FF000000" />
+ <path
+ android:pathData="M17.121,10.4641C16.9812,10.604 16.8861,10.7821 16.8476,10.9761C16.8091,11.17 16.829,11.371 16.9047,11.5537C16.9804,11.7364 17.1086,11.8924 17.273,12.0022C17.4375,12.112 17.6308,12.1707 17.8285,12.1707C18.0262,12.1707 18.2195,12.112 18.3839,12.0022C18.5484,11.8924 18.6765,11.7364 18.7523,11.5537C18.828,11.371 18.8479,11.17 18.8094,10.9761C18.7709,10.7821 18.6757,10.604 18.536,10.4641C18.4431,10.3711 18.3328,10.2972 18.2114,10.2468C18.09,10.1965 17.9599,10.1707 17.8285,10.1707C17.6971,10.1707 17.5669,10.1965 17.4455,10.2468C17.3241,10.2972 17.2139,10.3711 17.121,10.4641Z"
+ android:fillColor="#FF000000" />
+ <path
+ android:pathData="M21.364,7.6359C21.2242,7.496 21.046,7.4009 20.852,7.3622C20.658,7.3236 20.4569,7.3435 20.2742,7.4191C20.0914,7.4948 19.9352,7.6228 19.8253,7.7873C19.7155,7.9517 19.6568,8.1452 19.6568,8.343C19.6568,8.5407 19.7155,8.7342 19.8253,8.8986C19.9352,9.0631 20.0914,9.1911 20.2742,9.2668C20.4569,9.3425 20.658,9.3623 20.852,9.3237C21.046,9.2851 21.2242,9.1899 21.364,9.05C21.5515,8.8625 21.6568,8.6081 21.6568,8.343C21.6568,8.0778 21.5515,7.8235 21.364,7.6359Z"
+ android:fillColor="#FF000000" />
+ <path
+ android:pathData="M9.707,14.707C9.8469,14.5672 9.9421,14.3891 9.9808,14.1951C10.0194,14.0011 9.9996,13.7999 9.9239,13.6172C9.8482,13.4344 9.72,13.2784 9.5556,13.1685C9.3911,13.0586 9.1978,12.9998 9,12.9998C8.8022,12.9998 8.6088,13.0586 8.4444,13.1685C8.2799,13.2784 8.1518,13.4344 8.0761,13.6172C8.0004,13.7999 7.9806,14.0011 8.0192,14.1951C8.0578,14.3891 8.1531,14.5672 8.293,14.707C8.4805,14.8945 8.7348,14.9998 9,14.9998C9.2652,14.9998 9.5195,14.8945 9.707,14.707Z"
+ android:fillColor="#FF000000" />
+ <path
+ android:pathData="M5.464,10.4641C5.3243,10.604 5.2291,10.7821 5.1906,10.9761C5.1522,11.17 5.172,11.371 5.2477,11.5537C5.3235,11.7364 5.4516,11.8924 5.616,12.0022C5.7805,12.112 5.9738,12.1707 6.1715,12.1707C6.3692,12.1707 6.5625,12.112 6.727,12.0022C6.8914,11.8924 7.0196,11.7364 7.0953,11.5537C7.171,11.371 7.1909,11.17 7.1524,10.9761C7.1139,10.7821 7.0188,10.604 6.879,10.4641C6.7861,10.3711 6.6758,10.2972 6.5545,10.2468C6.4331,10.1965 6.3029,10.1707 6.1715,10.1707C6.0401,10.1707 5.91,10.1965 5.7886,10.2468C5.6672,10.2972 5.5569,10.3711 5.464,10.4641Z"
+ android:fillColor="#FF000000" />
+ <path
+ android:pathData="M2.636,7.636C2.4961,7.7758 2.4009,7.954 2.3623,8.148C2.3236,8.3419 2.3434,8.5431 2.4191,8.7258C2.4948,8.9086 2.623,9.0647 2.7874,9.1746C2.9519,9.2845 3.1452,9.3433 3.343,9.3433C3.5408,9.3433 3.7342,9.2845 3.8986,9.1746C4.0631,9.0647 4.1912,8.9086 4.2669,8.7258C4.3426,8.5431 4.3624,8.3419 4.3238,8.148C4.2852,7.954 4.1899,7.7758 4.05,7.636C3.8625,7.4485 3.6082,7.3433 3.343,7.3433C3.0779,7.3433 2.8235,7.4485 2.636,7.636Z"
+ android:fillColor="#FF000000" />
+</vector>
diff --git a/packages/SystemUI/res/drawable/ic_device_sprinkler_on.xml b/packages/SystemUI/res/drawable/ic_device_sprinkler_on.xml
new file mode 100644
index 000000000000..a5bdf1cd615d
--- /dev/null
+++ b/packages/SystemUI/res/drawable/ic_device_sprinkler_on.xml
@@ -0,0 +1,52 @@
+<?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="24dp"
+ android:height="24dp"
+ android:viewportWidth="24"
+ android:viewportHeight="24">
+ <path
+ android:pathData="M20.657,9.343C21.2093,9.343 21.657,8.8953 21.657,8.343C21.657,7.7907 21.2093,7.343 20.657,7.343C20.1047,7.343 19.657,7.7907 19.657,8.343C19.657,8.8953 20.1047,9.343 20.657,9.343Z"
+ android:fillColor="#FF000000" />
+ <path
+ android:pathData="M7.5,18H11V21H13V18H16.5V16H7.5V18Z"
+ android:fillColor="#FF000000" />
+ <path
+ android:pathData="M12,13C12.5523,13 13,12.5523 13,12C13,11.4477 12.5523,11 12,11C11.4477,11 11,11.4477 11,12C11,12.5523 11.4477,13 12,13Z"
+ android:fillColor="#FF000000" />
+ <path
+ android:pathData="M12,9C12.5523,9 13,8.5523 13,8C13,7.4477 12.5523,7 12,7C11.4477,7 11,7.4477 11,8C11,8.5523 11.4477,9 12,9Z"
+ android:fillColor="#FF000000" />
+ <path
+ android:pathData="M12,5C12.5523,5 13,4.5523 13,4C13,3.4477 12.5523,3 12,3C11.4477,3 11,3.4477 11,4C11,4.5523 11.4477,5 12,5Z"
+ android:fillColor="#FF000000" />
+ <path
+ android:pathData="M15.707,14.707C15.8469,14.5672 15.9422,14.3891 15.9808,14.1951C16.0194,14.0011 15.9996,13.7999 15.9239,13.6172C15.8483,13.4344 15.7201,13.2784 15.5556,13.1685C15.3912,13.0586 15.1978,12.9998 15,12.9998C14.8022,12.9998 14.6089,13.0586 14.4444,13.1685C14.28,13.2784 14.1518,13.4344 14.0761,13.6172C14.0004,13.7999 13.9807,14.0011 14.0193,14.1951C14.0579,14.3891 14.1531,14.5672 14.293,14.707C14.4806,14.8945 14.7349,14.9998 15,14.9998C15.2652,14.9998 15.5195,14.8945 15.707,14.707Z"
+ android:fillColor="#FF000000" />
+ <path
+ android:pathData="M18.536,10.4642C18.3961,10.3245 18.2179,10.2293 18.024,10.1908C17.83,10.1523 17.629,10.1722 17.4464,10.2479C17.2637,10.3236 17.1076,10.4516 16.9978,10.616C16.8879,10.7805 16.8293,10.9737 16.8293,11.1715C16.8293,11.3692 16.8879,11.5627 16.9978,11.7271C17.1076,11.8916 17.2637,12.0196 17.4464,12.0953C17.629,12.171 17.83,12.1909 18.024,12.1524C18.2179,12.1139 18.3961,12.0187 18.536,11.879C18.629,11.7861 18.7028,11.6759 18.7531,11.5545C18.8034,11.4331 18.8293,11.3029 18.8293,11.1715C18.8293,11.0401 18.8034,10.9101 18.7531,10.7887C18.7028,10.6673 18.629,10.5571 18.536,10.4642Z"
+ android:fillColor="#FF000000" />
+ <path
+ android:pathData="M9.707,14.707C9.8469,14.5672 9.9422,14.3891 9.9808,14.1951C10.0194,14.0011 9.9996,13.7999 9.9239,13.6172C9.8483,13.4344 9.7201,13.2784 9.5556,13.1685C9.3912,13.0586 9.1978,12.9998 9,12.9998C8.8022,12.9998 8.6089,13.0586 8.4444,13.1685C8.28,13.2784 8.1518,13.4344 8.0761,13.6172C8.0004,13.7999 7.9807,14.0011 8.0193,14.1951C8.0579,14.3891 8.1531,14.5672 8.293,14.707C8.4806,14.8945 8.7349,14.9998 9,14.9998C9.2652,14.9998 9.5195,14.8945 9.707,14.707Z"
+ android:fillColor="#FF000000" />
+ <path
+ android:pathData="M5.464,10.4641C5.3243,10.604 5.2291,10.7821 5.1906,10.9761C5.1522,11.17 5.172,11.371 5.2477,11.5537C5.3235,11.7364 5.4516,11.8924 5.616,12.0022C5.7805,12.112 5.9738,12.1707 6.1715,12.1707C6.3692,12.1707 6.5625,12.112 6.727,12.0022C6.8914,11.8924 7.0196,11.7364 7.0953,11.5537C7.171,11.371 7.1909,11.17 7.1524,10.9761C7.1139,10.7821 7.0188,10.604 6.879,10.4641C6.7861,10.3711 6.6758,10.2972 6.5545,10.2468C6.4331,10.1965 6.3029,10.1707 6.1715,10.1707C6.0401,10.1707 5.91,10.1965 5.7886,10.2468C5.6672,10.2972 5.5569,10.3711 5.464,10.4641Z"
+ android:fillColor="#FF000000" />
+ <path
+ android:pathData="M2.636,7.636C2.4961,7.7758 2.4009,7.954 2.3623,8.148C2.3236,8.3419 2.3434,8.5431 2.4191,8.7258C2.4948,8.9086 2.623,9.0647 2.7874,9.1746C2.9519,9.2845 3.1452,9.3433 3.343,9.3433C3.5408,9.3433 3.7342,9.2845 3.8986,9.1746C4.0631,9.0647 4.1912,8.9086 4.2669,8.7258C4.3426,8.5431 4.3624,8.3419 4.3238,8.148C4.2852,7.954 4.1899,7.7758 4.05,7.636C3.8625,7.4485 3.6082,7.3433 3.343,7.3433C3.0779,7.3433 2.8235,7.4485 2.636,7.636Z"
+ android:fillColor="#FF000000" />
+</vector>
diff --git a/packages/SystemUI/res/drawable/ic_device_styler_off.xml b/packages/SystemUI/res/drawable/ic_device_styler_off.xml
new file mode 100644
index 000000000000..4d5e3f385f4c
--- /dev/null
+++ b/packages/SystemUI/res/drawable/ic_device_styler_off.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="24dp"
+ android:height="24dp"
+ android:viewportWidth="24"
+ android:viewportHeight="24">
+ <path
+ android:pathData="M19.56,11.361L13,8.4408V6.9999C13,6.7347 12.8946,6.4804 12.7071,6.2929C12.5196,6.1054 12.2652,5.9999 12,5.9999C11.8022,5.9999 11.6089,5.9413 11.4444,5.8315C11.28,5.7216 11.1518,5.5652 11.0761,5.3825C11.0004,5.1998 10.9806,4.9988 11.0192,4.8049C11.0578,4.6109 11.153,4.4327 11.2929,4.2929C11.4327,4.153 11.6109,4.0578 11.8049,4.0192C11.9989,3.9806 12.2,4.0004 12.3827,4.0761C12.5654,4.1518 12.7216,4.2798 12.8315,4.4443C12.9414,4.6087 13,4.8021 13,4.9999H15C15.0015,4.4496 14.8517,3.9095 14.5668,3.4386C14.2819,2.9678 13.8729,2.5843 13.3847,2.3303C12.8965,2.0762 12.3478,1.9613 11.7987,1.9982C11.2496,2.0351 10.7212,2.2224 10.2714,2.5395C9.8216,2.8566 9.4677,3.2915 9.2484,3.7963C9.0291,4.3011 8.9529,4.8563 9.0282,5.4015C9.1034,5.9467 9.3272,6.4608 9.6749,6.8874C10.0227,7.3139 10.4811,7.6365 11,7.82V8.4499L4.44,11.37C4.0115,11.5562 3.6468,11.8636 3.3909,12.2546C3.1351,12.6455 2.9992,13.1028 3,13.57V13.58C2.9995,13.8979 3.0617,14.2129 3.1831,14.5068C3.3046,14.8006 3.4828,15.0676 3.7076,15.2924C3.9325,15.5172 4.1994,15.6954 4.4933,15.8168C4.7871,15.9382 5.1021,16.0004 5.42,15.9999H7V21.9999H17V15.9999H18.58C18.898,16.0004 19.2129,15.9382 19.5067,15.8168C19.8006,15.6954 20.0676,15.5172 20.2924,15.2924C20.5172,15.0676 20.6954,14.8006 20.8169,14.5068C20.9383,14.2129 21.0005,13.8979 21,13.58V13.57C20.9994,13.1019 20.8631,12.644 20.6075,12.2519C20.3519,11.8598 19.988,11.5504 19.56,11.361ZM15,19.9999H9V14.9999H15V19.9999ZM18.58,13.9999H17V12.9999H7V13.9999H5.42C5.3642,13.9993 5.3091,13.9877 5.2577,13.9657C5.2064,13.9438 5.1599,13.9119 5.1209,13.872C5.0819,13.8321 5.0512,13.7846 5.0304,13.7328C5.0097,13.681 4.9993,13.6258 5,13.57C4.999,13.4889 5.0222,13.4094 5.0668,13.3417C5.1114,13.274 5.1752,13.221 5.25,13.1899L12,10.1899L18.75,13.1899C18.8245,13.2243 18.8876,13.2795 18.9319,13.3486C18.9761,13.4176 18.9998,13.4979 19,13.58C18.9995,13.6912 18.9551,13.7977 18.8764,13.8764C18.7978,13.955 18.6912,13.9994 18.58,13.9999Z"
+ android:fillColor="#FF000000" />
+</vector>
diff --git a/packages/SystemUI/res/drawable/ic_device_styler_on.xml b/packages/SystemUI/res/drawable/ic_device_styler_on.xml
new file mode 100644
index 000000000000..58e04e0913b3
--- /dev/null
+++ b/packages/SystemUI/res/drawable/ic_device_styler_on.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="24dp"
+ android:height="24dp"
+ android:viewportWidth="24"
+ android:viewportHeight="24">
+ <path
+ android:pathData="M19.56,11.361L13,8.4408V6.9999C13,6.7347 12.8946,6.4804 12.7071,6.2929C12.5196,6.1054 12.2652,5.9999 12,5.9999C11.8022,5.9999 11.6089,5.9413 11.4444,5.8315C11.28,5.7216 11.1518,5.5652 11.0761,5.3825C11.0004,5.1998 10.9806,4.9988 11.0192,4.8049C11.0578,4.6109 11.153,4.4327 11.2929,4.2929C11.4327,4.153 11.6109,4.0578 11.8049,4.0192C11.9989,3.9806 12.2,4.0004 12.3827,4.0761C12.5654,4.1518 12.7216,4.2798 12.8315,4.4443C12.9414,4.6087 13,4.8021 13,4.9999H15C15.0015,4.4496 14.8517,3.9095 14.5668,3.4386C14.2819,2.9678 13.8729,2.5843 13.3847,2.3303C12.8965,2.0762 12.3478,1.9613 11.7987,1.9982C11.2496,2.0351 10.7212,2.2224 10.2714,2.5395C9.8216,2.8566 9.4677,3.2915 9.2484,3.7963C9.0291,4.3011 8.9529,4.8563 9.0282,5.4015C9.1034,5.9467 9.3272,6.4608 9.6749,6.8874C10.0227,7.3139 10.4811,7.6365 11,7.82V8.4499L4.44,11.37C4.0115,11.5562 3.6468,11.8636 3.3909,12.2546C3.1351,12.6455 2.9992,13.1028 3,13.57V13.58C2.9995,13.8979 3.0617,14.2129 3.1831,14.5068C3.3046,14.8006 3.4828,15.0676 3.7076,15.2924C3.9325,15.5172 4.1994,15.6954 4.4933,15.8168C4.7871,15.9382 5.1021,16.0004 5.42,15.9999H7V21.9999H17V15.9999H18.58C18.898,16.0004 19.2129,15.9382 19.5067,15.8168C19.8006,15.6954 20.0676,15.5172 20.2924,15.2924C20.5172,15.0676 20.6954,14.8006 20.8169,14.5068C20.9383,14.2129 21.0005,13.8979 21,13.58V13.57C20.9994,13.1019 20.8631,12.644 20.6075,12.2519C20.3519,11.8598 19.988,11.5504 19.56,11.361ZM18.58,14.0009H17V13.0009H7V14.0009H5.42C5.3642,14.0002 5.3091,13.9887 5.2577,13.9667C5.2064,13.9448 5.1599,13.9129 5.1209,13.873C5.0819,13.833 5.0512,13.7859 5.0304,13.7341C5.0097,13.6822 4.9993,13.6268 5,13.571C4.999,13.4899 5.0222,13.4104 5.0668,13.3427C5.1114,13.275 5.1752,13.222 5.25,13.1908L12,10.1908L18.75,13.1908C18.8245,13.2253 18.8876,13.2804 18.9319,13.3495C18.9761,13.4186 18.9998,13.4989 19,13.581C18.9992,13.692 18.9547,13.7982 18.8761,13.8766C18.7974,13.9551 18.6911,13.9994 18.58,13.9999V14.0009Z"
+ android:fillColor="#FF000000" />
+</vector>
diff --git a/packages/SystemUI/res/drawable/ic_device_switch_off.xml b/packages/SystemUI/res/drawable/ic_device_switch_off.xml
new file mode 100644
index 000000000000..12dcd816aee8
--- /dev/null
+++ b/packages/SystemUI/res/drawable/ic_device_switch_off.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
+ -->
+<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,3H5C4.4696,3 3.9609,3.2107 3.5858,3.5858C3.2107,3.9609 3,4.4696 3,5V19C3,19.5304 3.2107,20.0391 3.5858,20.4142C3.9609,20.7893 4.4696,21 5,21H19C19.5304,21 20.0391,20.7893 20.4142,20.4142C20.7893,20.0391 21,19.5304 21,19V5C21,4.4696 20.7893,3.9609 20.4142,3.5858C20.0391,3.2107 19.5304,3 19,3ZM19,19H5V5H19V19Z"
+ android:fillColor="#FF000000" />
+ <path
+ android:pathData="M16,7H8V17H16V7ZM14,15H10V9H14V15Z"
+ android:fillColor="#FF000000" />
+ <path
+ android:pathData="M13,10H11V12H13V10Z"
+ android:fillColor="#FF000000" />
+</vector>
diff --git a/packages/SystemUI/res/drawable/ic_device_switch_on.xml b/packages/SystemUI/res/drawable/ic_device_switch_on.xml
new file mode 100644
index 000000000000..68678a39506b
--- /dev/null
+++ b/packages/SystemUI/res/drawable/ic_device_switch_on.xml
@@ -0,0 +1,28 @@
+<?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="24dp"
+ android:height="24dp"
+ android:viewportWidth="24"
+ android:viewportHeight="24">
+ <path
+ android:pathData="M14,9H10V15H14V9ZM13,12H11V10H13V12Z"
+ android:fillColor="#FF000000" />
+ <path
+ android:pathData="M19,3H5C4.4696,3 3.9609,3.2107 3.5858,3.5858C3.2107,3.9609 3,4.4696 3,5V19C3,19.5304 3.2107,20.0391 3.5858,20.4142C3.9609,20.7893 4.4696,21 5,21H19C19.5304,21 20.0391,20.7893 20.4142,20.4142C20.7893,20.0391 21,19.5304 21,19V5C21,4.4696 20.7893,3.9609 20.4142,3.5858C20.0391,3.2107 19.5304,3 19,3ZM16,17H8V7H16V17Z"
+ android:fillColor="#FF000000" />
+</vector>
diff --git a/packages/SystemUI/res/drawable/ic_device_thermostat_gm2_24px.xml b/packages/SystemUI/res/drawable/ic_device_thermostat_gm2_24px.xml
deleted file mode 100644
index 45a658fe07da..000000000000
--- a/packages/SystemUI/res/drawable/ic_device_thermostat_gm2_24px.xml
+++ /dev/null
@@ -1,9 +0,0 @@
-<vector xmlns:android="http://schemas.android.com/apk/res/android"
- android:width="24dp"
- android:height="24dp"
- android:viewportWidth="24"
- android:viewportHeight="24">
- <path
- android:fillColor="#FF000000"
- android:pathData="M18,9h-5v2h5m3,-6h-8v2h8m-9,11.97c0.62,-0.83 1,-1.85 1,-2.97 0,-1.63 -0.79,-3.09 -2,-4V6c0,-1.66 -1.34,-3 -3,-3S5,4.34 5,6v6c-1.21,0.91 -2,2.37 -2,4 0,1.12 0.38,2.14 1,2.97V19h0.02c0.91,1.21 2.35,2 3.98,2s3.06,-0.79 3.98,-2H12v-0.03zM6.2,13.6L7,13V6c0,-0.55 0.45,-1 1,-1s1,0.45 1,1v7l0.8,0.6c0.75,0.57 1.2,1.46 1.2,2.4H5c0,-0.94 0.45,-1.84 1.2,-2.4z"/>
-</vector>
diff --git a/packages/SystemUI/res/drawable/ic_device_thermostat_off.xml b/packages/SystemUI/res/drawable/ic_device_thermostat_off.xml
new file mode 100644
index 000000000000..1ba8741e4ae2
--- /dev/null
+++ b/packages/SystemUI/res/drawable/ic_device_thermostat_off.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="24dp"
+ android:height="24dp"
+ android:viewportWidth="24"
+ android:viewportHeight="24">
+ <path
+ android:pathData="M16,18.97C16.6469,18.1148 16.9979,17.0723 17,16C16.9993,15.2239 16.8183,14.4586 16.4712,13.7644C16.1241,13.0702 15.6205,12.4662 15,12V6C15,5.2043 14.6839,4.4413 14.1213,3.8787C13.5587,3.3161 12.7956,3 12,3C11.2044,3 10.4413,3.3161 9.8787,3.8787C9.3161,4.4413 9,5.2043 9,6V12C8.3795,12.4662 7.8759,13.0702 7.5288,13.7644C7.1817,14.4586 7.0007,15.2239 7,16C7.0021,17.0723 7.3531,18.1148 8,18.97V19H8.02C8.4815,19.6206 9.0818,20.1246 9.7729,20.4719C10.4639,20.8192 11.2266,21.0001 12,21.0001C12.7734,21.0001 13.5361,20.8192 14.2271,20.4719C14.9182,20.1246 15.5185,19.6206 15.98,19H16V18.97ZM10.2,13.6L11,13V6C11,5.7348 11.1054,5.4804 11.2929,5.2929C11.4804,5.1054 11.7348,5 12,5C12.2652,5 12.5196,5.1054 12.7071,5.2929C12.8946,5.4804 13,5.7348 13,6V13L13.8,13.6C14.1711,13.8809 14.4723,14.2435 14.6805,14.6598C14.8886,15.076 14.9979,15.5346 15,16H9C9.0009,15.5344 9.1098,15.0754 9.318,14.659C9.5262,14.2426 9.8281,13.8801 10.2,13.6Z"
+ android:fillColor="#FF000000" />
+</vector>
diff --git a/packages/SystemUI/res/drawable/ic_device_thermostat_on.xml b/packages/SystemUI/res/drawable/ic_device_thermostat_on.xml
new file mode 100644
index 000000000000..1ba8741e4ae2
--- /dev/null
+++ b/packages/SystemUI/res/drawable/ic_device_thermostat_on.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="24dp"
+ android:height="24dp"
+ android:viewportWidth="24"
+ android:viewportHeight="24">
+ <path
+ android:pathData="M16,18.97C16.6469,18.1148 16.9979,17.0723 17,16C16.9993,15.2239 16.8183,14.4586 16.4712,13.7644C16.1241,13.0702 15.6205,12.4662 15,12V6C15,5.2043 14.6839,4.4413 14.1213,3.8787C13.5587,3.3161 12.7956,3 12,3C11.2044,3 10.4413,3.3161 9.8787,3.8787C9.3161,4.4413 9,5.2043 9,6V12C8.3795,12.4662 7.8759,13.0702 7.5288,13.7644C7.1817,14.4586 7.0007,15.2239 7,16C7.0021,17.0723 7.3531,18.1148 8,18.97V19H8.02C8.4815,19.6206 9.0818,20.1246 9.7729,20.4719C10.4639,20.8192 11.2266,21.0001 12,21.0001C12.7734,21.0001 13.5361,20.8192 14.2271,20.4719C14.9182,20.1246 15.5185,19.6206 15.98,19H16V18.97ZM10.2,13.6L11,13V6C11,5.7348 11.1054,5.4804 11.2929,5.2929C11.4804,5.1054 11.7348,5 12,5C12.2652,5 12.5196,5.1054 12.7071,5.2929C12.8946,5.4804 13,5.7348 13,6V13L13.8,13.6C14.1711,13.8809 14.4723,14.2435 14.6805,14.6598C14.8886,15.076 14.9979,15.5346 15,16H9C9.0009,15.5344 9.1098,15.0754 9.318,14.659C9.5262,14.2426 9.8281,13.8801 10.2,13.6Z"
+ android:fillColor="#FF000000" />
+</vector>
diff --git a/packages/SystemUI/res/drawable/ic_device_tv_off.xml b/packages/SystemUI/res/drawable/ic_device_tv_off.xml
new file mode 100644
index 000000000000..dd91ed831bb8
--- /dev/null
+++ b/packages/SystemUI/res/drawable/ic_device_tv_off.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="24dp"
+ android:height="24dp"
+ android:viewportWidth="24"
+ android:viewportHeight="24">
+ <path
+ android:pathData="M20,4H4C3.4701,4.0016 2.9623,4.2129 2.5875,4.5876C2.2128,4.9624 2.0016,5.47 2,6V17C2.0016,17.5299 2.2128,18.0376 2.5875,18.4124C2.9623,18.7871 3.4701,18.9984 4,19V21H5L5.667,19H18.333L19,21H20V19C20.5299,18.9984 21.0377,18.7871 21.4125,18.4124C21.7872,18.0376 21.9984,17.5299 22,17V6C21.9984,5.47 21.7872,4.9624 21.4125,4.5876C21.0377,4.2129 20.5299,4.0016 20,4ZM20,17H4V6H20V17Z"
+ android:fillColor="#FF000000" />
+</vector>
diff --git a/packages/SystemUI/res/drawable/ic_device_tv_on.xml b/packages/SystemUI/res/drawable/ic_device_tv_on.xml
new file mode 100644
index 000000000000..dd91ed831bb8
--- /dev/null
+++ b/packages/SystemUI/res/drawable/ic_device_tv_on.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="24dp"
+ android:height="24dp"
+ android:viewportWidth="24"
+ android:viewportHeight="24">
+ <path
+ android:pathData="M20,4H4C3.4701,4.0016 2.9623,4.2129 2.5875,4.5876C2.2128,4.9624 2.0016,5.47 2,6V17C2.0016,17.5299 2.2128,18.0376 2.5875,18.4124C2.9623,18.7871 3.4701,18.9984 4,19V21H5L5.667,19H18.333L19,21H20V19C20.5299,18.9984 21.0377,18.7871 21.4125,18.4124C21.7872,18.0376 21.9984,17.5299 22,17V6C21.9984,5.47 21.7872,4.9624 21.4125,4.5876C21.0377,4.2129 20.5299,4.0016 20,4ZM20,17H4V6H20V17Z"
+ android:fillColor="#FF000000" />
+</vector>
diff --git a/packages/SystemUI/res/drawable/ic_device_vacuum_off.xml b/packages/SystemUI/res/drawable/ic_device_vacuum_off.xml
new file mode 100644
index 000000000000..e0fadc8a9a27
--- /dev/null
+++ b/packages/SystemUI/res/drawable/ic_device_vacuum_off.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="24dp"
+ android:height="24dp"
+ android:viewportWidth="24"
+ android:viewportHeight="24">
+ <path
+ android:pathData="M4,16.0001C3.4067,16.0001 2.8266,16.176 2.3333,16.5057C1.8399,16.8353 1.4554,17.3039 1.2284,17.8521C1.0013,18.4002 0.9419,19.0034 1.0576,19.5854C1.1734,20.1673 1.4591,20.7019 1.8787,21.1214C2.2982,21.541 2.8328,21.8267 3.4147,21.9425C3.9967,22.0582 4.5999,21.9988 5.148,21.7717C5.6962,21.5447 6.1648,21.1602 6.4944,20.6668C6.824,20.1735 7,19.5934 7,19.0001C7,18.2045 6.6839,17.4414 6.1213,16.8788C5.5587,16.3162 4.7957,16.0001 4,16.0001ZM4,20.0001C3.8022,20.0001 3.6089,19.9415 3.4444,19.8316C3.28,19.7217 3.1518,19.5655 3.0761,19.3828C3.0004,19.2001 2.9806,18.999 3.0192,18.805C3.0578,18.611 3.153,18.4329 3.2929,18.293C3.4327,18.1532 3.6109,18.0579 3.8049,18.0193C3.9989,17.9807 4.2,18.0005 4.3827,18.0762C4.5654,18.1519 4.7216,18.2801 4.8315,18.4445C4.9413,18.609 5,18.8023 5,19.0001C5,19.2653 4.8946,19.5197 4.7071,19.7072C4.5196,19.8947 4.2652,20.0001 4,20.0001ZM23,20.0001V22.0001H16V20.0001H18.49L12.01,4.5901C11.7747,4.0366 11.3553,3.5814 10.823,3.3016C10.2906,3.0217 9.6779,2.9344 9.0885,3.0544C8.4991,3.1744 7.9693,3.4943 7.5888,3.96C7.2082,4.4257 7.0002,5.0086 7,5.6101V9.0001H9C10.0609,9.0001 11.0783,9.4215 11.8284,10.1717C12.5786,10.9218 13,11.9392 13,13.0001V22.0001H7.99C8.4398,21.4103 8.7508,20.7267 8.9,20.0001H11V13.0001C10.9984,12.4702 10.7872,11.9624 10.4125,11.5876C10.0377,11.2129 9.5299,11.0017 9,11.0001H4V14.0001C3.3113,13.9992 2.6301,14.1422 2,14.4201V9.0001H5V5.6101C5.0002,4.5458 5.3685,3.5144 6.0426,2.6908C6.7165,1.8672 7.6547,1.3021 8.6979,1.0913C9.741,0.8806 10.825,1.0372 11.7659,1.5345C12.7068,2.0319 13.4466,2.8394 13.86,3.8201L20.66,20.0001H23Z"
+ android:fillColor="#FF000000" />
+</vector>
diff --git a/packages/SystemUI/res/drawable/ic_device_vacuum_on.xml b/packages/SystemUI/res/drawable/ic_device_vacuum_on.xml
new file mode 100644
index 000000000000..d3b0a7df6cbe
--- /dev/null
+++ b/packages/SystemUI/res/drawable/ic_device_vacuum_on.xml
@@ -0,0 +1,28 @@
+<?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="24dp"
+ android:height="24dp"
+ android:viewportWidth="24"
+ android:viewportHeight="24">
+ <path
+ android:pathData="M4,16.0001C3.4067,16.0001 2.8266,16.176 2.3333,16.5057C1.8399,16.8353 1.4554,17.3039 1.2284,17.8521C1.0013,18.4002 0.9419,19.0034 1.0576,19.5854C1.1734,20.1673 1.4591,20.7018 1.8787,21.1214C2.2982,21.541 2.8328,21.8267 3.4147,21.9424C3.9967,22.0582 4.5999,21.9988 5.148,21.7717C5.6962,21.5447 6.1648,21.1602 6.4944,20.6668C6.824,20.1735 7,19.5934 7,19.0001C7,18.2044 6.6839,17.4414 6.1213,16.8788C5.5587,16.3162 4.7957,16.0001 4,16.0001ZM4,20.0001C3.8022,20.0001 3.6089,19.9415 3.4444,19.8316C3.28,19.7217 3.1518,19.5655 3.0761,19.3828C3.0004,19.2001 2.9806,18.999 3.0192,18.805C3.0578,18.611 3.153,18.4329 3.2929,18.293C3.4327,18.1531 3.6109,18.0579 3.8049,18.0193C3.9989,17.9807 4.2,18.0005 4.3827,18.0762C4.5654,18.1519 4.7216,18.2801 4.8315,18.4445C4.9413,18.609 5,18.8023 5,19.0001C5,19.2653 4.8946,19.5196 4.7071,19.7072C4.5196,19.8947 4.2652,20.0001 4,20.0001Z"
+ android:fillColor="#FF000000" />
+ <path
+ android:pathData="M20.66,20.0001L13.86,3.8201C13.4466,2.8394 12.7068,2.0319 11.7659,1.5345C10.825,1.0372 9.7411,0.8806 8.6979,1.0913C7.6547,1.3021 6.7165,1.8672 6.0426,2.6908C5.3685,3.5144 5.0002,4.5458 5,5.6101V9.0001H2V14.4261C2.76,14.0908 3.5918,13.9506 4.4197,14.0184C5.2476,14.0861 6.0455,14.3596 6.7409,14.814C7.4363,15.2684 8.0072,15.8893 8.4017,16.6203C8.7962,17.3514 9.0019,18.1694 9,19.0001C8.9968,20.0853 8.637,21.1394 7.976,22.0001H13V13.0001C13,11.9392 12.5786,10.9218 11.8284,10.1717C11.0783,9.4215 10.0609,9.0001 9,9.0001H7V5.6101C7.0002,5.0086 7.2082,4.4257 7.5888,3.96C7.9693,3.4943 8.4991,3.1744 9.0885,3.0544C9.6779,2.9344 10.2906,3.0217 10.823,3.3016C11.3553,3.5814 11.7747,4.0366 12.01,4.5901L18.49,20.0001H16V22.0001H23V20.0001H20.66Z"
+ android:fillColor="#FF000000" />
+</vector>
diff --git a/packages/SystemUI/res/drawable/ic_device_valve_off.xml b/packages/SystemUI/res/drawable/ic_device_valve_off.xml
new file mode 100644
index 000000000000..5bfb46fdd2bd
--- /dev/null
+++ b/packages/SystemUI/res/drawable/ic_device_valve_off.xml
@@ -0,0 +1,28 @@
+<?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="24dp"
+ android:height="24dp"
+ android:viewportWidth="24"
+ android:viewportHeight="24">
+ <path
+ android:pathData="M11,8H13V5H17V3H7V5H11V8Z"
+ android:fillColor="#FF000000" />
+ <path
+ android:pathData="M18,13V14H15V11H16V9H8V11H9V14H6V13H4V21H6V20H18V21H20V13H18ZM6,18V16H11V11H13V16H18V18H6Z"
+ android:fillColor="#FF000000" />
+</vector>
diff --git a/packages/SystemUI/res/drawable/ic_device_valve_on.xml b/packages/SystemUI/res/drawable/ic_device_valve_on.xml
new file mode 100644
index 000000000000..66b882933141
--- /dev/null
+++ b/packages/SystemUI/res/drawable/ic_device_valve_on.xml
@@ -0,0 +1,28 @@
+<?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="24dp"
+ android:height="24dp"
+ android:viewportWidth="24"
+ android:viewportHeight="24">
+ <path
+ android:pathData="M11,8H13V5H17V3H7V5H11V8Z"
+ android:fillColor="#FF000000" />
+ <path
+ android:pathData="M18,13V14H15V11H16V9H8V11H9V14H6V13H4V21H6V20H18V21H20V13H18Z"
+ android:fillColor="#FF000000" />
+</vector>
diff --git a/packages/SystemUI/res/drawable/ic_device_washer_off.xml b/packages/SystemUI/res/drawable/ic_device_washer_off.xml
new file mode 100644
index 000000000000..f759bcc88cda
--- /dev/null
+++ b/packages/SystemUI/res/drawable/ic_device_washer_off.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
+ -->
+<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.01L6,2C5.7371,1.9991 5.4766,2.0502 5.2336,2.1504C4.9905,2.2506 4.7696,2.3979 4.5837,2.5838C4.3978,2.7696 4.2505,2.9906 4.1504,3.2336C4.0502,3.4767 3.9991,3.7371 4,4V20C3.9991,20.2629 4.0502,20.5233 4.1504,20.7664C4.2505,21.0094 4.3978,21.2304 4.5837,21.4163C4.7696,21.6022 4.9905,21.7494 5.2336,21.8496C5.4766,21.9498 5.7371,22.0009 6,22H18C18.2629,22.0009 18.5234,21.9498 18.7665,21.8496C19.0095,21.7494 19.2304,21.6022 19.4163,21.4163C19.6022,21.2304 19.7495,21.0094 19.8497,20.7664C19.9498,20.5233 20.0009,20.2629 20,20V4C20.0007,3.7376 19.9493,3.4778 19.8489,3.2354C19.7485,2.993 19.6011,2.773 19.4151,2.5879C19.2291,2.4028 19.0083,2.2564 18.7654,2.1572C18.5225,2.0581 18.2624,2.008 18,2.01ZM18,20H6L5.993,4H18V20Z"
+ android:fillColor="#FF000000" />
+ <path
+ android:pathData="M11,7C11.5523,7 12,6.5523 12,6C12,5.4477 11.5523,5 11,5C10.4477,5 10,5.4477 10,6C10,6.5523 10.4477,7 11,7Z"
+ android:fillColor="#FF000000" />
+ <path
+ android:pathData="M8,7C8.5523,7 9,6.5523 9,6C9,5.4477 8.5523,5 8,5C7.4477,5 7,5.4477 7,6C7,6.5523 7.4477,7 8,7Z"
+ android:fillColor="#FF000000" />
+ <path
+ android:pathData="M12,18.9999C12.9889,18.9999 13.9556,18.7065 14.7778,18.1571C15.6001,17.6077 16.241,16.8269 16.6194,15.9132C16.9978,14.9996 17.0969,13.9945 16.9039,13.0246C16.711,12.0547 16.2348,11.1635 15.5355,10.4643C14.8363,9.765 13.9454,9.289 12.9754,9.0961C12.0055,8.9032 11.0002,9.0021 10.0866,9.3805C9.1729,9.759 8.3921,10.3998 7.8426,11.2221C7.2932,12.0443 7,13.011 7,13.9999C7,15.326 7.5268,16.5979 8.4645,17.5356C9.4021,18.4732 10.6739,18.9999 12,18.9999ZM14.36,11.6398C14.9689,12.2692 15.3061,13.1127 15.2989,13.9884C15.2916,14.8641 14.9405,15.702 14.3213,16.3212C13.7021,16.9404 12.8643,17.2915 11.9886,17.2987C11.1129,17.306 10.2694,16.9689 9.64,16.36L14.36,11.6398Z"
+ android:fillColor="#FF000000" />
+</vector>
diff --git a/packages/SystemUI/res/drawable/ic_device_washer_on.xml b/packages/SystemUI/res/drawable/ic_device_washer_on.xml
new file mode 100644
index 000000000000..b624fb6ebb13
--- /dev/null
+++ b/packages/SystemUI/res/drawable/ic_device_washer_on.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="24dp"
+ android:height="24dp"
+ android:viewportWidth="24"
+ android:viewportHeight="24">
+ <path
+ android:pathData="M9.64,16.3601C10.2694,16.969 11.1129,17.3061 11.9886,17.2988C12.8643,17.2916 13.7021,16.9405 14.3213,16.3213C14.9406,15.7021 15.2916,14.8642 15.2989,13.9885C15.3061,13.1128 14.9689,12.2693 14.36,11.6399L9.64,16.3601ZM18,2.01L6,2C5.7371,1.9991 5.4766,2.0502 5.2336,2.1504C4.9905,2.2506 4.7696,2.3979 4.5837,2.5838C4.3978,2.7696 4.2505,2.9906 4.1504,3.2336C4.0502,3.4767 3.9991,3.7371 4,4V20C3.9991,20.2629 4.0502,20.5233 4.1504,20.7664C4.2505,21.0094 4.3978,21.2304 4.5837,21.4163C4.7696,21.6022 4.9905,21.7494 5.2336,21.8496C5.4766,21.9498 5.7371,22.0009 6,22H18C18.2629,22.0009 18.5234,21.9498 18.7665,21.8496C19.0095,21.7494 19.2304,21.6022 19.4163,21.4163C19.6022,21.2304 19.7495,21.0094 19.8497,20.7664C19.9498,20.5233 20.0009,20.2629 20,20V4C20.0007,3.7376 19.9493,3.4778 19.8489,3.2354C19.7485,2.993 19.6011,2.773 19.4151,2.5879C19.2291,2.4028 19.0083,2.2564 18.7654,2.1572C18.5225,2.0581 18.2624,2.008 18,2.01ZM11,5C11.1978,5 11.3911,5.0586 11.5556,5.1685C11.72,5.2783 11.8482,5.4347 11.9239,5.6174C11.9996,5.8002 12.0194,6.0011 11.9808,6.1951C11.9422,6.3891 11.847,6.5672 11.7071,6.707C11.5673,6.8469 11.3891,6.9421 11.1951,6.9807C11.0011,7.0193 10.8001,6.9995 10.6173,6.9238C10.4346,6.8481 10.2784,6.7201 10.1685,6.5557C10.0587,6.3912 10,6.1978 10,6C10,5.7348 10.1054,5.4805 10.2929,5.293C10.4804,5.1054 10.7348,5 11,5ZM8,5C8.1978,5 8.3911,5.0586 8.5556,5.1685C8.72,5.2783 8.8482,5.4347 8.9239,5.6174C8.9996,5.8002 9.0194,6.0011 8.9808,6.1951C8.9422,6.3891 8.847,6.5672 8.7071,6.707C8.5673,6.8469 8.3891,6.9421 8.1951,6.9807C8.0011,7.0193 7.8001,6.9995 7.6173,6.9238C7.4346,6.8481 7.2784,6.7201 7.1685,6.5557C7.0587,6.3912 7,6.1978 7,6C7,5.7348 7.1054,5.4805 7.2929,5.293C7.4804,5.1054 7.7348,5 8,5ZM12,19C11.0111,19 10.0444,18.7066 9.2222,18.1572C8.3999,17.6078 7.759,16.827 7.3806,15.9133C7.0022,14.9997 6.9032,13.9946 7.0961,13.0247C7.289,12.0548 7.7652,11.1636 8.4645,10.4644C9.1637,9.7651 10.0547,9.2891 11.0246,9.0962C11.9945,8.9033 12.9998,9.0022 13.9134,9.3806C14.8271,9.7591 15.608,10.3999 16.1574,11.2222C16.7068,12.0444 17,13.0111 17,14C17,15.3261 16.4732,16.598 15.5355,17.5357C14.5979,18.4733 13.3261,19 12,19Z"
+ android:fillColor="#FF000000" />
+</vector>
diff --git a/packages/SystemUI/res/drawable/ic_device_water_heater_off.xml b/packages/SystemUI/res/drawable/ic_device_water_heater_off.xml
new file mode 100644
index 000000000000..179195821ad9
--- /dev/null
+++ b/packages/SystemUI/res/drawable/ic_device_water_heater_off.xml
@@ -0,0 +1,28 @@
+<?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="24dp"
+ android:height="24dp"
+ android:viewportWidth="24"
+ android:viewportHeight="24">
+ <path
+ android:pathData="M16,2H8C6.9391,2 5.9217,2.4212 5.1716,3.1714C4.4214,3.9215 4,4.9391 4,6V20C4,20.5304 4.2107,21.039 4.5858,21.4141C4.9609,21.7891 5.4696,22 6,22H18C18.5304,22 19.0391,21.7891 19.4142,21.4141C19.7893,21.039 20,20.5304 20,20V6C20,4.9391 19.5786,3.9215 18.8284,3.1714C18.0783,2.4212 17.0609,2 16,2ZM18,20H6V18C7.05,18 7.18,19 9,19C10.82,19 10.952,18 12,18C13.048,18 13.189,19 15,19C16.811,19 16.953,18 18,18V20ZM18,16C16.18,16 16.046,17 15,17C13.954,17 13.81,16 12,16C10.19,16 10.047,17 9,17C7.953,17 7.821,16 6,16V6C6,5.4696 6.2107,4.961 6.5858,4.5859C6.9609,4.2109 7.4696,4 8,4H16C16.5304,4 17.0391,4.2109 17.4142,4.5859C17.7893,4.961 18,5.4696 18,6V16Z"
+ android:fillColor="#FF000000" />
+ <path
+ android:pathData="M13.553,8.0161C13.1979,7.6625 12.9486,7.2166 12.8333,6.729C12.7179,6.2413 12.741,5.7311 12.9,5.2558C12.9134,5.2214 12.9162,5.1839 12.9082,5.1479C12.9003,5.1119 12.8818,5.0792 12.8552,5.0537C12.8286,5.0281 12.795,5.0109 12.7586,5.0044C12.7223,4.9979 12.6849,5.0023 12.6511,5.0171C8.8941,6.6581 10.4031,10.6938 10.4031,10.7568C10.4028,10.8187 10.3848,10.8792 10.3511,10.9311C10.3174,10.9831 10.2695,11.0243 10.2131,11.0498C10.2031,11.0498 9.974,11.1708 9.769,10.8838C9.5395,10.5707 9.3759,10.2145 9.2879,9.8364C9.1999,9.4583 9.1894,9.0663 9.2571,8.6841C9.2647,8.6434 9.2587,8.6012 9.2398,8.5644C9.2209,8.5276 9.1902,8.4984 9.1527,8.4809C9.1152,8.4635 9.0729,8.459 9.0326,8.4682C8.9923,8.4775 8.9562,8.5001 8.93,8.5322C8.503,9.08 8.2253,9.7288 8.1241,10.416C8.023,11.1032 8.1018,11.805 8.3528,12.4526C8.6039,13.1003 9.0187,13.6719 9.5567,14.1113C10.0946,14.5507 10.7373,14.8431 11.4221,14.9599C15.6071,15.4939 17.1871,11.2899 14.7041,8.9599C14.3381,8.6159 13.909,8.3721 13.553,8.0161ZM13.3241,12.8691C13.0354,13.1235 12.6634,13.2626 12.2787,13.2607C11.8939,13.2589 11.5233,13.116 11.2371,12.8589C11.225,12.8488 11.2159,12.836 11.2107,12.8213C11.2054,12.8065 11.2042,12.7903 11.2072,12.7749C11.2101,12.7595 11.2172,12.7452 11.2275,12.7334C11.2379,12.7216 11.2512,12.7129 11.2661,12.708C11.5164,12.6335 11.7426,12.4939 11.9216,12.3037C12.1005,12.1135 12.226,11.8794 12.2851,11.625C12.3198,11.2109 12.2684,10.7941 12.1341,10.4009C12.067,10.0764 12.087,9.74 12.1921,9.4258C12.196,9.4132 12.2035,9.4023 12.2138,9.394C12.2241,9.3858 12.2366,9.3809 12.2497,9.3799C12.2628,9.3788 12.2759,9.3817 12.2874,9.3882C12.2989,9.3946 12.3081,9.4042 12.3141,9.416C12.6801,10.236 13.8361,10.6222 13.8361,11.6162C13.843,11.8492 13.801,12.081 13.7128,12.2969C13.6246,12.5127 13.4922,12.7076 13.3241,12.8691Z"
+ android:fillColor="#FF000000" />
+</vector>
diff --git a/packages/SystemUI/res/drawable/ic_device_water_heater_on.xml b/packages/SystemUI/res/drawable/ic_device_water_heater_on.xml
new file mode 100644
index 000000000000..ee1ca91a5354
--- /dev/null
+++ b/packages/SystemUI/res/drawable/ic_device_water_heater_on.xml
@@ -0,0 +1,28 @@
+<?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="24dp"
+ android:height="24dp"
+ android:viewportWidth="24"
+ android:viewportHeight="24">
+ <path
+ android:pathData="M13.324,12.8694C13.4916,12.7083 13.6238,12.5136 13.7119,12.2986C13.8001,12.0835 13.8424,11.8527 13.836,11.6203C13.836,10.6203 12.68,10.2361 12.314,9.4201C12.3081,9.4084 12.2988,9.3988 12.2874,9.3923C12.2759,9.3859 12.2628,9.3829 12.2496,9.384C12.2365,9.3851 12.224,9.3899 12.2138,9.3982C12.2035,9.4064 12.1959,9.4178 12.192,9.4304C12.087,9.7446 12.067,10.0806 12.134,10.405C12.2683,10.7982 12.3197,11.2151 12.285,11.6291C12.2259,11.8835 12.1005,12.1181 11.9215,12.3083C11.7425,12.4985 11.5164,12.6377 11.266,12.7121C11.2511,12.717 11.2378,12.7257 11.2275,12.7375C11.2171,12.7493 11.2101,12.7636 11.2071,12.779C11.2042,12.7944 11.2054,12.8106 11.2106,12.8254C11.2159,12.8402 11.225,12.8529 11.237,12.863C11.5237,13.1195 11.8947,13.2623 12.2794,13.2634C12.6641,13.2645 13.0358,13.1242 13.324,12.8694Z"
+ android:fillColor="#FF000000" />
+ <path
+ android:pathData="M16,2H8C6.9391,2 5.9217,2.4212 5.1716,3.1714C4.4214,3.9215 4,4.9391 4,6V20C4,20.5304 4.2107,21.039 4.5858,21.4141C4.9609,21.7891 5.4696,22 6,22H18C18.5304,22 19.0391,21.7891 19.4142,21.4141C19.7893,21.039 20,20.5304 20,20V6C20,4.9391 19.5786,3.9215 18.8284,3.1714C18.0783,2.4212 17.0609,2 16,2ZM8.93,8.5278C8.9561,8.4957 8.9922,8.4736 9.0325,8.4644C9.0729,8.4551 9.1151,8.4591 9.1526,8.4766C9.1902,8.494 9.2208,8.5237 9.2397,8.5605C9.2586,8.5974 9.2647,8.6395 9.257,8.6802C9.1893,9.0625 9.1998,9.4544 9.2878,9.8325C9.3758,10.2106 9.5395,10.5668 9.769,10.8799C9.969,11.1669 10.203,11.0499 10.213,11.0459C10.2694,11.0204 10.3173,10.9792 10.351,10.9272C10.3847,10.8753 10.4027,10.8148 10.403,10.7529C10.403,10.6899 8.894,6.6532 12.651,5.0132C12.6848,4.9985 12.7223,4.994 12.7586,5.0005C12.7949,5.007 12.8285,5.0238 12.8551,5.0493C12.8817,5.0749 12.9002,5.108 12.9082,5.144C12.9162,5.1801 12.9133,5.2175 12.9,5.2519C12.741,5.7272 12.7178,6.2374 12.8332,6.7251C12.9486,7.2127 13.1979,7.6586 13.553,8.0122C13.909,8.3682 14.338,8.6121 14.704,8.9541C17.187,11.2821 15.604,15.4861 11.422,14.9541C10.7376,14.8371 10.0952,14.5448 9.5576,14.1055C9.0199,13.6662 8.6053,13.0946 8.3543,12.4473C8.1033,11.7999 8.0244,11.0986 8.1252,10.4116C8.2261,9.7247 8.5034,9.0756 8.93,8.5278ZM18,20H6V16C6.7396,15.9897 7.4619,16.2246 8.054,16.668C8.3188,16.8888 8.6527,17.0098 8.9975,17.0098C9.3423,17.0098 9.6762,16.8888 9.941,16.668C10.5357,16.2281 11.2558,15.9907 11.9955,15.9907C12.7352,15.9907 13.4553,16.2281 14.05,16.668C14.3161,16.889 14.6511,17.0103 14.997,17.0103C15.3429,17.0103 15.6779,16.889 15.944,16.668C16.5368,16.2244 17.2597,15.9896 18,16V20Z"
+ android:fillColor="#FF000000" />
+</vector>
diff --git a/packages/SystemUI/res/drawable/ic_device_window_off.xml b/packages/SystemUI/res/drawable/ic_device_window_off.xml
new file mode 100644
index 000000000000..ea4af98d2860
--- /dev/null
+++ b/packages/SystemUI/res/drawable/ic_device_window_off.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="24dp"
+ android:height="24dp"
+ android:viewportWidth="24"
+ android:viewportHeight="24">
+ <path
+ android:pathData="M20,2H4C3.4701,2.0016 2.9623,2.2129 2.5875,2.5877C2.2128,2.9624 2.0016,3.4701 2,4V20C2.0016,20.5299 2.2128,21.0376 2.5875,21.4124C2.9623,21.7871 3.4701,21.9984 4,22H20C20.5299,21.9984 21.0377,21.7871 21.4125,21.4124C21.7872,21.0376 21.9984,20.5299 22,20V4C21.9984,3.4701 21.7872,2.9624 21.4125,2.5877C21.0377,2.2129 20.5299,2.0016 20,2ZM20,11H13V4H20V11ZM11,4V11H4V4H11ZM4,13H11V20H4V13ZM13,20V13H20V20H13Z"
+ android:fillColor="#FF000000" />
+</vector>
diff --git a/packages/SystemUI/res/drawable/ic_device_window_on.xml b/packages/SystemUI/res/drawable/ic_device_window_on.xml
new file mode 100644
index 000000000000..ea4af98d2860
--- /dev/null
+++ b/packages/SystemUI/res/drawable/ic_device_window_on.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="24dp"
+ android:height="24dp"
+ android:viewportWidth="24"
+ android:viewportHeight="24">
+ <path
+ android:pathData="M20,2H4C3.4701,2.0016 2.9623,2.2129 2.5875,2.5877C2.2128,2.9624 2.0016,3.4701 2,4V20C2.0016,20.5299 2.2128,21.0376 2.5875,21.4124C2.9623,21.7871 3.4701,21.9984 4,22H20C20.5299,21.9984 21.0377,21.7871 21.4125,21.4124C21.7872,21.0376 21.9984,20.5299 22,20V4C21.9984,3.4701 21.7872,2.9624 21.4125,2.5877C21.0377,2.2129 20.5299,2.0016 20,2ZM20,11H13V4H20V11ZM11,4V11H4V4H11ZM4,13H11V20H4V13ZM13,20V13H20V20H13Z"
+ android:fillColor="#FF000000" />
+</vector>
diff --git a/packages/SystemUI/res/drawable/ic_light_off_gm2_24px.xml b/packages/SystemUI/res/drawable/ic_light_off_gm2_24px.xml
deleted file mode 100644
index 78c3cc54f022..000000000000
--- a/packages/SystemUI/res/drawable/ic_light_off_gm2_24px.xml
+++ /dev/null
@@ -1,19 +0,0 @@
-<vector xmlns:android="http://schemas.android.com/apk/res/android"
- android:width="24dp"
- android:height="24dp"
- android:viewportWidth="24"
- android:viewportHeight="24">
- <path
- android:fillColor="#FF000000"
- android:pathData="M9,21v-1h6v1c0,0.55 -0.45,1 -1,1h-4c-0.55,0 -1,-0.45 -1,-1z"/>
- <group>
- <clip-path android:pathData="M0,0h24v24H0z M 0,0"/>
- </group>
- <path
- android:fillColor="#FF000000"
- android:pathData="M12,2c-1.89,0 -3.6,0.75 -4.86,1.97l1.41,1.41C9.45,4.53 10.67,4 12,4c2.76,0 5,2.24 5,5 0,1.28 -0.5,2.5 -1.36,3.42l-0.02,0.02 1.41,1.41C18.25,12.6 19,10.89 19,9c0,-3.86 -3.14,-7 -7,-7z"
- android:fillType="evenOdd"/>
- <path
- android:fillColor="#FF000000"
- android:pathData="M2.92,2.29L1.65,3.57l3.59,3.59C5.09,7.75 5,8.36 5,9c0,2.38 1.19,4.47 3,5.74V17c0,0.55 0.45,1 1,1h6c0.3,0 0.57,-0.13 0.75,-0.34L20.09,22l1.27,-1.27L2.92,2.29zM10,16v-2.3l-0.85,-0.6C7.8,12.16 7,10.63 7,9v-0.08L14.09,16H10z"/>
-</vector>
diff --git a/packages/SystemUI/res/drawable/ic_lightbulb_outline_gm2_24px.xml b/packages/SystemUI/res/drawable/ic_lightbulb_outline_gm2_24px.xml
deleted file mode 100644
index 87684a32e016..000000000000
--- a/packages/SystemUI/res/drawable/ic_lightbulb_outline_gm2_24px.xml
+++ /dev/null
@@ -1,9 +0,0 @@
-<vector xmlns:android="http://schemas.android.com/apk/res/android"
- android:width="24dp"
- android:height="24dp"
- android:viewportWidth="24"
- android:viewportHeight="24">
- <path
- android:fillColor="#FF000000"
- android:pathData="M9,21c0,0.55 0.45,1 1,1h4c0.55,0 1,-0.45 1,-1v-1L9,20v1zM12,2C8.14,2 5,5.14 5,9c0,2.38 1.19,4.47 3,5.74L8,17c0,0.55 0.45,1 1,1h6c0.55,0 1,-0.45 1,-1v-2.26c1.81,-1.27 3,-3.36 3,-5.74 0,-3.86 -3.14,-7 -7,-7zM14.85,13.1l-0.85,0.6L14,16h-4v-2.3l-0.85,-0.6C7.8,12.16 7,10.63 7,9c0,-2.76 2.24,-5 5,-5s5,2.24 5,5c0,1.63 -0.8,3.16 -2.15,4.1z"/>
-</vector>
diff --git a/packages/SystemUI/res/drawable/ic_lock_gm2_24px.xml b/packages/SystemUI/res/drawable/ic_lock_gm2_24px.xml
deleted file mode 100644
index f4299e6cda11..000000000000
--- a/packages/SystemUI/res/drawable/ic_lock_gm2_24px.xml
+++ /dev/null
@@ -1,9 +0,0 @@
-<vector xmlns:android="http://schemas.android.com/apk/res/android"
- android:width="24dp"
- android:height="24dp"
- android:viewportWidth="24"
- android:viewportHeight="24">
- <path
- android:fillColor="#FF000000"
- android:pathData="M18,8h-1L17,6c0,-2.76 -2.24,-5 -5,-5S7,3.24 7,6v2L6,8c-1.1,0 -2,0.9 -2,2v10c0,1.1 0.9,2 2,2h12c1.1,0 2,-0.9 2,-2L20,10c0,-1.1 -0.9,-2 -2,-2zM9,6c0,-1.66 1.34,-3 3,-3s3,1.34 3,3v2L9,8L9,6zM18,20L6,20L6,10h12v10zM12,17c1.1,0 2,-0.9 2,-2s-0.9,-2 -2,-2 -2,0.9 -2,2 0.9,2 2,2z"/>
-</vector>
diff --git a/packages/SystemUI/res/drawable/ic_lock_open_gm2_24px.xml b/packages/SystemUI/res/drawable/ic_lock_open_gm2_24px.xml
deleted file mode 100644
index 59fe0a914656..000000000000
--- a/packages/SystemUI/res/drawable/ic_lock_open_gm2_24px.xml
+++ /dev/null
@@ -1,12 +0,0 @@
-<vector xmlns:android="http://schemas.android.com/apk/res/android"
- android:width="24dp"
- android:height="24dp"
- android:viewportWidth="24"
- android:viewportHeight="24">
- <path
- android:fillColor="#FF000000"
- android:pathData="M18,8h-1L17,6c0,-2.76 -2.24,-5 -5,-5S7,3.24 7,6h2c0,-1.66 1.34,-3 3,-3s3,1.34 3,3v2L6,8c-1.1,0 -2,0.9 -2,2v10c0,1.1 0.9,2 2,2h12c1.1,0 2,-0.9 2,-2L20,10c0,-1.1 -0.9,-2 -2,-2zM18,20L6,20L6,10h12v10z"/>
- <path
- android:fillColor="#FF000000"
- android:pathData="M12,15m-2,0a2,2 0,1 1,4 0a2,2 0,1 1,-4 0"/>
-</vector>
diff --git a/packages/SystemUI/res/drawable/ic_power_gm2_24px.xml b/packages/SystemUI/res/drawable/ic_power_gm2_24px.xml
deleted file mode 100644
index cd957196e4dc..000000000000
--- a/packages/SystemUI/res/drawable/ic_power_gm2_24px.xml
+++ /dev/null
@@ -1,9 +0,0 @@
-<vector xmlns:android="http://schemas.android.com/apk/res/android"
- android:width="24dp"
- android:height="24dp"
- android:viewportWidth="24"
- android:viewportHeight="24">
- <path
- android:fillColor="#FF000000"
- android:pathData="M16,9v4.66l-3.5,3.51V19h-1v-1.83L8,13.65V9h8m0,-6h-2v4h-4V3H8v4h-0.01C6.9,6.99 6,7.89 6,8.98v5.52L9.5,18v3h5v-3l3.5,-3.51V9c0,-1.1 -0.9,-2 -2,-2V3z"/>
-</vector>
diff --git a/packages/SystemUI/res/drawable/ic_power_off_gm2_24px.xml b/packages/SystemUI/res/drawable/ic_power_off_gm2_24px.xml
deleted file mode 100644
index 3eb7dd637abe..000000000000
--- a/packages/SystemUI/res/drawable/ic_power_off_gm2_24px.xml
+++ /dev/null
@@ -1,9 +0,0 @@
-<vector xmlns:android="http://schemas.android.com/apk/res/android"
- android:width="24dp"
- android:height="24dp"
- android:viewportWidth="24"
- android:viewportHeight="24">
- <path
- android:fillColor="#FF000000"
- android:pathData="M21.19,21.19L2.81,2.81 1.39,4.22l4.63,4.63L6,14.5 9.5,18v3h5v-3l0.34,-0.34 4.94,4.94 1.41,-1.41zM12.5,17.17L12.5,19h-1v-1.83L8,13.65v-2.83l5.42,5.42 -0.92,0.93zM11.83,9L8,5.17L8,3h2v4h4L14,3h2v4c1.1,0 2,0.9 2,2v5.49l-0.34,0.34L16,13.17L16,9h-4.17z"/>
-</vector>
diff --git a/packages/SystemUI/res/drawable/ic_switches_gm2_24px.xml b/packages/SystemUI/res/drawable/ic_switches_gm2_24px.xml
deleted file mode 100644
index bb535ceaed8c..000000000000
--- a/packages/SystemUI/res/drawable/ic_switches_gm2_24px.xml
+++ /dev/null
@@ -1,9 +0,0 @@
-<vector xmlns:android="http://schemas.android.com/apk/res/android"
- android:width="24dp"
- android:height="24dp"
- android:viewportWidth="24"
- android:viewportHeight="24">
- <path
- android:fillColor="#FF000000"
- android:pathData="M19,9h-8.02C10.06,7.79 8.63,7 7,7c-2.76,0 -5,2.24 -5,5s2.24,5 5,5c1.63,0 3.06,-0.79 3.98,-2H19c1.66,0 3,-1.34 3,-3S20.66,9 19,9zM19,13h-7.1c0.07,-0.32 0.1,-0.66 0.1,-1s-0.04,-0.68 -0.1,-1H19c0.55,0 1,0.45 1,1S19.55,13 19,13z"/>
-</vector>
diff --git a/packages/SystemUI/res/drawable/ic_vacuum_gm2_24px.xml b/packages/SystemUI/res/drawable/ic_vacuum_gm2_24px.xml
deleted file mode 100644
index 86b9591238f1..000000000000
--- a/packages/SystemUI/res/drawable/ic_vacuum_gm2_24px.xml
+++ /dev/null
@@ -1,9 +0,0 @@
-<vector xmlns:android="http://schemas.android.com/apk/res/android"
- android:width="24dp"
- android:height="24dp"
- android:viewportWidth="24"
- android:viewportHeight="24">
- <path
- android:fillColor="#FF000000"
- android:pathData="M4,16c-1.66,0 -3,1.34 -3,3s1.34,3 3,3 3,-1.34 3,-3 -1.34,-3 -3,-3zM4,20c-0.55,0 -1,-0.45 -1,-1s0.45,-1 1,-1 1,0.45 1,1 -0.45,1 -1,1zM23,20v2h-7v-2h2.49L12.01,4.59C11.6,3.63 10.66,3 9.61,3 8.17,3 7,4.17 7,5.61L7,9h2c2.21,0 4,1.79 4,4v9L7.99,22c0.44,-0.58 0.76,-1.26 0.91,-2L11,20v-7c0,-1.1 -0.9,-2 -2,-2L4,11v3c-0.71,0 -1.39,0.15 -2,0.42L2,9h3L5,5.61C5,3.07 7.07,1 9.61,1c1.86,0 3.53,1.11 4.25,2.82L20.66,20L23,20z"/>
-</vector>
diff --git a/packages/SystemUI/res/drawable/ic_videocam_gm2_24px.xml b/packages/SystemUI/res/drawable/ic_videocam_gm2_24px.xml
deleted file mode 100644
index 687c9c417fa6..000000000000
--- a/packages/SystemUI/res/drawable/ic_videocam_gm2_24px.xml
+++ /dev/null
@@ -1,9 +0,0 @@
-<vector xmlns:android="http://schemas.android.com/apk/res/android"
- android:width="24dp"
- android:height="24dp"
- android:viewportWidth="24"
- android:viewportHeight="24">
- <path
- android:fillColor="#FF000000"
- android:pathData="M18,10.48L18,6c0,-1.1 -0.9,-2 -2,-2L4,4c-1.1,0 -2,0.9 -2,2v12c0,1.1 0.9,2 2,2h12c1.1,0 2,-0.9 2,-2v-4.48l4,3.98v-11l-4,3.98zM16,9.69L16,18L4,18L4,6h12v3.69z"/>
-</vector>
diff --git a/packages/SystemUI/res/layout-land/auth_credential_pattern_view.xml b/packages/SystemUI/res/layout-land/auth_credential_pattern_view.xml
index e791c8aea97e..19a85fec1397 100644
--- a/packages/SystemUI/res/layout-land/auth_credential_pattern_view.xml
+++ b/packages/SystemUI/res/layout-land/auth_credential_pattern_view.xml
@@ -48,11 +48,7 @@
android:id="@+id/subtitle"
android:layout_width="match_parent"
android:layout_height="wrap_content"
- android:layout_marginHorizontal="24dp"
- android:layout_marginTop="8dp"
- android:textSize="16sp"
- android:gravity="center"
- android:textColor="?android:attr/textColorPrimary"/>
+ style="@style/TextAppearance.AuthCredential.Subtitle"/>
<TextView
android:id="@+id/description"
@@ -69,10 +65,7 @@
android:id="@+id/error"
android:layout_width="match_parent"
android:layout_height="wrap_content"
- android:layout_marginHorizontal="24dp"
- android:textSize="16sp"
- android:gravity="center"
- android:textColor="?android:attr/colorError"/>
+ style="@style/TextAppearance.AuthCredential.Error"/>
<Space
android:layout_width="0dp"
diff --git a/packages/SystemUI/res/layout/auth_biometric_contents.xml b/packages/SystemUI/res/layout/auth_biometric_contents.xml
index a1006a8396e0..6b61046e0f6c 100644
--- a/packages/SystemUI/res/layout/auth_biometric_contents.xml
+++ b/packages/SystemUI/res/layout/auth_biometric_contents.xml
@@ -18,34 +18,24 @@
<TextView
android:id="@+id/title"
- android:fontFamily="@*android:string/config_headlineFontFamilyMedium"
android:layout_width="match_parent"
android:layout_height="wrap_content"
- android:paddingHorizontal="24dp"
- android:paddingTop="24dp"
android:gravity="@integer/biometric_dialog_text_gravity"
- android:textSize="20sp"
- android:textColor="?android:attr/textColorPrimary"/>
+ style="@style/TextAppearance.AuthCredential.Title"/>
<TextView
android:id="@+id/subtitle"
android:layout_width="match_parent"
android:layout_height="wrap_content"
- android:paddingTop="8dp"
- android:paddingHorizontal="24dp"
android:gravity="@integer/biometric_dialog_text_gravity"
- android:textSize="16sp"
- android:textColor="?android:attr/textColorPrimary"/>
+ style="@style/TextAppearance.AuthCredential.Subtitle"/>
<TextView
android:id="@+id/description"
android:layout_width="match_parent"
android:layout_height="wrap_content"
- android:paddingHorizontal="24dp"
- android:paddingTop="8dp"
android:gravity="@integer/biometric_dialog_text_gravity"
- android:textSize="16sp"
- android:textColor="?android:attr/textColorPrimary"/>
+ style="@style/TextAppearance.AuthCredential.Description"/>
<ImageView
android:id="@+id/biometric_icon"
diff --git a/packages/SystemUI/res/layout/auth_credential_password_view.xml b/packages/SystemUI/res/layout/auth_credential_password_view.xml
index b14bc7de06c4..45638ce5e744 100644
--- a/packages/SystemUI/res/layout/auth_credential_password_view.xml
+++ b/packages/SystemUI/res/layout/auth_credential_password_view.xml
@@ -42,11 +42,7 @@
android:id="@+id/subtitle"
android:layout_width="match_parent"
android:layout_height="wrap_content"
- android:layout_marginHorizontal="24dp"
- android:layout_marginTop="8dp"
- android:textSize="16sp"
- android:gravity="center"
- android:textColor="?android:attr/textColorPrimary"/>
+ style="@style/TextAppearance.AuthCredential.Subtitle"/>
<TextView
android:id="@+id/description"
@@ -59,15 +55,6 @@
android:layout_height="0dp"
android:layout_weight="1"/>
- <TextView
- android:id="@+id/error"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:layout_marginHorizontal="24dp"
- android:textSize="16sp"
- android:gravity="center"
- android:textColor="?android:attr/colorError"/>
-
<EditText
android:id="@+id/lockPassword"
android:layout_width="208dp"
@@ -80,6 +67,12 @@
android:imeOptions="actionNext|flagNoFullscreen|flagForceAscii"
style="@style/TextAppearance.AuthCredential.PasswordEntry"/>
+ <TextView
+ android:id="@+id/error"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ style="@style/TextAppearance.AuthCredential.Error"/>
+
<Space
android:layout_width="0dp"
android:layout_height="0dp"
diff --git a/packages/SystemUI/res/layout/auth_credential_pattern_view.xml b/packages/SystemUI/res/layout/auth_credential_pattern_view.xml
index eda5ecbf7f8c..4939ea2c99ee 100644
--- a/packages/SystemUI/res/layout/auth_credential_pattern_view.xml
+++ b/packages/SystemUI/res/layout/auth_credential_pattern_view.xml
@@ -42,11 +42,7 @@
android:id="@+id/subtitle"
android:layout_width="match_parent"
android:layout_height="wrap_content"
- android:layout_marginHorizontal="24dp"
- android:layout_marginTop="8dp"
- android:textSize="16sp"
- android:gravity="center"
- android:textColor="?android:attr/textColorPrimary"/>
+ style="@style/TextAppearance.AuthCredential.Subtitle"/>
<TextView
android:id="@+id/description"
@@ -89,10 +85,7 @@
android:id="@+id/error"
android:layout_width="match_parent"
android:layout_height="wrap_content"
- android:layout_marginHorizontal="24dp"
- android:textSize="16sp"
- android:gravity="center"
- android:textColor="?android:attr/colorError"/>
+ style="@style/TextAppearance.AuthCredential.Error"/>
</LinearLayout>
diff --git a/packages/SystemUI/res/layout/controls_base_item.xml b/packages/SystemUI/res/layout/controls_base_item.xml
index 6e1fd2072b32..b83e500fbaeb 100644
--- a/packages/SystemUI/res/layout/controls_base_item.xml
+++ b/packages/SystemUI/res/layout/controls_base_item.xml
@@ -50,6 +50,7 @@
app:layout_constraintBottom_toBottomOf="@+id/icon"
app:layout_constraintStart_toEndOf="@+id/icon" />
+
<TextView
android:id="@+id/status_extra"
android:layout_width="wrap_content"
@@ -64,7 +65,7 @@
<TextView
android:id="@+id/title"
- android:layout_width="wrap_content"
+ android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textAppearance="@style/TextAppearance.Control.Title"
android:paddingLeft="@dimen/control_padding_adjustment"
@@ -73,12 +74,20 @@
android:focusable="false"
android:maxLines="1"
android:ellipsize="end"
- app:layout_constraintBottom_toTopOf="@+id/subtitle"
- app:layout_constraintStart_toStartOf="parent" />
+ app:layout_constraintStart_toStartOf="parent"
+ app:layout_constraintEnd_toEndOf="parent"
+ app:layout_constraintBottom_toTopOf="@id/barrier"/>
+
+ <androidx.constraintlayout.widget.Barrier
+ android:id="@+id/barrier"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ app:barrierDirection="top"
+ app:constraint_referenced_ids="subtitle,favorite" />
<TextView
android:id="@+id/subtitle"
- android:layout_width="wrap_content"
+ android:layout_width="0dp"
android:layout_height="wrap_content"
android:textAppearance="@style/TextAppearance.Control.Subtitle"
android:paddingLeft="@dimen/control_padding_adjustment"
@@ -88,24 +97,22 @@
android:focusable="false"
android:maxLines="1"
android:ellipsize="end"
+ app:layout_constraintStart_toStartOf="parent"
+ app:layout_constraintEnd_toStartOf="@id/favorite"
app:layout_constraintBottom_toBottomOf="parent"
- app:layout_constraintStart_toStartOf="parent"/>
+ />
- <FrameLayout
- android:id="@+id/favorite_container"
+ <CheckBox
+ android:id="@+id/favorite"
android:visibility="gone"
- android:layout_width="48dp"
- android:layout_height="48dp"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_gravity="bottom|end"
+ android:button="@drawable/controls_btn_star"
+ android:layout_marginTop="4dp"
+ android:layout_marginStart="4dp"
+ app:layout_constraintStart_toEndOf="@id/subtitle"
app:layout_constraintEnd_toEndOf="parent"
- app:layout_constraintBottom_toBottomOf="parent">
-
- <CheckBox
- android:id="@+id/favorite"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_gravity="bottom|end"
- android:button="@drawable/controls_btn_star"/>
- </FrameLayout>
-
+ app:layout_constraintBottom_toBottomOf="parent"/>
</androidx.constraintlayout.widget.ConstraintLayout>
diff --git a/packages/SystemUI/res/values-television/dimens.xml b/packages/SystemUI/res/values-television/dimens.xml
new file mode 100644
index 000000000000..6da0c693f389
--- /dev/null
+++ b/packages/SystemUI/res/values-television/dimens.xml
@@ -0,0 +1,20 @@
+<?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>
+ <!-- Opacity at which the background for the shutdown UI will be drawn. -->
+ <item name="shutdown_scrim_behind_alpha" format="float" type="dimen">1.0</item>
+</resources> \ No newline at end of file
diff --git a/packages/SystemUI/res/values-television/styles.xml b/packages/SystemUI/res/values-television/styles.xml
index b59f0072b8c3..b01c5d88e3b3 100644
--- a/packages/SystemUI/res/values-television/styles.xml
+++ b/packages/SystemUI/res/values-television/styles.xml
@@ -17,4 +17,9 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android">
<style name="Theme.SystemUI.Dialog" parent="@android:style/Theme.DeviceDefault.Dialog" />
<style name="Theme.SystemUI.Dialog.Alert" parent="@*android:style/Theme.DeviceDefault.Dialog.Alert" />
+
+ <style name="Animation.ShutdownUi">
+ <item name="android:windowEnterAnimation">@null</item>
+ <item name="android:windowExitAnimation">@null</item>
+ </style>
</resources>
diff --git a/packages/SystemUI/res/values/dimens.xml b/packages/SystemUI/res/values/dimens.xml
index ee7f5230145e..864442ecd0c5 100644
--- a/packages/SystemUI/res/values/dimens.xml
+++ b/packages/SystemUI/res/values/dimens.xml
@@ -1266,4 +1266,7 @@
<dimen name="screenrecord_status_icon_radius">5dp</dimen>
<dimen name="kg_user_switcher_text_size">16sp</dimen>
+
+ <!-- Opacity at which the background for the shutdown UI will be drawn. -->
+ <item name="shutdown_scrim_behind_alpha" format="float" type="dimen">0.95</item>
</resources>
diff --git a/packages/SystemUI/res/values/strings.xml b/packages/SystemUI/res/values/strings.xml
index 8a3a16e9a6cf..b779130afc93 100644
--- a/packages/SystemUI/res/values/strings.xml
+++ b/packages/SystemUI/res/values/strings.xml
@@ -2687,9 +2687,9 @@
<!-- Controls management controls screen header for Other zone [CHAR LIMIT=60] -->
<string name="controls_favorite_other_zone_header">Other</string>
- <!-- Controls dialog title [CHAR LIMIT=30] -->
+ <!-- Controls dialog title [CHAR LIMIT=40] -->
<string name="controls_dialog_title">Add to quick controls</string>
- <!-- Controls dialog add to favorites [CHAR LIMIT=30] -->
+ <!-- Controls dialog add to favorites [CHAR LIMIT=40] -->
<string name="controls_dialog_ok">Add to favorites</string>
<!-- Controls dialog message [CHAR LIMIT=NONE] -->
<string name="controls_dialog_message"><xliff:g id="app" example="System UI">%s</xliff:g> suggested this control to add to your favorites.</string>
diff --git a/packages/SystemUI/res/values/styles.xml b/packages/SystemUI/res/values/styles.xml
index 1233d4dc73e7..1598465d6df0 100644
--- a/packages/SystemUI/res/values/styles.xml
+++ b/packages/SystemUI/res/values/styles.xml
@@ -250,28 +250,39 @@
<style name="TextAppearance.AuthCredential">
<item name="android:gravity">center_horizontal</item>
- <item name="android:fontFamily">google-sans</item>
<item name="android:textAlignment">gravity</item>
<item name="android:layout_gravity">top</item>
<item name="android:textColor">?android:attr/textColorPrimary</item>
</style>
<style name="TextAppearance.AuthCredential.Title">
- <item name="android:layout_marginBottom">2dp</item>
- <item name="android:layout_marginLeft">24dp</item>
- <item name="android:layout_marginRight">24dp</item>
- <item name="android:layout_marginTop">16dp</item>
+ <item name="android:fontFamily">google-sans</item>
+ <item name="android:paddingTop">16dp</item>
+ <item name="android:paddingHorizontal">24dp</item>
<item name="android:textSize">24sp</item>
</style>
- <style name="TextAppearance.AuthCredential.Description">
- <item name="android:layout_marginBottom">12dp</item>
- <item name="android:layout_marginStart">40dp</item>
- <item name="android:layout_marginEnd">40dp</item>
- <item name="android:layout_marginTop">3dp</item>
+ <style name="TextAppearance.AuthCredential.Subtitle">
+ <item name="android:fontFamily">google-sans</item>
+ <item name="android:paddingTop">8dp</item>
+ <item name="android:paddingHorizontal">24dp</item>
<item name="android:textSize">16sp</item>
</style>
+ <style name="TextAppearance.AuthCredential.Description">
+ <item name="android:fontFamily">google-sans</item>
+ <item name="android:paddingTop">8dp</item>
+ <item name="android:paddingHorizontal">24dp</item>
+ <item name="android:textSize">14sp</item>
+ </style>
+
+ <style name="TextAppearance.AuthCredential.Error">
+ <item name="android:paddingTop">12dp</item>
+ <item name="android:paddingHorizontal">24dp</item>
+ <item name="android:textSize">14sp</item>
+ <item name="android:textColor">?android:attr/colorError</item>
+ </style>
+
<style name="TextAppearance.AuthCredential.PasswordEntry" parent="@android:style/TextAppearance.DeviceDefault">
<item name="android:gravity">center</item>
<item name="android:singleLine">true</item>
@@ -305,6 +316,9 @@
<item name="android:windowExitAnimation">@null</item>
</style>
+ <style name="Animation.ShutdownUi" parent="@android:style/Animation.Toast">
+ </style>
+
<!-- Standard animations for hiding and showing the status bar. -->
<style name="Animation.StatusBar">
</style>
diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/system/ActivityManagerWrapper.java b/packages/SystemUI/shared/src/com/android/systemui/shared/system/ActivityManagerWrapper.java
index 49e3e5724988..3bda3c8df699 100644
--- a/packages/SystemUI/shared/src/com/android/systemui/shared/system/ActivityManagerWrapper.java
+++ b/packages/SystemUI/shared/src/com/android/systemui/shared/system/ActivityManagerWrapper.java
@@ -20,9 +20,7 @@ import static android.app.ActivityManager.LOCK_TASK_MODE_LOCKED;
import static android.app.ActivityManager.LOCK_TASK_MODE_NONE;
import static android.app.ActivityManager.LOCK_TASK_MODE_PINNED;
import static android.app.ActivityManager.RECENT_IGNORE_UNAVAILABLE;
-import static android.app.WindowConfiguration.ACTIVITY_TYPE_RECENTS;
import static android.app.WindowConfiguration.ACTIVITY_TYPE_UNDEFINED;
-import static android.app.WindowConfiguration.WINDOWING_MODE_PINNED;
import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_PRIMARY;
import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_SECONDARY;
import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED;
@@ -38,7 +36,6 @@ import android.app.ActivityTaskManager;
import android.app.AppGlobals;
import android.app.IAssistDataReceiver;
import android.app.WindowConfiguration;
-import android.app.WindowConfiguration.ActivityType;
import android.content.ContentResolver;
import android.content.Context;
import android.content.Intent;
@@ -113,15 +110,18 @@ public class ActivityManagerWrapper {
* @return the top running task (can be {@code null}).
*/
public ActivityManager.RunningTaskInfo getRunningTask() {
- return getRunningTask(ACTIVITY_TYPE_RECENTS /* ignoreActivityType */);
+ return getRunningTask(false /* filterVisibleRecents */);
}
- public ActivityManager.RunningTaskInfo getRunningTask(@ActivityType int ignoreActivityType) {
+ /**
+ * @return the top running task filtering only for tasks that can be visible in the recent tasks
+ * list (can be {@code null}).
+ */
+ public ActivityManager.RunningTaskInfo getRunningTask(boolean filterOnlyVisibleRecents) {
// Note: The set of running tasks from the system is ordered by recency
try {
List<ActivityManager.RunningTaskInfo> tasks =
- ActivityTaskManager.getService().getFilteredTasks(1, ignoreActivityType,
- WINDOWING_MODE_PINNED /* ignoreWindowingMode */);
+ ActivityTaskManager.getService().getFilteredTasks(1, filterOnlyVisibleRecents);
if (tasks.isEmpty()) {
return null;
}
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java b/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java
index 3afe19f926ec..7cbc840afed4 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java
@@ -127,6 +127,7 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab
private static final boolean DEBUG = KeyguardConstants.DEBUG;
private static final boolean DEBUG_SIM_STATES = KeyguardConstants.DEBUG_SIM_STATES;
private static final boolean DEBUG_FACE = true;
+ private static final boolean DEBUG_SPEW = false;
private static final int LOW_BATTERY_THRESHOLD = 20;
private static final String ACTION_FACE_UNLOCK_STARTED
@@ -324,7 +325,8 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab
}
};
- private class BiometricAuthenticated {
+ @VisibleForTesting
+ static class BiometricAuthenticated {
private final boolean mAuthenticated;
private final boolean mIsStrongBiometric;
@@ -338,11 +340,14 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab
private SparseBooleanArray mUserHasTrust = new SparseBooleanArray();
private SparseBooleanArray mUserTrustIsManaged = new SparseBooleanArray();
private SparseBooleanArray mUserTrustIsUsuallyManaged = new SparseBooleanArray();
- private SparseArray<BiometricAuthenticated> mUserFingerprintAuthenticated = new SparseArray<>();
- private SparseArray<BiometricAuthenticated> mUserFaceAuthenticated = new SparseArray<>();
private SparseBooleanArray mUserFaceUnlockRunning = new SparseBooleanArray();
private Map<Integer, Intent> mSecondaryLockscreenRequirement = new HashMap<Integer, Intent>();
+ @VisibleForTesting
+ SparseArray<BiometricAuthenticated> mUserFingerprintAuthenticated = new SparseArray<>();
+ @VisibleForTesting
+ SparseArray<BiometricAuthenticated> mUserFaceAuthenticated = new SparseArray<>();
+
private static int sCurrentUser;
private Runnable mUpdateBiometricListeningState = this::updateBiometricListeningState;
@@ -1850,11 +1855,33 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab
// Only listen if this KeyguardUpdateMonitor belongs to the primary user. There is an
// instance of KeyguardUpdateMonitor for each user but KeyguardUpdateMonitor is user-aware.
- return (mBouncer || mAuthInterruptActive || awakeKeyguard || shouldListenForFaceAssistant())
+ final boolean shouldListen =
+ (mBouncer || mAuthInterruptActive || awakeKeyguard
+ || shouldListenForFaceAssistant())
&& !mSwitchingUser && !isFaceDisabled(user) && becauseCannotSkipBouncer
&& !mKeyguardGoingAway && mFaceSettingEnabledForUser.get(user) && !mLockIconPressed
&& strongAuthAllowsScanning && mIsPrimaryUser
&& !mSecureCameraLaunched;
+
+ // Too chatty, but very useful when debugging issues.
+ if (DEBUG_SPEW) {
+ Log.v(TAG, "shouldListenForFace(" + user + ")=" + shouldListen + "... "
+ + ", mBouncer: " + mBouncer
+ + ", mAuthInterruptActive: " + mAuthInterruptActive
+ + ", awakeKeyguard: " + awakeKeyguard
+ + ", shouldListenForFaceAssistant: " + shouldListenForFaceAssistant()
+ + ", mSwitchingUser: " + mSwitchingUser
+ + ", isFaceDisabled(" + user + "): " + isFaceDisabled(user)
+ + ", becauseCannotSkipBouncer: " + becauseCannotSkipBouncer
+ + ", mKeyguardGoingAway: " + mKeyguardGoingAway
+ + ", mFaceSettingEnabledForUser(" + user + "): "
+ + mFaceSettingEnabledForUser.get(user)
+ + ", mLockIconPressed: " + mLockIconPressed
+ + ", strongAuthAllowsScanning: " + strongAuthAllowsScanning
+ + ", isPrimaryUser: " + mIsPrimaryUser
+ + ", mSecureCameraLaunched: " + mSecureCameraLaunched);
+ }
+ return shouldListen;
}
/**
@@ -2049,8 +2076,10 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab
/**
* Handle {@link #MSG_USER_SWITCHING}
*/
- private void handleUserSwitching(int userId, IRemoteCallback reply) {
+ @VisibleForTesting
+ void handleUserSwitching(int userId, IRemoteCallback reply) {
Assert.isMainThread();
+ clearBiometricRecognized();
mUserTrustIsUsuallyManaged.put(userId, mTrustManager.isTrustUsuallyManaged(userId));
for (int i = 0; i < mCallbacks.size(); i++) {
KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get();
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/AuthContainerView.java b/packages/SystemUI/src/com/android/systemui/biometrics/AuthContainerView.java
index 0018d33bdacb..b736b4df8abf 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/AuthContainerView.java
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/AuthContainerView.java
@@ -22,6 +22,7 @@ import android.annotation.Nullable;
import android.content.Context;
import android.graphics.PixelFormat;
import android.hardware.biometrics.BiometricAuthenticator;
+import android.hardware.biometrics.BiometricConstants;
import android.os.Binder;
import android.os.Bundle;
import android.os.Handler;
@@ -207,6 +208,7 @@ public class AuthContainerView extends LinearLayout
animateAway(AuthDialogCallback.DISMISSED_BIOMETRIC_AUTHENTICATED);
break;
case AuthBiometricView.Callback.ACTION_USER_CANCELED:
+ sendEarlyUserCanceled();
animateAway(AuthDialogCallback.DISMISSED_USER_CANCELED);
break;
case AuthBiometricView.Callback.ACTION_BUTTON_NEGATIVE:
@@ -286,11 +288,13 @@ public class AuthContainerView extends LinearLayout
addView(mFrameLayout);
+ // TODO: De-dupe the logic with AuthCredentialPasswordView
setOnKeyListener((v, keyCode, event) -> {
if (keyCode != KeyEvent.KEYCODE_BACK) {
return false;
}
if (event.getAction() == KeyEvent.ACTION_UP) {
+ sendEarlyUserCanceled();
animateAway(AuthDialogCallback.DISMISSED_USER_CANCELED);
}
return true;
@@ -300,6 +304,11 @@ public class AuthContainerView extends LinearLayout
requestFocus();
}
+ void sendEarlyUserCanceled() {
+ mConfig.mCallback.onSystemEvent(
+ BiometricConstants.BIOMETRIC_SYSTEM_EVENT_EARLY_USER_CANCEL);
+ }
+
@Override
public boolean isAllowDeviceCredentials() {
return Utils.isDeviceCredentialAllowed(mConfig.mBiometricPromptBundle);
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/AuthController.java b/packages/SystemUI/src/com/android/systemui/biometrics/AuthController.java
index c30477c77bbb..0c6794c2ab85 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/AuthController.java
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/AuthController.java
@@ -165,6 +165,19 @@ public class AuthController extends SystemUI implements CommandQueue.Callbacks,
}
@Override
+ public void onSystemEvent(int event) {
+ if (mReceiver == null) {
+ Log.e(TAG, "onSystemEvent(" + event + "): Receiver is null");
+ return;
+ }
+ try {
+ mReceiver.onSystemEvent(event);
+ } catch (RemoteException e) {
+ Log.e(TAG, "RemoteException when sending system event", e);
+ }
+ }
+
+ @Override
public void onDismissed(@DismissedReason int reason, @Nullable byte[] credentialAttestation) {
switch (reason) {
case AuthDialogCallback.DISMISSED_USER_CANCELED:
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/AuthCredentialPasswordView.java b/packages/SystemUI/src/com/android/systemui/biometrics/AuthCredentialPasswordView.java
index b986f6c9e680..d8a11d36a335 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/AuthCredentialPasswordView.java
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/AuthCredentialPasswordView.java
@@ -51,11 +51,13 @@ public class AuthCredentialPasswordView extends AuthCredentialView
super.onFinishInflate();
mPasswordField = findViewById(R.id.lockPassword);
mPasswordField.setOnEditorActionListener(this);
+ // TODO: De-dupe the logic with AuthContainerView
mPasswordField.setOnKeyListener((v, keyCode, event) -> {
if (keyCode != KeyEvent.KEYCODE_BACK) {
return false;
}
if (event.getAction() == KeyEvent.ACTION_UP) {
+ mContainerView.sendEarlyUserCanceled();
mContainerView.animateAway(AuthDialogCallback.DISMISSED_USER_CANCELED);
}
return true;
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/AuthDialogCallback.java b/packages/SystemUI/src/com/android/systemui/biometrics/AuthDialogCallback.java
index a47621d12122..d3bd4fbd921c 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/AuthDialogCallback.java
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/AuthDialogCallback.java
@@ -58,4 +58,11 @@ public interface AuthDialogCallback {
* Invoked when the "use password" button is clicked
*/
void onDeviceCredentialPressed();
+
+ /**
+ * See {@link android.hardware.biometrics.BiometricPrompt.Builder
+ * #setReceiveSystemEvents(boolean)}
+ * @param event
+ */
+ void onSystemEvent(int event);
}
diff --git a/packages/SystemUI/src/com/android/systemui/bubbles/BadgedImageView.java b/packages/SystemUI/src/com/android/systemui/bubbles/BadgedImageView.java
index a1cb7f61ad04..55be77ca3be5 100644
--- a/packages/SystemUI/src/com/android/systemui/bubbles/BadgedImageView.java
+++ b/packages/SystemUI/src/com/android/systemui/bubbles/BadgedImageView.java
@@ -28,6 +28,8 @@ import com.android.launcher3.icons.DotRenderer;
import com.android.systemui.Interpolators;
import com.android.systemui.R;
+import java.util.EnumSet;
+
/**
* View that displays an adaptive icon with an app-badge and a dot.
*
@@ -42,12 +44,27 @@ public class BadgedImageView extends ImageView {
/** Same as value in Launcher3 IconShape */
public static final int DEFAULT_PATH_SIZE = 100;
- static final int DOT_STATE_DEFAULT = 0;
- static final int DOT_STATE_SUPPRESSED_FOR_FLYOUT = 1;
- static final int DOT_STATE_ANIMATING = 2;
+ /**
+ * Flags that suppress the visibility of the 'new' dot, for one reason or another. If any of
+ * these flags are set, the dot will not be shown even if {@link Bubble#showDot()} returns true.
+ */
+ enum SuppressionFlag {
+ // Suppressed because the flyout is visible - it will morph into the dot via animation.
+ FLYOUT_VISIBLE,
+ // Suppressed because this bubble is behind others in the collapsed stack.
+ BEHIND_STACK,
+ }
+
+ /**
+ * Start by suppressing the dot because the flyout is visible - most bubbles are added with a
+ * flyout, so this is a reasonable default.
+ */
+ private final EnumSet<SuppressionFlag> mDotSuppressionFlags =
+ EnumSet.of(SuppressionFlag.FLYOUT_VISIBLE);
- // Flyout gets shown before the dot
- private int mCurrentDotState = DOT_STATE_SUPPRESSED_FOR_FLYOUT;
+ private float mDotScale = 0f;
+ private float mAnimatingToDotScale = 0f;
+ private boolean mDotIsAnimating = false;
private BubbleViewProvider mBubble;
@@ -57,8 +74,6 @@ public class BadgedImageView extends ImageView {
private boolean mOnLeft;
private int mDotColor;
- private float mDotScale = 0f;
- private boolean mDotDrawn;
private Rect mTempBounds = new Rect();
@@ -83,28 +98,28 @@ public class BadgedImageView extends ImageView {
Path iconPath = PathParser.createPathFromPathData(
getResources().getString(com.android.internal.R.string.config_icon_mask));
mDotRenderer = new DotRenderer(mBubbleBitmapSize, iconPath, DEFAULT_PATH_SIZE);
+
+ setFocusable(true);
}
/**
* Updates the view with provided info.
*/
- public void update(BubbleViewProvider bubble) {
+ public void setRenderedBubble(BubbleViewProvider bubble) {
mBubble = bubble;
setImageBitmap(bubble.getBadgedImage());
- setDotState(DOT_STATE_SUPPRESSED_FOR_FLYOUT);
mDotColor = bubble.getDotColor();
drawDot(bubble.getDotPath());
- animateDot();
}
@Override
public void onDraw(Canvas canvas) {
super.onDraw(canvas);
- if (isDotHidden()) {
- mDotDrawn = false;
+
+ if (!shouldDrawDot()) {
return;
}
- mDotDrawn = mDotScale > 0.1f;
+
getDrawingRect(mTempBounds);
mDrawParams.color = mDotColor;
@@ -115,23 +130,33 @@ public class BadgedImageView extends ImageView {
mDotRenderer.draw(canvas, mDrawParams);
}
- /**
- * Sets the dot state, does not animate changes.
- */
- void setDotState(int state) {
- mCurrentDotState = state;
- if (state == DOT_STATE_SUPPRESSED_FOR_FLYOUT || state == DOT_STATE_DEFAULT) {
- mDotScale = mBubble.showDot() ? 1f : 0f;
- invalidate();
+ /** Adds a dot suppression flag, updating dot visibility if needed. */
+ void addDotSuppressionFlag(SuppressionFlag flag) {
+ if (mDotSuppressionFlags.add(flag)) {
+ // Update dot visibility, and animate out if we're now behind the stack.
+ updateDotVisibility(flag == SuppressionFlag.BEHIND_STACK /* animate */);
}
}
- /**
- * Whether the dot should be hidden based on current dot state.
- */
- private boolean isDotHidden() {
- return (mCurrentDotState == DOT_STATE_DEFAULT && !mBubble.showDot())
- || mCurrentDotState == DOT_STATE_SUPPRESSED_FOR_FLYOUT;
+ /** Removes a dot suppression flag, updating dot visibility if needed. */
+ void removeDotSuppressionFlag(SuppressionFlag flag) {
+ if (mDotSuppressionFlags.remove(flag)) {
+ // Update dot visibility, animating if we're no longer behind the stack.
+ updateDotVisibility(flag == SuppressionFlag.BEHIND_STACK);
+ }
+ }
+
+ /** Updates the visibility of the dot, animating if requested. */
+ void updateDotVisibility(boolean animate) {
+ final float targetScale = shouldDrawDot() ? 1f : 0f;
+
+ if (animate) {
+ animateDotScale(targetScale, null /* after */);
+ } else {
+ mDotScale = targetScale;
+ mAnimatingToDotScale = targetScale;
+ invalidate();
+ }
}
/**
@@ -194,11 +219,11 @@ public class BadgedImageView extends ImageView {
}
/** Sets the position of the 'new' dot, animating it out and back in if requested. */
- void setDotPosition(boolean onLeft, boolean animate) {
- if (animate && onLeft != getDotOnLeft() && !isDotHidden()) {
- animateDot(false /* showDot */, () -> {
+ void setDotPositionOnLeft(boolean onLeft, boolean animate) {
+ if (animate && onLeft != getDotOnLeft() && shouldDrawDot()) {
+ animateDotScale(0f /* showDot */, () -> {
setDotOnLeft(onLeft);
- animateDot(true /* showDot */, null);
+ animateDotScale(1.0f, null /* after */);
});
} else {
setDotOnLeft(onLeft);
@@ -209,28 +234,34 @@ public class BadgedImageView extends ImageView {
return getDotOnLeft();
}
- /** Changes the dot's visibility to match the bubble view's state. */
- void animateDot() {
- if (mCurrentDotState == DOT_STATE_DEFAULT) {
- animateDot(mBubble.showDot(), null);
- }
+ /** Whether to draw the dot in onDraw(). */
+ private boolean shouldDrawDot() {
+ // Always render the dot if it's animating, since it could be animating out. Otherwise, show
+ // it if the bubble wants to show it, and we aren't suppressing it.
+ return mDotIsAnimating || (mBubble.showDot() && mDotSuppressionFlags.isEmpty());
}
/**
- * Animates the dot to show or hide.
+ * Animates the dot to the given scale, running the optional callback when the animation ends.
*/
- private void animateDot(boolean showDot, Runnable after) {
- if (mDotDrawn == showDot) {
- // State is consistent, do nothing.
+ private void animateDotScale(float toScale, @Nullable Runnable after) {
+ mDotIsAnimating = true;
+
+ // Don't restart the animation if we're already animating to the given value.
+ if (mAnimatingToDotScale == toScale || !shouldDrawDot()) {
+ mDotIsAnimating = false;
return;
}
- setDotState(DOT_STATE_ANIMATING);
+ mAnimatingToDotScale = toScale;
+
+ final boolean showDot = toScale > 0f;
// Do NOT wait until after animation ends to setShowDot
// to avoid overriding more recent showDot states.
clearAnimation();
- animate().setDuration(200)
+ animate()
+ .setDuration(200)
.setInterpolator(Interpolators.FAST_OUT_SLOW_IN)
.setUpdateListener((valueAnimator) -> {
float fraction = valueAnimator.getAnimatedFraction();
@@ -238,7 +269,7 @@ public class BadgedImageView extends ImageView {
setDotScale(fraction);
}).withEndAction(() -> {
setDotScale(showDot ? 1f : 0f);
- setDotState(DOT_STATE_DEFAULT);
+ mDotIsAnimating = false;
if (after != null) {
after.run();
}
diff --git a/packages/SystemUI/src/com/android/systemui/bubbles/Bubble.java b/packages/SystemUI/src/com/android/systemui/bubbles/Bubble.java
index 726a7dd111d7..71f2bc09b983 100644
--- a/packages/SystemUI/src/com/android/systemui/bubbles/Bubble.java
+++ b/packages/SystemUI/src/com/android/systemui/bubbles/Bubble.java
@@ -76,7 +76,6 @@ class Bubble implements BubbleViewProvider {
private BadgedImageView mIconView;
private BubbleExpandedView mExpandedView;
- private boolean mInflated;
private BubbleViewInfoTask mInflationTask;
private boolean mInflateSynchronously;
@@ -166,10 +165,16 @@ class Bubble implements BubbleViewProvider {
return mExpandedView;
}
- void cleanupExpandedState() {
+ /**
+ * Call when the views should be removed, ensure this is called to clean up ActivityView
+ * content.
+ */
+ void cleanupViews() {
if (mExpandedView != null) {
mExpandedView.cleanUpExpandedState();
+ mExpandedView = null;
}
+ mIconView = null;
}
/**
@@ -213,17 +218,15 @@ class Bubble implements BubbleViewProvider {
}
boolean isInflated() {
- return mInflated;
+ return mIconView != null && mExpandedView != null;
}
void stopInflation() {
if (mInflationTask == null) {
return;
}
- mInflationTask.cancel(/* mayInterruptIfRunning */ true);
- mIconView = null;
- mExpandedView = null;
- mInflated = false;
+ mInflationTask.cancel(true /* mayInterruptIfRunning */);
+ cleanupViews();
}
void setViewInfo(BubbleViewInfoTask.BubbleViewInfo info) {
@@ -240,21 +243,14 @@ class Bubble implements BubbleViewProvider {
mDotColor = info.dotColor;
mDotPath = info.dotPath;
- if (mExpandedView != null && mIconView != null) {
- mInflated = true;
- }
if (mExpandedView != null) {
mExpandedView.update(/* bubble */ this);
}
if (mIconView != null) {
- mIconView.update(/* bubble */ this);
+ mIconView.setRenderedBubble(/* bubble */ this);
}
}
- void setInflated(boolean inflated) {
- mInflated = inflated;
- }
-
/**
* Set visibility of bubble in the expanded state.
*
@@ -306,7 +302,7 @@ class Bubble implements BubbleViewProvider {
void markAsAccessedAt(long lastAccessedMillis) {
mLastAccessed = lastAccessedMillis;
setSuppressNotification(true);
- setShowDot(false /* show */, true /* animate */);
+ setShowDot(false /* show */);
}
/**
@@ -346,12 +342,11 @@ class Bubble implements BubbleViewProvider {
/**
* Sets whether the bubble for this notification should show a dot indicating updated content.
*/
- void setShowDot(boolean showDot, boolean animate) {
+ void setShowDot(boolean showDot) {
mShowBubbleUpdateDot = showDot;
- if (animate && mIconView != null) {
- mIconView.animateDot();
- } else if (mIconView != null) {
- mIconView.invalidate();
+
+ if (mIconView != null) {
+ mIconView.updateDotVisibility(true /* animate */);
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleController.java b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleController.java
index 01c2faa62403..9d885fd3c207 100644
--- a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleController.java
+++ b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleController.java
@@ -331,14 +331,14 @@ public class BubbleController implements ConfigurationController.ConfigurationLi
@Override
public void onZenChanged(int zen) {
for (Bubble b : mBubbleData.getBubbles()) {
- b.setShowDot(b.showInShade(), true /* animate */);
+ b.setShowDot(b.showInShade());
}
}
@Override
public void onConfigChanged(ZenModeConfig config) {
for (Bubble b : mBubbleData.getBubbles()) {
- b.setShowDot(b.showInShade(), true /* animate */);
+ b.setShowDot(b.showInShade());
}
}
});
@@ -1101,7 +1101,7 @@ public class BubbleController implements ConfigurationController.ConfigurationLi
} else if (interceptBubbleDismissal) {
Bubble bubble = mBubbleData.getBubbleWithKey(entry.getKey());
bubble.setSuppressNotification(true);
- bubble.setShowDot(false /* show */, true /* animate */);
+ bubble.setShowDot(false /* show */);
} else {
return false;
}
@@ -1141,7 +1141,7 @@ public class BubbleController implements ConfigurationController.ConfigurationLi
Bubble bubbleChild = mBubbleData.getBubbleWithKey(child.getKey());
mNotificationGroupManager.onEntryRemoved(bubbleChild.getEntry());
bubbleChild.setSuppressNotification(true);
- bubbleChild.setShowDot(false /* show */, true /* animate */);
+ bubbleChild.setShowDot(false /* show */);
} else {
// non-bubbled children can be removed
for (NotifCallback cb : mCallbacks) {
diff --git a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleData.java b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleData.java
index 2bd15188b7d3..1c69594469c1 100644
--- a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleData.java
+++ b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleData.java
@@ -288,7 +288,7 @@ public class BubbleData {
boolean isBubbleExpandedAndSelected = mExpanded && mSelectedBubble == bubble;
boolean suppress = isBubbleExpandedAndSelected || !showInShade || !bubble.showInShade();
bubble.setSuppressNotification(suppress);
- bubble.setShowDot(!isBubbleExpandedAndSelected /* show */, true /* animate */);
+ bubble.setShowDot(!isBubbleExpandedAndSelected /* show */);
dispatchPendingChanges();
}
diff --git a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleOverflow.java b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleOverflow.java
index 4fb2d0881ede..13669a68defa 100644
--- a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleOverflow.java
+++ b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleOverflow.java
@@ -112,7 +112,7 @@ public class BubbleOverflow implements BubbleViewProvider {
mPath.transform(matrix);
mOverflowBtn.setVisibility(GONE);
- mOverflowBtn.update(this);
+ mOverflowBtn.setRenderedBubble(this);
}
ImageView getBtn() {
diff --git a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleOverflowActivity.java b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleOverflowActivity.java
index b65198595095..2231d11b7bc2 100644
--- a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleOverflowActivity.java
+++ b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleOverflowActivity.java
@@ -183,7 +183,7 @@ class BubbleOverflowAdapter extends RecyclerView.Adapter<BubbleOverflowAdapter.V
public void onBindViewHolder(ViewHolder vh, int index) {
Bubble b = mBubbles.get(index);
- vh.iconView.update(b);
+ vh.iconView.setRenderedBubble(b);
vh.iconView.setOnClickListener(view -> {
mBubbles.remove(b);
notifyDataSetChanged();
diff --git a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleStackView.java b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleStackView.java
index 7191a203ea8c..6fd6b8d9f738 100644
--- a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleStackView.java
+++ b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleStackView.java
@@ -22,8 +22,6 @@ import static android.view.ViewGroup.LayoutParams.WRAP_CONTENT;
import static com.android.systemui.Interpolators.FAST_OUT_SLOW_IN;
import static com.android.systemui.Prefs.Key.HAS_SEEN_BUBBLES_EDUCATION;
import static com.android.systemui.Prefs.Key.HAS_SEEN_BUBBLES_MANAGE_EDUCATION;
-import static com.android.systemui.bubbles.BadgedImageView.DOT_STATE_DEFAULT;
-import static com.android.systemui.bubbles.BadgedImageView.DOT_STATE_SUPPRESSED_FOR_FLYOUT;
import static com.android.systemui.bubbles.BubbleDebugConfig.DEBUG_BUBBLE_STACK_VIEW;
import static com.android.systemui.bubbles.BubbleDebugConfig.DEBUG_USER_EDUCATION;
import static com.android.systemui.bubbles.BubbleDebugConfig.TAG_BUBBLES;
@@ -226,7 +224,7 @@ public class BubbleStackView extends FrameLayout {
private boolean mIsExpanded;
/** Whether the stack is currently on the left side of the screen, or animating there. */
- private boolean mStackOnLeftOrWillBe = false;
+ private boolean mStackOnLeftOrWillBe = true;
/** Whether a touch gesture, such as a stack/bubble drag or flyout drag, is in progress. */
private boolean mIsGestureInProgress = false;
@@ -936,9 +934,13 @@ public class BubbleStackView extends FrameLayout {
mStackOnLeftOrWillBe = mStackAnimationController.isStackOnLeftSide();
}
+ if (bubble.getIconView() == null) {
+ return;
+ }
+
// Set the dot position to the opposite of the side the stack is resting on, since the stack
// resting slightly off-screen would result in the dot also being off-screen.
- bubble.getIconView().setDotPosition(
+ bubble.getIconView().setDotPositionOnLeft(
!mStackOnLeftOrWillBe /* onLeft */, false /* animate */);
mBubbleContainer.addView(bubble.getIconView(), 0,
@@ -961,8 +963,7 @@ public class BubbleStackView extends FrameLayout {
if (v instanceof BadgedImageView
&& ((BadgedImageView) v).getKey().equals(bubble.getKey())) {
mBubbleContainer.removeViewAt(i);
- bubble.cleanupExpandedState();
- bubble.setInflated(false);
+ bubble.cleanupViews();
logBubbleEvent(bubble, SysUiStatsLog.BUBBLE_UICHANGED__ACTION__DISMISSED);
return;
}
@@ -1698,7 +1699,7 @@ public class BubbleStackView extends FrameLayout {
|| mBubbleToExpandAfterFlyoutCollapse != null
|| bubbleView == null) {
if (bubbleView != null) {
- bubbleView.setDotState(DOT_STATE_DEFAULT);
+ bubbleView.removeDotSuppressionFlag(BadgedImageView.SuppressionFlag.FLYOUT_VISIBLE);
}
// Skip the message if none exists, we're expanded or animating expansion, or we're
// about to expand a bubble from the previous tapped flyout, or if bubble view is null.
@@ -1717,12 +1718,16 @@ public class BubbleStackView extends FrameLayout {
mBubbleData.setExpanded(true);
mBubbleToExpandAfterFlyoutCollapse = null;
}
- bubbleView.setDotState(DOT_STATE_DEFAULT);
+
+ // Stop suppressing the dot now that the flyout has morphed into the dot.
+ bubbleView.removeDotSuppressionFlag(
+ BadgedImageView.SuppressionFlag.FLYOUT_VISIBLE);
};
mFlyout.setVisibility(INVISIBLE);
- // Don't show the dot when we're animating the flyout
- bubbleView.setDotState(DOT_STATE_SUPPRESSED_FOR_FLYOUT);
+ // Suppress the dot when we are animating the flyout.
+ bubbleView.addDotSuppressionFlag(
+ BadgedImageView.SuppressionFlag.FLYOUT_VISIBLE);
// Start flyout expansion. Post in case layout isn't complete and getWidth returns 0.
post(() -> {
@@ -1743,6 +1748,11 @@ public class BubbleStackView extends FrameLayout {
};
mFlyout.postDelayed(mAnimateInFlyout, 200);
};
+
+ if (bubble.getIconView() == null) {
+ return;
+ }
+
mFlyout.setupFlyoutStartingAsDot(flyoutMessage,
mStackAnimationController.getStackPosition(), getWidth(),
mStackAnimationController.isStackOnLeftSide(),
@@ -1877,9 +1887,19 @@ public class BubbleStackView extends FrameLayout {
for (int i = 0; i < bubbleCount; i++) {
BadgedImageView bv = (BadgedImageView) mBubbleContainer.getChildAt(i);
bv.setZ((mMaxBubbles * mBubbleElevation) - i);
+
// If the dot is on the left, and so is the stack, we need to change the dot position.
if (bv.getDotPositionOnLeft() == mStackOnLeftOrWillBe) {
- bv.setDotPosition(!mStackOnLeftOrWillBe, animate);
+ bv.setDotPositionOnLeft(!mStackOnLeftOrWillBe, animate);
+ }
+
+ if (!mIsExpanded && i > 0) {
+ // If we're collapsed and this bubble is behind other bubbles, suppress its dot.
+ bv.addDotSuppressionFlag(
+ BadgedImageView.SuppressionFlag.BEHIND_STACK);
+ } else {
+ bv.removeDotSuppressionFlag(
+ BadgedImageView.SuppressionFlag.BEHIND_STACK);
}
}
}
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 7ee162e03dbc..00de8b4a51b8 100644
--- a/packages/SystemUI/src/com/android/systemui/bubbles/animation/StackAnimationController.java
+++ b/packages/SystemUI/src/com/android/systemui/bubbles/animation/StackAnimationController.java
@@ -287,7 +287,7 @@ public class StackAnimationController extends
/** Whether the stack is on the left side of the screen. */
public boolean isStackOnLeftSide() {
if (mLayout == null || !isStackPositionSet()) {
- return false;
+ return true; // Default to left, which is where it starts by default.
}
float stackCenter = mStackPosition.x + mBubbleBitmapSize / 2;
diff --git a/packages/SystemUI/src/com/android/systemui/controls/controller/ControlsControllerImpl.kt b/packages/SystemUI/src/com/android/systemui/controls/controller/ControlsControllerImpl.kt
index 118fcbb20f26..fdb0e4c95bed 100644
--- a/packages/SystemUI/src/com/android/systemui/controls/controller/ControlsControllerImpl.kt
+++ b/packages/SystemUI/src/com/android/systemui/controls/controller/ControlsControllerImpl.kt
@@ -65,7 +65,7 @@ class ControlsControllerImpl @Inject constructor (
companion object {
private const val TAG = "ControlsControllerImpl"
- internal const val CONTROLS_AVAILABLE = "systemui.controls_available"
+ internal const val CONTROLS_AVAILABLE = Settings.Secure.CONTROLS_ENABLED
internal val URI = Settings.Secure.getUriFor(CONTROLS_AVAILABLE)
private const val USER_CHANGE_RETRY_DELAY = 500L // ms
private const val DEFAULT_ENABLED = 1
@@ -439,13 +439,14 @@ class ControlsControllerImpl @Inject constructor (
Log.d(TAG, "Controls not available")
return
}
- executor.execute {
- val changed = Favorites.updateControls(
- componentName,
- listOf(control)
- )
- if (changed) {
- persistenceWrapper.storeFavorites(Favorites.getAllStructures())
+
+ // Assume that non STATUS_OK responses may contain incomplete or invalid information about
+ // the control, and do not attempt to update it
+ if (control.getStatus() == Control.STATUS_OK) {
+ executor.execute {
+ if (Favorites.updateControls(componentName, listOf(control))) {
+ persistenceWrapper.storeFavorites(Favorites.getAllStructures())
+ }
}
}
uiController.onRefreshState(componentName, listOf(control))
diff --git a/packages/SystemUI/src/com/android/systemui/controls/management/ControlAdapter.kt b/packages/SystemUI/src/com/android/systemui/controls/management/ControlAdapter.kt
index 563c2f677801..764fda05354c 100644
--- a/packages/SystemUI/src/com/android/systemui/controls/management/ControlAdapter.kt
+++ b/packages/SystemUI/src/com/android/systemui/controls/management/ControlAdapter.kt
@@ -68,6 +68,8 @@ class ControlAdapter(
width = ViewGroup.LayoutParams.MATCH_PARENT
}
elevation = this@ControlAdapter.elevation
+ background = parent.context.getDrawable(
+ R.drawable.control_background_ripple)
}
) { id, favorite ->
model?.changeFavoriteStatus(id, favorite)
@@ -137,10 +139,7 @@ private class ControlHolder(view: View, val favoriteCallback: ModelFavoriteChang
private val title: TextView = itemView.requireViewById(R.id.title)
private val subtitle: TextView = itemView.requireViewById(R.id.subtitle)
private val removed: TextView = itemView.requireViewById(R.id.status)
- private val favorite: CheckBox = itemView.requireViewById<CheckBox>(R.id.favorite)
- private val favoriteFrame: ViewGroup = itemView
- .requireViewById<ViewGroup>(R.id.favorite_container)
- .apply {
+ private val favorite: CheckBox = itemView.requireViewById<CheckBox>(R.id.favorite).apply {
visibility = View.VISIBLE
}
@@ -155,7 +154,7 @@ private class ControlHolder(view: View, val favoriteCallback: ModelFavoriteChang
favorite.setOnClickListener {
favoriteCallback(data.control.controlId, favorite.isChecked)
}
- favoriteFrame.setOnClickListener { favorite.performClick() }
+ itemView.setOnClickListener { favorite.performClick() }
applyRenderInfo(renderInfo)
}
diff --git a/packages/SystemUI/src/com/android/systemui/controls/ui/RenderInfo.kt b/packages/SystemUI/src/com/android/systemui/controls/ui/RenderInfo.kt
index 810ea65c7873..d33cd94004fd 100644
--- a/packages/SystemUI/src/com/android/systemui/controls/ui/RenderInfo.kt
+++ b/packages/SystemUI/src/com/android/systemui/controls/ui/RenderInfo.kt
@@ -110,60 +110,160 @@ private val deviceColorMap = mapOf<Int, Pair<Int, Int>>(
private val deviceIconMap = mapOf<Int, IconState>(
THERMOSTAT_RANGE to IconState(
- R.drawable.ic_device_thermostat_gm2_24px,
- R.drawable.ic_device_thermostat_gm2_24px
+ R.drawable.ic_device_thermostat_off,
+ R.drawable.ic_device_thermostat_on
),
(THERMOSTAT_RANGE + TemperatureControlTemplate.MODE_OFF) to IconState(
- R.drawable.ic_device_thermostat_gm2_24px,
- R.drawable.ic_device_thermostat_gm2_24px
+ R.drawable.ic_device_thermostat_off,
+ R.drawable.ic_device_thermostat_on
),
(THERMOSTAT_RANGE + TemperatureControlTemplate.MODE_HEAT) to IconState(
- R.drawable.ic_device_thermostat_gm2_24px,
- R.drawable.ic_device_thermostat_gm2_24px
+ R.drawable.ic_device_thermostat_off,
+ R.drawable.ic_device_thermostat_on
),
(THERMOSTAT_RANGE + TemperatureControlTemplate.MODE_COOL) to IconState(
- R.drawable.ic_device_thermostat_gm2_24px,
- R.drawable.ic_device_thermostat_gm2_24px
+ R.drawable.ic_device_thermostat_off,
+ R.drawable.ic_device_thermostat_on
),
(THERMOSTAT_RANGE + TemperatureControlTemplate.MODE_HEAT_COOL) to IconState(
- R.drawable.ic_device_thermostat_gm2_24px,
- R.drawable.ic_device_thermostat_gm2_24px
+ R.drawable.ic_device_thermostat_off,
+ R.drawable.ic_device_thermostat_on
),
(THERMOSTAT_RANGE + TemperatureControlTemplate.MODE_ECO) to IconState(
- R.drawable.ic_device_thermostat_gm2_24px,
- R.drawable.ic_device_thermostat_gm2_24px
+ R.drawable.ic_device_thermostat_off,
+ R.drawable.ic_device_thermostat_on
),
DeviceTypes.TYPE_THERMOSTAT to IconState(
- R.drawable.ic_device_thermostat_gm2_24px,
- R.drawable.ic_device_thermostat_gm2_24px
+ R.drawable.ic_device_thermostat_off,
+ R.drawable.ic_device_thermostat_on
),
DeviceTypes.TYPE_LIGHT to IconState(
- R.drawable.ic_light_off_gm2_24px,
- R.drawable.ic_lightbulb_outline_gm2_24px
+ R.drawable.ic_device_light_off,
+ R.drawable.ic_device_light_on
),
DeviceTypes.TYPE_CAMERA to IconState(
- R.drawable.ic_videocam_gm2_24px,
- R.drawable.ic_videocam_gm2_24px
+ R.drawable.ic_device_camera_off,
+ R.drawable.ic_device_camera_on
),
DeviceTypes.TYPE_LOCK to IconState(
- R.drawable.ic_lock_open_gm2_24px,
- R.drawable.ic_lock_gm2_24px
+ R.drawable.ic_device_lock_off,
+ R.drawable.ic_device_lock_on
),
DeviceTypes.TYPE_SWITCH to IconState(
- R.drawable.ic_switches_gm2_24px,
- R.drawable.ic_switches_gm2_24px
+ R.drawable.ic_device_switch_off,
+ R.drawable.ic_device_switch_on
),
DeviceTypes.TYPE_OUTLET to IconState(
- R.drawable.ic_power_off_gm2_24px,
- R.drawable.ic_power_gm2_24px
+ R.drawable.ic_device_outlet_off,
+ R.drawable.ic_device_outlet_on
),
DeviceTypes.TYPE_VACUUM to IconState(
- R.drawable.ic_vacuum_gm2_24px,
- R.drawable.ic_vacuum_gm2_24px
+ R.drawable.ic_device_vacuum_off,
+ R.drawable.ic_device_vacuum_on
),
DeviceTypes.TYPE_MOP to IconState(
- R.drawable.ic_vacuum_gm2_24px,
- R.drawable.ic_vacuum_gm2_24px
+ R.drawable.ic_device_mop_off,
+ R.drawable.ic_device_mop_on
+ ),
+ DeviceTypes.TYPE_AIR_FRESHENER to IconState(
+ R.drawable.ic_device_air_freshener_off,
+ R.drawable.ic_device_air_freshener_on
+ ),
+ DeviceTypes.TYPE_AIR_PURIFIER to IconState(
+ R.drawable.ic_device_air_purifier_off,
+ R.drawable.ic_device_air_purifier_on
+ ),
+ DeviceTypes.TYPE_FAN to IconState(
+ R.drawable.ic_device_fan_off,
+ R.drawable.ic_device_fan_on
+ ),
+ DeviceTypes.TYPE_HOOD to IconState(
+ R.drawable.ic_device_hood_off,
+ R.drawable.ic_device_hood_on
+ ),
+ DeviceTypes.TYPE_KETTLE to IconState(
+ R.drawable.ic_device_kettle_off,
+ R.drawable.ic_device_kettle_on
+ ),
+ DeviceTypes.TYPE_MICROWAVE to IconState(
+ R.drawable.ic_device_microwave_off,
+ R.drawable.ic_device_microwave_on
+ ),
+ DeviceTypes.TYPE_REMOTE_CONTROL to IconState(
+ R.drawable.ic_device_remote_control_off,
+ R.drawable.ic_device_remote_control_on
+ ),
+ DeviceTypes.TYPE_SET_TOP to IconState(
+ R.drawable.ic_device_set_top_off,
+ R.drawable.ic_device_set_top_on
+ ),
+ DeviceTypes.TYPE_STYLER to IconState(
+ R.drawable.ic_device_styler_off,
+ R.drawable.ic_device_styler_on
+ ),
+ DeviceTypes.TYPE_TV to IconState(
+ R.drawable.ic_device_tv_off,
+ R.drawable.ic_device_tv_on
+ ),
+ DeviceTypes.TYPE_WATER_HEATER to IconState(
+ R.drawable.ic_device_water_heater_off,
+ R.drawable.ic_device_water_heater_on
+ ),
+ DeviceTypes.TYPE_DISHWASHER to IconState(
+ R.drawable.ic_device_dishwasher_off,
+ R.drawable.ic_device_dishwasher_on
+ ),
+ DeviceTypes.TYPE_MULTICOOKER to IconState(
+ R.drawable.ic_device_multicooker_off,
+ R.drawable.ic_device_multicooker_on
+ ),
+ DeviceTypes.TYPE_SPRINKLER to IconState(
+ R.drawable.ic_device_sprinkler_off,
+ R.drawable.ic_device_sprinkler_on
+ ),
+ DeviceTypes.TYPE_WASHER to IconState(
+ R.drawable.ic_device_washer_off,
+ R.drawable.ic_device_washer_on
+ ),
+ DeviceTypes.TYPE_BLINDS to IconState(
+ R.drawable.ic_device_blinds_off,
+ R.drawable.ic_device_blinds_on
+ ),
+ DeviceTypes.TYPE_DRAWER to IconState(
+ R.drawable.ic_device_drawer_off,
+ R.drawable.ic_device_drawer_on
+ ),
+ DeviceTypes.TYPE_GARAGE to IconState(
+ R.drawable.ic_device_garage_off,
+ R.drawable.ic_device_garage_on
+ ),
+ DeviceTypes.TYPE_GATE to IconState(
+ R.drawable.ic_device_gate_off,
+ R.drawable.ic_device_gate_on
+ ),
+ DeviceTypes.TYPE_PERGOLA to IconState(
+ R.drawable.ic_device_pergola_off,
+ R.drawable.ic_device_pergola_on
+ ),
+ DeviceTypes.TYPE_WINDOW to IconState(
+ R.drawable.ic_device_window_off,
+ R.drawable.ic_device_window_on
+ ),
+ DeviceTypes.TYPE_VALVE to IconState(
+ R.drawable.ic_device_valve_off,
+ R.drawable.ic_device_valve_on
+ ),
+ DeviceTypes.TYPE_SECURITY_SYSTEM to IconState(
+ R.drawable.ic_device_security_system_off,
+ R.drawable.ic_device_security_system_on
+ ),
+ DeviceTypes.TYPE_REFRIGERATOR to IconState(
+ R.drawable.ic_device_refrigerator_off,
+ R.drawable.ic_device_refrigerator_on
+ ),
+ DeviceTypes.TYPE_DOORBELL to IconState(
+ R.drawable.ic_device_doorbell_off,
+ R.drawable.ic_device_doorbell_on
),
DeviceTypes.TYPE_ROUTINE to IconState(
RenderInfo.APP_ICON_ID,
diff --git a/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsImpl.java b/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsImpl.java
index 12955a153360..ce29859f12ca 100644
--- a/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsImpl.java
@@ -49,8 +49,6 @@ import dagger.Lazy;
public class GlobalActionsImpl implements GlobalActions, CommandQueue.Callbacks {
- private static final float SHUTDOWN_SCRIM_ALPHA = 0.95f;
-
private final Context mContext;
private final Lazy<GlobalActionsDialog> mGlobalActionsDialogLazy;
private final KeyguardStateController mKeyguardStateController;
@@ -124,7 +122,7 @@ public class GlobalActionsImpl implements GlobalActions, CommandQueue.Callbacks
| WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH
| WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED);
window.setBackgroundDrawable(background);
- window.setWindowAnimations(R.style.Animation_Toast);
+ window.setWindowAnimations(com.android.systemui.R.style.Animation_ShutdownUi);
d.setContentView(R.layout.shutdown_dialog);
d.setCancelable(false);
@@ -153,7 +151,9 @@ public class GlobalActionsImpl implements GlobalActions, CommandQueue.Callbacks
mBlurUtils.applyBlur(d.getWindow().getDecorView().getViewRootImpl(),
mBlurUtils.blurRadiusOfRatio(1));
} else {
- background.setAlpha((int) (SHUTDOWN_SCRIM_ALPHA * 255));
+ float backgroundAlpha = mContext.getResources().getFloat(
+ com.android.systemui.R.dimen.shutdown_scrim_behind_alpha);
+ background.setAlpha((int) (backgroundAlpha * 255));
}
d.show();
diff --git a/packages/SystemUI/src/com/android/systemui/pip/PipTaskOrganizer.java b/packages/SystemUI/src/com/android/systemui/pip/PipTaskOrganizer.java
index 6ce5e7cf506c..af8b18482ea8 100644
--- a/packages/SystemUI/src/com/android/systemui/pip/PipTaskOrganizer.java
+++ b/packages/SystemUI/src/com/android/systemui/pip/PipTaskOrganizer.java
@@ -16,6 +16,9 @@
package com.android.systemui.pip;
+import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
+import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED;
+
import static com.android.systemui.pip.PipAnimationController.ANIM_TYPE_ALPHA;
import static com.android.systemui.pip.PipAnimationController.ANIM_TYPE_BOUNDS;
import static com.android.systemui.pip.PipAnimationController.TRANSITION_DIRECTION_NONE;
@@ -26,8 +29,6 @@ import static com.android.systemui.pip.PipAnimationController.TRANSITION_DIRECTI
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.app.ActivityManager;
-import android.app.ActivityTaskManager;
-import android.window.ITaskOrganizerController;
import android.app.PictureInPictureParams;
import android.content.Context;
import android.content.pm.ActivityInfo;
@@ -38,9 +39,9 @@ import android.os.Looper;
import android.os.RemoteException;
import android.util.Log;
import android.util.Size;
+import android.view.SurfaceControl;
import android.window.ITaskOrganizer;
import android.window.IWindowContainer;
-import android.view.SurfaceControl;
import android.window.WindowContainerTransaction;
import android.window.WindowOrganizer;
@@ -216,6 +217,29 @@ public class PipTaskOrganizer extends ITaskOrganizer.Stub {
mOneShotAnimationType = animationType;
}
+ /**
+ * Dismiss PiP, this is done in two phases using {@link WindowContainerTransaction}
+ * - setActivityWindowingMode to fullscreen at beginning of the transaction. without changing
+ * the windowing mode of the Task itself. This makes sure the activity render it's fullscreen
+ * configuration while the Task is still in PiP.
+ * - setWindowingMode to fullscreen at the end of transition
+ * @param animationDurationMs duration in millisecond for the exiting PiP transition
+ */
+ public void dismissPip(int animationDurationMs) {
+ try {
+ final WindowContainerTransaction wct = new WindowContainerTransaction();
+ wct.setActivityWindowingMode(mToken, WINDOWING_MODE_FULLSCREEN);
+ WindowOrganizer.applyTransaction(wct);
+ } catch (RemoteException e) {
+ Log.e(TAG, "Failed to apply container transaction", e);
+ }
+ final Rect destinationBounds = mBoundsToRestore.remove(mToken.asBinder());
+ scheduleAnimateResizePip(mLastReportedBounds, destinationBounds,
+ TRANSITION_DIRECTION_TO_FULLSCREEN, animationDurationMs,
+ null /* updateBoundsCallback */);
+ mInPip = false;
+ }
+
@Override
public void onTaskAppeared(ActivityManager.RunningTaskInfo info) {
Objects.requireNonNull(info, "Requires RunningTaskInfo");
@@ -235,7 +259,8 @@ public class PipTaskOrganizer extends ITaskOrganizer.Stub {
mBoundsToRestore.put(mToken.asBinder(), currentBounds);
if (mOneShotAnimationType == ANIM_TYPE_BOUNDS) {
scheduleAnimateResizePip(currentBounds, destinationBounds,
- TRANSITION_DIRECTION_TO_PIP, mEnterExitAnimationDuration, null);
+ TRANSITION_DIRECTION_TO_PIP, mEnterExitAnimationDuration,
+ null /* updateBoundsCallback */);
} else if (mOneShotAnimationType == ANIM_TYPE_ALPHA) {
mUpdateHandler.post(() -> mPipAnimationController
.getAnimator(mLeash, destinationBounds, 0f, 1f)
@@ -249,6 +274,12 @@ public class PipTaskOrganizer extends ITaskOrganizer.Stub {
}
}
+ /**
+ * Note that dismissing PiP is now originated from SystemUI, see {@link #dismissPip(int)}.
+ * Meanwhile this callback is invoked whenever the task is removed. For instance:
+ * - as a result of removeStacksInWindowingModes from WM
+ * - activity itself is died
+ */
@Override
public void onTaskVanished(ActivityManager.RunningTaskInfo info) {
IWindowContainer token = info.token;
@@ -259,7 +290,8 @@ public class PipTaskOrganizer extends ITaskOrganizer.Stub {
}
final Rect boundsToRestore = mBoundsToRestore.remove(token.asBinder());
scheduleAnimateResizePip(mLastReportedBounds, boundsToRestore,
- TRANSITION_DIRECTION_TO_FULLSCREEN, mEnterExitAnimationDuration, null);
+ TRANSITION_DIRECTION_TO_FULLSCREEN, mEnterExitAnimationDuration,
+ null /* updateBoundsCallback */);
mInPip = false;
}
@@ -274,7 +306,8 @@ public class PipTaskOrganizer extends ITaskOrganizer.Stub {
getAspectRatioOrDefault(newParams),
null /* bounds */, getMinimalSize(info.topActivityInfo));
Objects.requireNonNull(destinationBounds, "Missing destination bounds");
- scheduleAnimateResizePip(destinationBounds, mEnterExitAnimationDuration, null);
+ scheduleAnimateResizePip(destinationBounds, mEnterExitAnimationDuration,
+ null /* updateBoundsCallback */);
}
/**
@@ -434,12 +467,19 @@ public class PipTaskOrganizer extends ITaskOrganizer.Stub {
}
mLastReportedBounds.set(destinationBounds);
try {
- // If we are animating to fullscreen, then we need to reset the override bounds on the
- // task to ensure that the task "matches" the parent's bounds
- Rect taskBounds = direction == TRANSITION_DIRECTION_TO_FULLSCREEN
- ? null
- : destinationBounds;
final WindowContainerTransaction wct = new WindowContainerTransaction();
+ final Rect taskBounds;
+ if (direction == TRANSITION_DIRECTION_TO_FULLSCREEN) {
+ // If we are animating to fullscreen, then we need to reset the override bounds
+ // on the task to ensure that the task "matches" the parent's bounds, this applies
+ // also to the final windowing mode, which should be reset to undefined rather than
+ // fullscreen.
+ taskBounds = null;
+ wct.setWindowingMode(mToken, WINDOWING_MODE_UNDEFINED)
+ .setActivityWindowingMode(mToken, WINDOWING_MODE_UNDEFINED);
+ } else {
+ taskBounds = destinationBounds;
+ }
if (direction == TRANSITION_DIRECTION_TO_PIP) {
wct.scheduleFinishEnterPip(mToken, taskBounds);
} else {
diff --git a/packages/SystemUI/src/com/android/systemui/pip/phone/PipManager.java b/packages/SystemUI/src/com/android/systemui/pip/phone/PipManager.java
index e89ce2e3a56f..9722c0873a78 100644
--- a/packages/SystemUI/src/com/android/systemui/pip/phone/PipManager.java
+++ b/packages/SystemUI/src/com/android/systemui/pip/phone/PipManager.java
@@ -36,7 +36,6 @@ import android.util.Pair;
import android.view.DisplayInfo;
import android.view.IPinnedStackController;
import android.window.WindowContainerTransaction;
-import android.window.WindowOrganizer;
import com.android.systemui.Dependency;
import com.android.systemui.UiOffloadThread;
@@ -258,7 +257,7 @@ public class PipManager implements BasePipManager, PipTaskOrganizer.PipTransitio
// register the pip input consumer to ensure touch can send to it.
mInputConsumerController.registerInputConsumer();
}
- } catch (RemoteException e) {
+ } catch (RemoteException | UnsupportedOperationException e) {
e.printStackTrace();
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/pip/phone/PipMotionHelper.java b/packages/SystemUI/src/com/android/systemui/pip/phone/PipMotionHelper.java
index 449a2bca6abb..7974281b956f 100644
--- a/packages/SystemUI/src/com/android/systemui/pip/phone/PipMotionHelper.java
+++ b/packages/SystemUI/src/com/android/systemui/pip/phone/PipMotionHelper.java
@@ -219,11 +219,7 @@ public class PipMotionHelper implements PipAppOpsListener.Callback,
cancelAnimations();
mMenuController.hideMenuWithoutResize();
mPipTaskOrganizer.getUpdateHandler().post(() -> {
- try {
- mActivityTaskManager.dismissPip(!skipAnimation, EXPAND_STACK_TO_FULLSCREEN_DURATION);
- } catch (RemoteException e) {
- Log.e(TAG, "Error expanding PiP activity", e);
- }
+ mPipTaskOrganizer.dismissPip(skipAnimation ? 0 : EXPAND_STACK_TO_FULLSCREEN_DURATION);
});
}
diff --git a/packages/SystemUI/src/com/android/systemui/pip/tv/PipManager.java b/packages/SystemUI/src/com/android/systemui/pip/tv/PipManager.java
index 2dcf1f89c3ec..18dde9dfc61e 100644
--- a/packages/SystemUI/src/com/android/systemui/pip/tv/PipManager.java
+++ b/packages/SystemUI/src/com/android/systemui/pip/tv/PipManager.java
@@ -45,7 +45,6 @@ import android.text.TextUtils;
import android.util.Log;
import android.util.Pair;
import android.view.DisplayInfo;
-import android.window.WindowOrganizer;
import com.android.systemui.Dependency;
import com.android.systemui.R;
@@ -296,7 +295,7 @@ public class PipManager implements BasePipManager, PipTaskOrganizer.PipTransitio
try {
WindowManagerWrapper.getInstance().addPinnedStackListener(mPinnedStackListener);
TaskOrganizer.registerOrganizer(mPipTaskOrganizer, WINDOWING_MODE_PINNED);
- } catch (RemoteException e) {
+ } catch (RemoteException | UnsupportedOperationException e) {
Log.e(TAG, "Failed to register pinned stack listener", e);
}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/PagedTileLayout.java b/packages/SystemUI/src/com/android/systemui/qs/PagedTileLayout.java
index 0403a0505b00..cd737217b84a 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/PagedTileLayout.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/PagedTileLayout.java
@@ -142,6 +142,9 @@ public class PagedTileLayout extends ViewPager implements QSTileLayout {
@Override
public void computeScroll() {
if (!mScroller.isFinished() && mScroller.computeScrollOffset()) {
+ if (!isFakeDragging()) {
+ beginFakeDrag();
+ }
fakeDragBy(getScrollX() - mScroller.getCurrX());
// Keep on drawing until the animation has finished.
postInvalidateOnAnimation();
diff --git a/packages/SystemUI/src/com/android/systemui/recents/RecentsOnboarding.java b/packages/SystemUI/src/com/android/systemui/recents/RecentsOnboarding.java
index aa6444973a6f..3b3d9dde3b7e 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/RecentsOnboarding.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/RecentsOnboarding.java
@@ -17,7 +17,6 @@
package com.android.systemui.recents;
import static android.app.WindowConfiguration.ACTIVITY_TYPE_STANDARD;
-import static android.app.WindowConfiguration.ACTIVITY_TYPE_UNDEFINED;
import static android.view.WindowManagerPolicyConstants.NAV_BAR_MODE_3BUTTON;
import static com.android.systemui.Prefs.Key.DISMISSED_RECENTS_SWIPE_UP_ONBOARDING_COUNT;
@@ -27,8 +26,7 @@ import static com.android.systemui.Prefs.Key.HAS_SEEN_RECENTS_SWIPE_UP_ONBOARDIN
import static com.android.systemui.Prefs.Key.OVERVIEW_OPENED_COUNT;
import static com.android.systemui.Prefs.Key.OVERVIEW_OPENED_FROM_HOME_COUNT;
import static com.android.systemui.shared.system.LauncherEventUtil.DISMISS;
-import static com.android.systemui.shared.system.LauncherEventUtil
- .RECENTS_QUICK_SCRUB_ONBOARDING_TIP;
+import static com.android.systemui.shared.system.LauncherEventUtil.RECENTS_QUICK_SCRUB_ONBOARDING_TIP;
import static com.android.systemui.shared.system.LauncherEventUtil.RECENTS_SWIPE_UP_ONBOARDING_TIP;
import static com.android.systemui.shared.system.LauncherEventUtil.VISIBLE;
@@ -139,7 +137,7 @@ public class RecentsOnboarding {
private void onAppLaunch() {
ActivityManager.RunningTaskInfo info = ActivityManagerWrapper.getInstance()
- .getRunningTask(ACTIVITY_TYPE_UNDEFINED /* ignoreActivityType */);
+ .getRunningTask();
if (info == null) {
return;
}
diff --git a/packages/SystemUI/src/com/android/systemui/stackdivider/Divider.java b/packages/SystemUI/src/com/android/systemui/stackdivider/Divider.java
index 01498f933383..66e321145701 100644
--- a/packages/SystemUI/src/com/android/systemui/stackdivider/Divider.java
+++ b/packages/SystemUI/src/com/android/systemui/stackdivider/Divider.java
@@ -25,6 +25,7 @@ import static android.window.WindowOrganizer.TaskOrganizer;
import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
import android.animation.ValueAnimator;
+import android.app.ActivityTaskManager;
import android.content.Context;
import android.content.res.Configuration;
import android.graphics.Rect;
@@ -32,11 +33,11 @@ import android.os.Handler;
import android.os.RemoteException;
import android.provider.Settings;
import android.util.Slog;
-import android.window.IWindowContainer;
import android.view.LayoutInflater;
import android.view.SurfaceControl;
import android.view.SurfaceSession;
import android.view.View;
+import android.window.IWindowContainer;
import android.window.WindowContainerTransaction;
import android.window.WindowOrganizer;
@@ -112,6 +113,9 @@ public class Divider extends SystemUI implements DividerView.DividerCallbacks,
private DisplayChangeController.OnDisplayChangingListener mRotationController =
(display, fromRotation, toRotation, t) -> {
+ if (!mSplits.isSplitScreenSupported()) {
+ return;
+ }
DisplayLayout displayLayout =
new DisplayLayout(mDisplayController.getDisplayLayout(display));
SplitDisplayLayout sdl = new SplitDisplayLayout(mContext, displayLayout, mSplits);
@@ -472,6 +476,10 @@ public class Divider extends SystemUI implements DividerView.DividerCallbacks,
mDisplayController.getDisplayLayout(displayId), mSplits);
mImeController.addPositionProcessor(mImePositionProcessor);
mDisplayController.addDisplayChangingController(mRotationController);
+ if (!ActivityTaskManager.supportsSplitScreenMultiWindow(mContext)) {
+ removeDivider();
+ return;
+ }
try {
mSplits.init(mSurfaceSession);
// Set starting tile bounds based on middle target
@@ -481,13 +489,15 @@ public class Divider extends SystemUI implements DividerView.DividerCallbacks,
WindowOrganizer.applyTransaction(tct);
} catch (Exception e) {
Slog.e(TAG, "Failed to register docked stack listener", e);
+ removeDivider();
+ return;
}
update(mDisplayController.getDisplayContext(displayId).getResources().getConfiguration());
}
@Override
public void onDisplayConfigurationChanged(int displayId, Configuration newConfig) {
- if (displayId != DEFAULT_DISPLAY) {
+ if (displayId != DEFAULT_DISPLAY || !mSplits.isSplitScreenSupported()) {
return;
}
mSplitLayout = new SplitDisplayLayout(mDisplayController.getDisplayContext(displayId),
diff --git a/packages/SystemUI/src/com/android/systemui/stackdivider/DividerView.java b/packages/SystemUI/src/com/android/systemui/stackdivider/DividerView.java
index 1aa78311a989..1e4c8e4dc268 100644
--- a/packages/SystemUI/src/com/android/systemui/stackdivider/DividerView.java
+++ b/packages/SystemUI/src/com/android/systemui/stackdivider/DividerView.java
@@ -25,7 +25,6 @@ import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
import android.animation.ValueAnimator;
import android.annotation.Nullable;
-import android.app.ActivityTaskManager;
import android.content.Context;
import android.content.res.Configuration;
import android.graphics.Rect;
@@ -130,7 +129,6 @@ public class DividerView extends FrameLayout implements OnTouchListener,
private int mDividerInsets;
private final Display mDefaultDisplay;
- private boolean mSupportSplitScreenMultiWindow;
private int mDividerSize;
private int mTouchElevation;
@@ -284,8 +282,6 @@ public class DividerView extends FrameLayout implements OnTouchListener,
final DisplayManager displayManager =
(DisplayManager) mContext.getSystemService(Context.DISPLAY_SERVICE);
mDefaultDisplay = displayManager.getDisplay(Display.DEFAULT_DISPLAY);
- mSupportSplitScreenMultiWindow =
- ActivityTaskManager.supportsSplitScreenMultiWindow(mContext);
}
@Override
@@ -358,11 +354,6 @@ public class DividerView extends FrameLayout implements OnTouchListener,
@Override
protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
- if (!mSupportSplitScreenMultiWindow) {
- super.onLayout(changed, left, top, right, bottom);
- return;
- }
-
if (mFirstLayout) {
// Wait for first layout so that the ViewRootImpl surface has been created.
initializeSurfaceState();
diff --git a/packages/SystemUI/src/com/android/systemui/stackdivider/SplitScreenTaskOrganizer.java b/packages/SystemUI/src/com/android/systemui/stackdivider/SplitScreenTaskOrganizer.java
index 6cb7f4ff7204..0a528a63009e 100644
--- a/packages/SystemUI/src/com/android/systemui/stackdivider/SplitScreenTaskOrganizer.java
+++ b/packages/SystemUI/src/com/android/systemui/stackdivider/SplitScreenTaskOrganizer.java
@@ -49,6 +49,7 @@ class SplitScreenTaskOrganizer extends ITaskOrganizer.Stub {
ArrayList<SurfaceControl> mHomeAndRecentsSurfaces = new ArrayList<>();
Rect mHomeBounds = new Rect();
final Divider mDivider;
+ private boolean mSplitScreenSupported = false;
SplitScreenTaskOrganizer(Divider divider) {
mDivider = divider;
@@ -57,12 +58,19 @@ class SplitScreenTaskOrganizer extends ITaskOrganizer.Stub {
void init(SurfaceSession session) throws RemoteException {
TaskOrganizer.registerOrganizer(this, WINDOWING_MODE_SPLIT_SCREEN_PRIMARY);
TaskOrganizer.registerOrganizer(this, WINDOWING_MODE_SPLIT_SCREEN_SECONDARY);
- mPrimary = TaskOrganizer.createRootTask(Display.DEFAULT_DISPLAY,
- WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_PRIMARY);
- mSecondary = TaskOrganizer.createRootTask(Display.DEFAULT_DISPLAY,
- WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_SECONDARY);
- mPrimarySurface = mPrimary.token.getLeash();
- mSecondarySurface = mSecondary.token.getLeash();
+ try {
+ mPrimary = TaskOrganizer.createRootTask(Display.DEFAULT_DISPLAY,
+ WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_PRIMARY);
+ mSecondary = TaskOrganizer.createRootTask(Display.DEFAULT_DISPLAY,
+ WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_SECONDARY);
+ mPrimarySurface = mPrimary.token.getLeash();
+ mSecondarySurface = mSecondary.token.getLeash();
+ } catch (RemoteException e) {
+ // teardown to prevent callbacks
+ TaskOrganizer.unregisterOrganizer(this);
+ throw e;
+ }
+ mSplitScreenSupported = true;
// Initialize dim surfaces:
mPrimaryDim = new SurfaceControl.Builder(session).setParent(mPrimarySurface)
@@ -78,6 +86,10 @@ class SplitScreenTaskOrganizer extends ITaskOrganizer.Stub {
releaseTransaction(t);
}
+ boolean isSplitScreenSupported() {
+ return mSplitScreenSupported;
+ }
+
SurfaceControl.Transaction getTransaction() {
return mDivider.mTransactionPool.acquire();
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardIndicationController.java b/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardIndicationController.java
index bb0fa2d2c7cb..5475812b5563 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardIndicationController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardIndicationController.java
@@ -93,7 +93,7 @@ public class KeyguardIndicationController implements StateListener,
private String mRestingIndication;
private String mAlignmentIndication;
private CharSequence mTransientIndication;
- private ColorStateList mTransientTextColorState;
+ private boolean mTransientTextIsError;
private ColorStateList mInitialTextColorState;
private boolean mVisible;
private boolean mHideTransientMessageOnScreenOff;
@@ -260,7 +260,7 @@ public class KeyguardIndicationController implements StateListener,
* Shows {@param transientIndication} until it is hidden by {@link #hideTransientIndication}.
*/
public void showTransientIndication(CharSequence transientIndication) {
- showTransientIndication(transientIndication, mInitialTextColorState,
+ showTransientIndication(transientIndication, false /* isError */,
false /* hideOnScreenOff */);
}
@@ -268,10 +268,10 @@ public class KeyguardIndicationController implements StateListener,
* Shows {@param transientIndication} until it is hidden by {@link #hideTransientIndication}.
*/
private void showTransientIndication(CharSequence transientIndication,
- ColorStateList textColorState, boolean hideOnScreenOff) {
+ boolean isError, boolean hideOnScreenOff) {
mTransientIndication = transientIndication;
mHideTransientMessageOnScreenOff = hideOnScreenOff && transientIndication != null;
- mTransientTextColorState = textColorState;
+ mTransientTextIsError = isError;
mHandler.removeMessages(MSG_HIDE_TRANSIENT);
mHandler.removeMessages(MSG_SWIPE_UP_TO_UNLOCK);
if (mDozing && !TextUtils.isEmpty(mTransientIndication)) {
@@ -311,7 +311,6 @@ public class KeyguardIndicationController implements StateListener,
mTextView.switchIndication(mTransientIndication);
} else if (!TextUtils.isEmpty(mAlignmentIndication)) {
mTextView.switchIndication(mAlignmentIndication);
- mTextView.setTextColor(Utils.getColorError(mContext));
} else if (mPowerPluggedIn) {
String indication = computePowerIndication();
if (animate) {
@@ -336,9 +335,9 @@ public class KeyguardIndicationController implements StateListener,
powerIndication = computePowerIndication();
}
+ boolean isError = false;
if (!mKeyguardUpdateMonitor.isUserUnlocked(userId)) {
mTextView.switchIndication(com.android.internal.R.string.lockscreen_storage_locked);
- mTextView.setTextColor(mInitialTextColorState);
} else if (!TextUtils.isEmpty(mTransientIndication)) {
if (powerIndication != null && !mTransientIndication.equals(powerIndication)) {
String indication = mContext.getResources().getString(
@@ -348,7 +347,7 @@ public class KeyguardIndicationController implements StateListener,
} else {
mTextView.switchIndication(mTransientIndication);
}
- mTextView.setTextColor(mTransientTextColorState);
+ isError = mTransientTextIsError;
} else if (!TextUtils.isEmpty(trustGrantedIndication)
&& mKeyguardUpdateMonitor.getUserHasTrust(userId)) {
if (powerIndication != null) {
@@ -359,15 +358,13 @@ public class KeyguardIndicationController implements StateListener,
} else {
mTextView.switchIndication(trustGrantedIndication);
}
- mTextView.setTextColor(mInitialTextColorState);
} else if (!TextUtils.isEmpty(mAlignmentIndication)) {
mTextView.switchIndication(mAlignmentIndication);
- mTextView.setTextColor(Utils.getColorError(mContext));
+ isError = true;
} else if (mPowerPluggedIn) {
if (DEBUG_CHARGING_SPEED) {
powerIndication += ", " + (mChargingWattage / 1000) + " mW";
}
- mTextView.setTextColor(mInitialTextColorState);
if (animate) {
animateText(mTextView, powerIndication);
} else {
@@ -377,11 +374,11 @@ public class KeyguardIndicationController implements StateListener,
&& mKeyguardUpdateMonitor.getUserTrustIsManaged(userId)
&& !mKeyguardUpdateMonitor.getUserHasTrust(userId)) {
mTextView.switchIndication(trustManagedIndication);
- mTextView.setTextColor(mInitialTextColorState);
} else {
mTextView.switchIndication(mRestingIndication);
- mTextView.setTextColor(mInitialTextColorState);
}
+ mTextView.setTextColor(isError ? Utils.getColorError(mContext)
+ : mInitialTextColorState);
}
}
@@ -532,7 +529,7 @@ public class KeyguardIndicationController implements StateListener,
mStatusBarKeyguardViewManager.showBouncerMessage(message, mInitialTextColorState);
} else if (mKeyguardUpdateMonitor.isScreenOn()) {
showTransientIndication(mContext.getString(R.string.keyguard_unlock),
- mInitialTextColorState, true /* hideOnScreenOff */);
+ false /* isError */, true /* hideOnScreenOff */);
hideTransientIndicationDelayed(BaseKeyguardCallback.HIDE_DELAY_MS);
}
}
@@ -551,7 +548,7 @@ public class KeyguardIndicationController implements StateListener,
public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
pw.println("KeyguardIndicationController:");
- pw.println(" mTransientTextColorState: " + mTransientTextColorState);
+ pw.println(" mTransientTextIsError: " + mTransientTextIsError);
pw.println(" mInitialTextColorState: " + mInitialTextColorState);
pw.println(" mPowerPluggedInWired: " + mPowerPluggedInWired);
pw.println(" mPowerPluggedIn: " + mPowerPluggedIn);
@@ -630,7 +627,7 @@ public class KeyguardIndicationController implements StateListener,
mStatusBarKeyguardViewManager.showBouncerMessage(helpString,
mInitialTextColorState);
} else if (mKeyguardUpdateMonitor.isScreenOn()) {
- showTransientIndication(helpString, mInitialTextColorState, showSwipeToUnlock);
+ showTransientIndication(helpString, false /* isError */, showSwipeToUnlock);
if (!showSwipeToUnlock) {
hideTransientIndicationDelayed(TRANSIENT_BIOMETRIC_ERROR_TIMEOUT);
}
@@ -704,14 +701,13 @@ public class KeyguardIndicationController implements StateListener,
@Override
public void onTrustAgentErrorMessage(CharSequence message) {
- showTransientIndication(message, Utils.getColorError(mContext),
- false /* hideOnScreenOff */);
+ showTransientIndication(message, true /* isError */, false /* hideOnScreenOff */);
}
@Override
public void onScreenTurnedOn() {
if (mMessageToShowOnScreenOn != null) {
- showTransientIndication(mMessageToShowOnScreenOn, Utils.getColorError(mContext),
+ showTransientIndication(mMessageToShowOnScreenOn, true /* isError */,
false /* hideOnScreenOff */);
// We want to keep this message around in case the screen was off
hideTransientIndicationDelayed(HIDE_DELAY_MS);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/EdgeBackGestureHandler.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/EdgeBackGestureHandler.java
index ecfe1168b7f0..8efda213d659 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/EdgeBackGestureHandler.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/EdgeBackGestureHandler.java
@@ -110,8 +110,6 @@ public class EdgeBackGestureHandler implements DisplayListener,
private final float mTouchSlop;
// Duration after which we consider the event as longpress.
private final int mLongPressTimeout;
- // The back gesture type
- private int mBackType;
private final PointF mDownPoint = new PointF();
private final PointF mEndPoint = new PointF();
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 3074e33c46a8..f06cfec9480a 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBouncer.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBouncer.java
@@ -203,6 +203,7 @@ public class KeyguardBouncer {
Log.wtf(TAG, "onFullyShown when view was null");
} else {
mKeyguardView.onResume();
+ mRoot.announceForAccessibility(mKeyguardView.getAccessibilityTitleForCurrentMode());
}
}
@@ -247,6 +248,7 @@ public class KeyguardBouncer {
if (mExpansion == EXPANSION_VISIBLE) {
mKeyguardView.onResume();
mKeyguardView.resetSecurityContainer();
+ showPromptReason(mBouncerPromptReason);
}
SysUiStatsLog.write(SysUiStatsLog.KEYGUARD_BOUNCER_STATE_CHANGED,
SysUiStatsLog.KEYGUARD_BOUNCER_STATE_CHANGED__STATE__SHOWN);
@@ -438,7 +440,6 @@ public class KeyguardBouncer {
mStatusBarHeight = mRoot.getResources().getDimensionPixelOffset(
com.android.systemui.R.dimen.status_bar_height);
mRoot.setVisibility(View.INVISIBLE);
- mRoot.setAccessibilityPaneTitle(mKeyguardView.getAccessibilityTitleForCurrentMode());
final WindowInsets rootInsets = mRoot.getRootWindowInsets();
if (rootInsets != null) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/BatteryControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/BatteryControllerImpl.java
index 496bf68e67a5..bf5900ff24bb 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/BatteryControllerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/BatteryControllerImpl.java
@@ -67,9 +67,9 @@ public class BatteryControllerImpl extends BroadcastReceiver implements BatteryC
private final Handler mBgHandler;
protected final Context mContext;
- private int mLevel;
- private boolean mPluggedIn;
- private boolean mCharging;
+ protected int mLevel;
+ protected boolean mPluggedIn;
+ protected boolean mCharging;
private boolean mCharged;
private boolean mPowerSave;
private boolean mAodPowerSave;
diff --git a/packages/SystemUI/src/com/android/systemui/usb/StorageNotification.java b/packages/SystemUI/src/com/android/systemui/usb/StorageNotification.java
index 11885c55b51d..442c7eaae729 100644
--- a/packages/SystemUI/src/com/android/systemui/usb/StorageNotification.java
+++ b/packages/SystemUI/src/com/android/systemui/usb/StorageNotification.java
@@ -187,8 +187,9 @@ public class StorageNotification extends SystemUI {
}
private void updateMissingPrivateVolumes() {
- if (isTv()) {
+ if (isTv() || isAutomotive()) {
// On TV, TvSettings displays a modal full-screen activity in this case.
+ // Not applicable for automotive.
return;
}
@@ -595,6 +596,9 @@ public class StorageNotification extends SystemUI {
if (isTv()) {
intent.setPackage("com.android.tv.settings");
intent.setAction("com.android.tv.settings.action.NEW_STORAGE");
+ } else if (isAutomotive()) {
+ // TODO(b/151671685): add intent to handle unsupported usb
+ return null;
} else {
intent.setClassName("com.android.settings",
"com.android.settings.deviceinfo.StorageWizardInit");
@@ -611,6 +615,9 @@ public class StorageNotification extends SystemUI {
if (isTv()) {
intent.setPackage("com.android.tv.settings");
intent.setAction("com.android.tv.settings.action.NEW_STORAGE");
+ } else if (isAutomotive()) {
+ // TODO(b/151671685): add intent to handle unmountable usb
+ return null;
} else {
intent.setClassName("com.android.settings",
"com.android.settings.deviceinfo.StorageWizardInit");
@@ -669,6 +676,9 @@ public class StorageNotification extends SystemUI {
if (isTv()) {
intent.setPackage("com.android.tv.settings");
intent.setAction(Settings.ACTION_INTERNAL_STORAGE_SETTINGS);
+ } else if (isAutomotive()) {
+ // TODO(b/151671685): add volume settings intent for automotive
+ return null;
} else {
switch (vol.getType()) {
case VolumeInfo.TYPE_PRIVATE:
@@ -700,7 +710,7 @@ public class StorageNotification extends SystemUI {
}
private PendingIntent buildForgetPendingIntent(VolumeRecord rec) {
- // Not used on TV
+ // Not used on TV and Automotive
final Intent intent = new Intent();
intent.setClassName("com.android.settings",
"com.android.settings.Settings$PrivateVolumeForgetActivity");
@@ -716,6 +726,9 @@ public class StorageNotification extends SystemUI {
if (isTv()) {
intent.setPackage("com.android.tv.settings");
intent.setAction("com.android.tv.settings.action.MIGRATE_STORAGE");
+ } else if (isAutomotive()) {
+ // TODO(b/151671685): add storage migrate intent for automotive
+ return null;
} else {
intent.setClassName("com.android.settings",
"com.android.settings.deviceinfo.StorageWizardMigrateProgress");
@@ -735,6 +748,9 @@ public class StorageNotification extends SystemUI {
if (isTv()) {
intent.setPackage("com.android.tv.settings");
intent.setAction("com.android.tv.settings.action.MOVE_APP");
+ } else if (isAutomotive()) {
+ // TODO(b/151671685): add storage move intent for automotive
+ return null;
} else {
intent.setClassName("com.android.settings",
"com.android.settings.deviceinfo.StorageWizardMoveProgress");
@@ -750,6 +766,9 @@ public class StorageNotification extends SystemUI {
if (isTv()) {
intent.setPackage("com.android.tv.settings");
intent.setAction(Settings.ACTION_INTERNAL_STORAGE_SETTINGS);
+ } else if (isAutomotive()) {
+ // TODO(b/151671685): add storage ready intent for automotive
+ return null;
} else {
intent.setClassName("com.android.settings",
"com.android.settings.deviceinfo.StorageWizardReady");
diff --git a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardUpdateMonitorTest.java b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardUpdateMonitorTest.java
index 9d9ba1bc91b9..eecde7218d28 100644
--- a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardUpdateMonitorTest.java
+++ b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardUpdateMonitorTest.java
@@ -52,6 +52,7 @@ import android.hardware.face.FaceManager;
import android.hardware.fingerprint.FingerprintManager;
import android.os.Bundle;
import android.os.Handler;
+import android.os.IRemoteCallback;
import android.os.UserHandle;
import android.os.UserManager;
import android.telephony.ServiceState;
@@ -63,6 +64,7 @@ import android.testing.TestableContext;
import android.testing.TestableLooper;
import com.android.internal.telephony.TelephonyIntents;
+import com.android.keyguard.KeyguardUpdateMonitor.BiometricAuthenticated;
import com.android.systemui.SysuiTestCase;
import com.android.systemui.broadcast.BroadcastDispatcher;
import com.android.systemui.dump.DumpManager;
@@ -506,6 +508,24 @@ public class KeyguardUpdateMonitorTest extends SysuiTestCase {
}
@Test
+ public void testBiometricsCleared_whenUserSwitches() throws Exception {
+ final IRemoteCallback reply = new IRemoteCallback.Stub() {
+ @Override
+ public void sendResult(Bundle data) {} // do nothing
+ };
+ final BiometricAuthenticated dummyAuthentication =
+ new BiometricAuthenticated(true /* authenticated */, true /* strong */);
+ mKeyguardUpdateMonitor.mUserFaceAuthenticated.put(0 /* user */, dummyAuthentication);
+ mKeyguardUpdateMonitor.mUserFingerprintAuthenticated.put(0 /* user */, dummyAuthentication);
+ assertThat(mKeyguardUpdateMonitor.mUserFingerprintAuthenticated.size()).isEqualTo(1);
+ assertThat(mKeyguardUpdateMonitor.mUserFaceAuthenticated.size()).isEqualTo(1);
+
+ mKeyguardUpdateMonitor.handleUserSwitching(10 /* user */, reply);
+ assertThat(mKeyguardUpdateMonitor.mUserFingerprintAuthenticated.size()).isEqualTo(0);
+ assertThat(mKeyguardUpdateMonitor.mUserFaceAuthenticated.size()).isEqualTo(0);
+ }
+
+ @Test
public void testGetUserCanSkipBouncer_whenTrust() {
int user = KeyguardUpdateMonitor.getCurrentUser();
mKeyguardUpdateMonitor.onTrustChanged(true /* enabled */, user, 0 /* flags */);
diff --git a/packages/SystemUI/tests/src/com/android/systemui/biometrics/AuthContainerViewTest.java b/packages/SystemUI/tests/src/com/android/systemui/biometrics/AuthContainerViewTest.java
index 1db8e4c3d73e..74d0610ee0d6 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/biometrics/AuthContainerViewTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/biometrics/AuthContainerViewTest.java
@@ -34,6 +34,7 @@ import static org.mockito.Mockito.when;
import android.content.Context;
import android.hardware.biometrics.BiometricAuthenticator;
+import android.hardware.biometrics.BiometricConstants;
import android.hardware.biometrics.BiometricPrompt;
import android.os.Bundle;
import android.os.IBinder;
@@ -89,6 +90,8 @@ public class AuthContainerViewTest extends SysuiTestCase {
mAuthContainer.mBiometricCallback.onAction(
AuthBiometricView.Callback.ACTION_USER_CANCELED);
+ verify(mCallback).onSystemEvent(eq(
+ BiometricConstants.BIOMETRIC_SYSTEM_EVENT_EARLY_USER_CANCEL));
verify(mCallback).onDismissed(
eq(AuthDialogCallback.DISMISSED_USER_CANCELED),
eq(null) /* credentialAttestation */);
diff --git a/packages/SystemUI/tests/src/com/android/systemui/controls/controller/ControlsControllerImplTest.kt b/packages/SystemUI/tests/src/com/android/systemui/controls/controller/ControlsControllerImplTest.kt
index eb4d438600d8..93aee33cc1c8 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/controls/controller/ControlsControllerImplTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/controls/controller/ControlsControllerImplTest.kt
@@ -161,7 +161,7 @@ class ControlsControllerImplTest : SysuiTestCase() {
verify(listingController).addCallback(capture(listingCallbackCaptor))
}
- private fun builderFromInfo(
+ private fun statelessBuilderFromInfo(
controlInfo: ControlInfo,
structure: CharSequence = ""
): Control.StatelessBuilder {
@@ -170,6 +170,15 @@ class ControlsControllerImplTest : SysuiTestCase() {
.setSubtitle(controlInfo.controlSubtitle).setStructure(structure)
}
+ private fun statefulBuilderFromInfo(
+ controlInfo: ControlInfo,
+ structure: CharSequence = ""
+ ): Control.StatefulBuilder {
+ return Control.StatefulBuilder(controlInfo.controlId, pendingIntent)
+ .setDeviceType(controlInfo.deviceType).setTitle(controlInfo.controlTitle)
+ .setSubtitle(controlInfo.controlSubtitle).setStructure(structure)
+ }
+
@Test
fun testStartOnUser() {
assertEquals(user, controller.currentUserId)
@@ -236,7 +245,7 @@ class ControlsControllerImplTest : SysuiTestCase() {
@Test
fun testLoadForComponent_noFavorites() {
var loaded = false
- val control = builderFromInfo(TEST_CONTROL_INFO).build()
+ val control = statelessBuilderFromInfo(TEST_CONTROL_INFO).build()
controller.loadForComponent(TEST_COMPONENT, Consumer { data ->
val controls = data.allControls
@@ -263,8 +272,8 @@ class ControlsControllerImplTest : SysuiTestCase() {
@Test
fun testLoadForComponent_favorites() {
var loaded = false
- val control = builderFromInfo(TEST_CONTROL_INFO).build()
- val control2 = builderFromInfo(TEST_CONTROL_INFO_2).build()
+ val control = statelessBuilderFromInfo(TEST_CONTROL_INFO).build()
+ val control2 = statelessBuilderFromInfo(TEST_CONTROL_INFO_2).build()
controller.replaceFavoritesForStructure(TEST_STRUCTURE_INFO)
controller.replaceFavoritesForStructure(TEST_STRUCTURE_INFO_2)
delayableExecutor.runAllReady()
@@ -445,7 +454,7 @@ class ControlsControllerImplTest : SysuiTestCase() {
delayableExecutor.runAllReady()
val newControlInfo = TEST_CONTROL_INFO.copy(controlTitle = TEST_CONTROL_TITLE_2)
- val control = builderFromInfo(newControlInfo).build()
+ val control = statelessBuilderFromInfo(newControlInfo).build()
controller.loadForComponent(TEST_COMPONENT, Consumer {})
@@ -461,11 +470,11 @@ class ControlsControllerImplTest : SysuiTestCase() {
}
@Test
- fun testFavoriteInformationModifiedOnRefresh() {
+ fun testFavoriteInformationModifiedOnRefreshWithOkStatus() {
controller.replaceFavoritesForStructure(TEST_STRUCTURE_INFO)
val newControlInfo = TEST_CONTROL_INFO.copy(controlTitle = TEST_CONTROL_TITLE_2)
- val control = builderFromInfo(newControlInfo).build()
+ val control = statefulBuilderFromInfo(newControlInfo).setStatus(Control.STATUS_OK).build()
controller.refreshStatus(TEST_COMPONENT, control)
@@ -477,6 +486,23 @@ class ControlsControllerImplTest : SysuiTestCase() {
}
@Test
+ fun testFavoriteInformationNotModifiedOnRefreshWithNonOkStatus() {
+ controller.replaceFavoritesForStructure(TEST_STRUCTURE_INFO)
+
+ val newControlInfo = TEST_CONTROL_INFO.copy(controlTitle = TEST_CONTROL_TITLE_2)
+ val control = statefulBuilderFromInfo(newControlInfo).setStatus(Control.STATUS_ERROR)
+ .build()
+
+ controller.refreshStatus(TEST_COMPONENT, control)
+
+ delayableExecutor.runAllReady()
+
+ val favorites = controller.getFavorites().flatMap { it.controls }
+ assertEquals(1, favorites.size)
+ assertEquals(TEST_CONTROL_INFO, favorites[0])
+ }
+
+ @Test
fun testSwitchUsers() {
controller.replaceFavoritesForStructure(TEST_STRUCTURE_INFO)
delayableExecutor.runAllReady()
@@ -762,7 +788,8 @@ class ControlsControllerImplTest : SysuiTestCase() {
@Test
fun testSeedFavoritesForComponent() {
var succeeded = false
- val control = builderFromInfo(TEST_CONTROL_INFO, TEST_STRUCTURE_INFO.structure).build()
+ val control = statelessBuilderFromInfo(TEST_CONTROL_INFO, TEST_STRUCTURE_INFO.structure)
+ .build()
controller.seedFavoritesForComponent(TEST_COMPONENT, Consumer { accepted ->
succeeded = accepted
@@ -803,7 +830,8 @@ class ControlsControllerImplTest : SysuiTestCase() {
fun testSeedFavoritesForComponent_inProgressCallback() {
var succeeded = false
var seeded = false
- val control = builderFromInfo(TEST_CONTROL_INFO, TEST_STRUCTURE_INFO.structure).build()
+ val control = statelessBuilderFromInfo(TEST_CONTROL_INFO, TEST_STRUCTURE_INFO.structure)
+ .build()
controller.seedFavoritesForComponent(TEST_COMPONENT, Consumer { accepted ->
succeeded = accepted
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/KeyguardIndicationControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/KeyguardIndicationControllerTest.java
index fb401778d891..be5b190b54a5 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/KeyguardIndicationControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/KeyguardIndicationControllerTest.java
@@ -192,8 +192,7 @@ public class KeyguardIndicationControllerTest extends SysuiTestCase {
assertThat(mTextView.getText()).isEqualTo(
mContext.getResources().getString(R.string.dock_alignment_slow_charging));
- assertThat(mTextView.getCurrentTextColor()).isEqualTo(
- Utils.getColorError(mContext).getDefaultColor());
+ assertThat(mTextView.getCurrentTextColor()).isEqualTo(Color.WHITE);
}
@Test
@@ -210,8 +209,7 @@ public class KeyguardIndicationControllerTest extends SysuiTestCase {
assertThat(mTextView.getText()).isEqualTo(
mContext.getResources().getString(R.string.dock_alignment_not_charging));
- assertThat(mTextView.getCurrentTextColor()).isEqualTo(
- Utils.getColorError(mContext).getDefaultColor());
+ assertThat(mTextView.getCurrentTextColor()).isEqualTo(Color.WHITE);
}
@Test
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/KeyguardBouncerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/KeyguardBouncerTest.java
index 35971bd4037c..e052ae2653f0 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/KeyguardBouncerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/KeyguardBouncerTest.java
@@ -26,6 +26,7 @@ import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.doAnswer;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.reset;
+import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.verifyNoMoreInteractions;
import static org.mockito.Mockito.verifyZeroInteractions;
@@ -56,11 +57,13 @@ import com.android.systemui.statusbar.policy.KeyguardStateController;
import org.junit.Assert;
import org.junit.Before;
+import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.ArgumentCaptor;
import org.mockito.Mock;
-import org.mockito.MockitoAnnotations;
+import org.mockito.junit.MockitoJUnit;
+import org.mockito.junit.MockitoRule;
@SmallTest
@RunWith(AndroidTestingRunner.class)
@@ -91,13 +94,14 @@ public class KeyguardBouncerTest extends SysuiTestCase {
private Handler mHandler;
@Mock
private KeyguardSecurityModel mKeyguardSecurityModel;
-
+ @Rule
+ public MockitoRule mRule = MockitoJUnit.rule();
+ private ViewGroup mRootView;
private KeyguardBouncer mBouncer;
@Before
public void setup() {
allowTestableLooperAsMainThread();
- MockitoAnnotations.initMocks(this);
mDependency.injectTestDependency(KeyguardUpdateMonitor.class, mKeyguardUpdateMonitor);
mDependency.injectTestDependency(KeyguardSecurityModel.class, mKeyguardSecurityModel);
mDependency.injectMockDependency(KeyguardStateController.class);
@@ -115,6 +119,8 @@ public class KeyguardBouncerTest extends SysuiTestCase {
protected void inflateView() {
super.inflateView();
mKeyguardView = mKeyguardHostView;
+ mRoot = spy(mRoot);
+ mRootView = mRoot;
}
};
}
@@ -217,6 +223,7 @@ public class KeyguardBouncerTest extends SysuiTestCase {
mBouncer.setExpansion(0);
verify(mKeyguardHostView).onResume();
+ verify(mRootView).announceForAccessibility(any());
}
@Test
diff --git a/packages/Tethering/common/TetheringLib/Android.bp b/packages/Tethering/common/TetheringLib/Android.bp
index 6af5fe54f281..31c40d2a3343 100644
--- a/packages/Tethering/common/TetheringLib/Android.bp
+++ b/packages/Tethering/common/TetheringLib/Android.bp
@@ -65,12 +65,7 @@ java_library {
stubs_defaults {
name: "framework-tethering-stubs-defaults",
- srcs: [
- "src/android/net/TetheredClient.java",
- "src/android/net/TetheringManager.java",
- "src/android/net/TetheringConstants.java",
- ],
- libs: ["tethering-aidl-interfaces-java"],
+ srcs: [":framework-tethering-srcs"],
}
filegroup {
diff --git a/packages/Tethering/src/com/android/server/connectivity/tethering/Tethering.java b/packages/Tethering/src/com/android/server/connectivity/tethering/Tethering.java
index c84892d675f9..4b2c9215f7b7 100644
--- a/packages/Tethering/src/com/android/server/connectivity/tethering/Tethering.java
+++ b/packages/Tethering/src/com/android/server/connectivity/tethering/Tethering.java
@@ -307,28 +307,22 @@ public class Tethering {
userManager, this, mNotificationUpdater);
mExecutor = new TetheringThreadExecutor(mHandler);
mActiveDataSubIdListener = new ActiveDataSubIdListener(mExecutor);
+ mNetdCallback = new NetdCallback();
// Load tethering configuration.
updateConfiguration();
- // NetdCallback should be registered after updateConfiguration() to ensure
- // TetheringConfiguration is created.
- mNetdCallback = new NetdCallback();
+ }
+
+ /**
+ * Start to register callbacks.
+ * Call this function when tethering is ready to handle callback events.
+ */
+ public void startStateMachineUpdaters() {
try {
mNetd.registerUnsolicitedEventListener(mNetdCallback);
} catch (RemoteException e) {
mLog.e("Unable to register netd UnsolicitedEventListener");
}
-
- startStateMachineUpdaters(mHandler);
- startTrackDefaultNetwork();
-
- final WifiManager wifiManager = getWifiManager();
- if (wifiManager != null) {
- wifiManager.registerSoftApCallback(mExecutor, new TetheringSoftApCallback());
- }
- }
-
- private void startStateMachineUpdaters(Handler handler) {
mCarrierConfigChange.startListening();
mContext.getSystemService(TelephonyManager.class).listen(mActiveDataSubIdListener,
PhoneStateListener.LISTEN_ACTIVE_DATA_SUBSCRIPTION_ID_CHANGE);
@@ -341,7 +335,14 @@ public class Tethering {
filter.addAction(WifiP2pManager.WIFI_P2P_CONNECTION_CHANGED_ACTION);
filter.addAction(UserManager.ACTION_USER_RESTRICTIONS_CHANGED);
filter.addAction(ACTION_RESTRICT_BACKGROUND_CHANGED);
- mContext.registerReceiver(mStateReceiver, filter, null, handler);
+ mContext.registerReceiver(mStateReceiver, filter, null, mHandler);
+
+ final WifiManager wifiManager = getWifiManager();
+ if (wifiManager != null) {
+ wifiManager.registerSoftApCallback(mExecutor, new TetheringSoftApCallback());
+ }
+
+ startTrackDefaultNetwork();
}
private class TetheringThreadExecutor implements Executor {
diff --git a/packages/Tethering/src/com/android/server/connectivity/tethering/TetheringService.java b/packages/Tethering/src/com/android/server/connectivity/tethering/TetheringService.java
index c5329d8d3316..c30be25dbd22 100644
--- a/packages/Tethering/src/com/android/server/connectivity/tethering/TetheringService.java
+++ b/packages/Tethering/src/com/android/server/connectivity/tethering/TetheringService.java
@@ -80,6 +80,7 @@ public class TetheringService extends Service {
mContext = mDeps.getContext();
mUserManager = (UserManager) mContext.getSystemService(Context.USER_SERVICE);
mTethering = makeTethering(mDeps);
+ mTethering.startStateMachineUpdaters();
}
/**
diff --git a/packages/Tethering/tests/unit/src/com/android/server/connectivity/tethering/TetheringTest.java b/packages/Tethering/tests/unit/src/com/android/server/connectivity/tethering/TetheringTest.java
index 5ead1106d75a..a59c6fd9e193 100644
--- a/packages/Tethering/tests/unit/src/com/android/server/connectivity/tethering/TetheringTest.java
+++ b/packages/Tethering/tests/unit/src/com/android/server/connectivity/tethering/TetheringTest.java
@@ -484,6 +484,7 @@ public class TetheringTest {
mServiceContext.registerReceiver(mBroadcastReceiver,
new IntentFilter(ACTION_TETHER_STATE_CHANGED));
mTethering = makeTethering();
+ mTethering.startStateMachineUpdaters();
verify(mStatsManager, times(1)).registerNetworkStatsProvider(anyString(), any());
verify(mNetd).registerUnsolicitedEventListener(any());
final ArgumentCaptor<PhoneStateListener> phoneListenerCaptor =
diff --git a/services/Android.bp b/services/Android.bp
index 52c5993a2862..1ce7dcfff03b 100644
--- a/services/Android.bp
+++ b/services/Android.bp
@@ -126,6 +126,7 @@ droidstubs {
" --hide DeprecationMismatch" +
" --hide HiddenTypedefConstant",
visibility: ["//visibility:private"],
+ filter_packages: ["com.android."],
check_api: {
current: {
api_file: "api/current.txt",
diff --git a/services/contentcapture/java/com/android/server/contentcapture/ContentCapturePerUserService.java b/services/contentcapture/java/com/android/server/contentcapture/ContentCapturePerUserService.java
index 32bca35009a8..9486b0d39bc2 100644
--- a/services/contentcapture/java/com/android/server/contentcapture/ContentCapturePerUserService.java
+++ b/services/contentcapture/java/com/android/server/contentcapture/ContentCapturePerUserService.java
@@ -17,7 +17,7 @@
package com.android.server.contentcapture;
import static android.service.contentcapture.ContentCaptureService.setClientState;
-import static android.view.contentcapture.ContentCaptureSession.NO_SESSION_ID;
+import static android.view.contentcapture.ContentCaptureManager.NO_SESSION_ID;
import static android.view.contentcapture.ContentCaptureSession.STATE_DISABLED;
import static android.view.contentcapture.ContentCaptureSession.STATE_DUPLICATED_ID;
import static android.view.contentcapture.ContentCaptureSession.STATE_INTERNAL_ERROR;
diff --git a/services/contentcapture/java/com/android/server/contentcapture/ContentCaptureServerSession.java b/services/contentcapture/java/com/android/server/contentcapture/ContentCaptureServerSession.java
index aa63e40747ee..06ab426c6698 100644
--- a/services/contentcapture/java/com/android/server/contentcapture/ContentCaptureServerSession.java
+++ b/services/contentcapture/java/com/android/server/contentcapture/ContentCaptureServerSession.java
@@ -16,9 +16,9 @@
package com.android.server.contentcapture;
import static android.service.contentcapture.ContentCaptureService.setClientState;
+import static android.view.contentcapture.ContentCaptureManager.NO_SESSION_ID;
import static android.view.contentcapture.ContentCaptureManager.RESULT_CODE_FALSE;
import static android.view.contentcapture.ContentCaptureManager.RESULT_CODE_TRUE;
-import static android.view.contentcapture.ContentCaptureSession.NO_SESSION_ID;
import static android.view.contentcapture.ContentCaptureSession.STATE_ACTIVE;
import static android.view.contentcapture.ContentCaptureSession.STATE_DISABLED;
import static android.view.contentcapture.ContentCaptureSession.STATE_SERVICE_RESURRECTED;
diff --git a/services/core/java/com/android/server/ConnectivityService.java b/services/core/java/com/android/server/ConnectivityService.java
index 76a8e1474a95..237a961fd338 100644
--- a/services/core/java/com/android/server/ConnectivityService.java
+++ b/services/core/java/com/android/server/ConnectivityService.java
@@ -7967,10 +7967,13 @@ public class ConnectivityService extends IConnectivityManager.Stub
return false;
}
+ final Network[] underlyingNetworks;
synchronized (mVpns) {
- if (getVpnIfOwner(callbackUid) != null) {
- return true;
- }
+ final Vpn vpn = getVpnIfOwner(callbackUid);
+ underlyingNetworks = (vpn == null) ? null : vpn.getUnderlyingNetworks();
+ }
+ if (underlyingNetworks != null) {
+ if (Arrays.asList(underlyingNetworks).contains(nai.network)) return true;
}
// Administrator UIDs also contains the Owner UID
diff --git a/services/core/java/com/android/server/NetworkManagementService.java b/services/core/java/com/android/server/NetworkManagementService.java
index 1bb3c3ac0cda..0ddfa1c16a0a 100644
--- a/services/core/java/com/android/server/NetworkManagementService.java
+++ b/services/core/java/com/android/server/NetworkManagementService.java
@@ -886,6 +886,7 @@ public class NetworkManagementService extends INetworkManagementService.Stub {
@Override
public void setIPv6AddrGenMode(String iface, int mode) throws ServiceSpecificException {
+ NetworkStack.checkNetworkStackPermission(mContext);
try {
mNetdService.setIPv6AddrGenMode(iface, mode);
} catch (RemoteException e) {
diff --git a/services/core/java/com/android/server/PackageWatchdog.java b/services/core/java/com/android/server/PackageWatchdog.java
index 41a104c5d4dc..d9e7c3851906 100644
--- a/services/core/java/com/android/server/PackageWatchdog.java
+++ b/services/core/java/com/android/server/PackageWatchdog.java
@@ -1062,7 +1062,12 @@ public class PackageWatchdog {
public void updatePackagesLocked(List<MonitoredPackage> packages) {
for (int pIndex = 0; pIndex < packages.size(); pIndex++) {
MonitoredPackage p = packages.get(pIndex);
- this.packages.put(p.getName(), p);
+ MonitoredPackage existingPackage = this.packages.get(p.getName());
+ if (existingPackage != null) {
+ existingPackage.updateHealthCheckDuration(p.mDurationMs);
+ } else {
+ this.packages.put(p.getName(), p);
+ }
}
}
@@ -1331,6 +1336,12 @@ public class PackageWatchdog {
return updateHealthCheckStateLocked();
}
+ /** Explicitly update the monitoring duration of the package. */
+ @GuardedBy("mLock")
+ public void updateHealthCheckDuration(long newDurationMs) {
+ mDurationMs = newDurationMs;
+ }
+
/**
* Marks the health check as passed and transitions to {@link HealthCheckState.PASSED}
* if not yet {@link HealthCheckState.FAILED}.
diff --git a/services/core/java/com/android/server/StorageManagerService.java b/services/core/java/com/android/server/StorageManagerService.java
index 4d8c86c87e9e..9018caa8d7b6 100644
--- a/services/core/java/com/android/server/StorageManagerService.java
+++ b/services/core/java/com/android/server/StorageManagerService.java
@@ -4459,8 +4459,9 @@ class StorageManagerService extends IStorageManager.Stub
String.format("/storage/emulated/%d/Android/data/%s/",
userId, pkg);
+ int appUid =
+ UserHandle.getUid(userId, mPmInternal.getPackage(pkg).getUid());
// Create package obb and data dir if it doesn't exist.
- int appUid = UserHandle.getUid(userId, mPmInternal.getPackage(pkg).getUid());
File file = new File(packageObbDir);
if (!file.exists()) {
vold.setupAppDir(packageObbDir, appUid);
diff --git a/services/core/java/com/android/server/TelephonyRegistry.java b/services/core/java/com/android/server/TelephonyRegistry.java
index 895282c5cb59..2bbf27849005 100644
--- a/services/core/java/com/android/server/TelephonyRegistry.java
+++ b/services/core/java/com/android/server/TelephonyRegistry.java
@@ -27,6 +27,7 @@ import android.annotation.NonNull;
import android.annotation.Nullable;
import android.app.ActivityManager;
import android.app.AppOpsManager;
+import android.app.compat.CompatChanges;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
@@ -39,8 +40,10 @@ import android.os.Bundle;
import android.os.Handler;
import android.os.IBinder;
import android.os.Message;
+import android.os.Process;
import android.os.RemoteException;
import android.os.UserHandle;
+import android.provider.DeviceConfig;
import android.telephony.Annotation;
import android.telephony.Annotation.ApnType;
import android.telephony.Annotation.DataFailureCause;
@@ -177,8 +180,38 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub {
}
}
+ /**
+ * Wrapper class to facilitate testing -- encapsulates bits of configuration that are
+ * normally fetched from static methods with many dependencies.
+ */
+ public static class ConfigurationProvider {
+ /**
+ * @return The per-pid registration limit for PhoneStateListeners, as set from DeviceConfig
+ * @noinspection ConstantConditions
+ */
+ public int getRegistrationLimit() {
+ return Binder.withCleanCallingIdentity(() ->
+ DeviceConfig.getInt(DeviceConfig.NAMESPACE_TELEPHONY,
+ PhoneStateListener.FLAG_PER_PID_REGISTRATION_LIMIT,
+ PhoneStateListener.DEFAULT_PER_PID_REGISTRATION_LIMIT));
+ }
+
+ /**
+ * @param uid uid to check
+ * @return Whether enforcement of the per-pid registation limit for PhoneStateListeners is
+ * enabled in PlatformCompat for the given uid.
+ * @noinspection ConstantConditions
+ */
+ public boolean isRegistrationLimitEnabledInPlatformCompat(int uid) {
+ return Binder.withCleanCallingIdentity(() -> CompatChanges.isChangeEnabled(
+ PhoneStateListener.PHONE_STATE_LISTENER_LIMIT_CHANGE_ID, uid));
+ }
+ }
+
private final Context mContext;
+ private ConfigurationProvider mConfigurationProvider;
+
// access should be inside synchronized (mRecords) for these two fields
private final ArrayList<IBinder> mRemoveList = new ArrayList<IBinder>();
private final ArrayList<Record> mRecords = new ArrayList<Record>();
@@ -506,10 +539,11 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub {
// handler before they get to app code.
@VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
- public TelephonyRegistry(Context context) {
+ public TelephonyRegistry(Context context, ConfigurationProvider configurationProvider) {
CellLocation location = CellLocation.getEmpty();
mContext = context;
+ mConfigurationProvider = configurationProvider;
mBatteryStats = BatteryStatsService.getService();
int numPhones = getTelephonyManager().getActiveModemCount();
@@ -605,7 +639,7 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub {
synchronized (mRecords) {
// register
IBinder b = callback.asBinder();
- Record r = add(b);
+ Record r = add(b, Binder.getCallingUid(), Binder.getCallingPid(), false);
if (r == null) {
return;
@@ -659,7 +693,7 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub {
synchronized (mRecords) {
// register
IBinder b = callback.asBinder();
- Record r = add(b);
+ Record r = add(b, Binder.getCallingUid(), Binder.getCallingPid(), false);
if (r == null) {
return;
@@ -789,7 +823,11 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub {
synchronized (mRecords) {
// register
IBinder b = callback.asBinder();
- Record r = add(b);
+ boolean doesLimitApply =
+ Binder.getCallingUid() != Process.SYSTEM_UID
+ && Binder.getCallingUid() != Process.PHONE_UID
+ && Binder.getCallingUid() != Process.myUid();
+ Record r = add(b, Binder.getCallingUid(), Binder.getCallingPid(), doesLimitApply);
if (r == null) {
return;
@@ -1084,18 +1122,44 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub {
return record.canReadCallLog() ? mCallIncomingNumber[phoneId] : "";
}
- private Record add(IBinder binder) {
+ private Record add(IBinder binder, int callingUid, int callingPid, boolean doesLimitApply) {
Record r;
synchronized (mRecords) {
final int N = mRecords.size();
+ // While iterating through the records, keep track of how many we have from this pid.
+ int numRecordsForPid = 0;
for (int i = 0; i < N; i++) {
r = mRecords.get(i);
if (binder == r.binder) {
// Already existed.
return r;
}
+ if (r.callerPid == callingPid) {
+ numRecordsForPid++;
+ }
}
+ // If we've exceeded the limit for registrations, log an error and quit.
+ int registrationLimit = mConfigurationProvider.getRegistrationLimit();
+
+ if (doesLimitApply
+ && registrationLimit >= 1
+ && numRecordsForPid >= registrationLimit) {
+ String errorMsg = "Pid " + callingPid + " has exceeded the number of permissible"
+ + "registered listeners. Ignoring request to add.";
+ loge(errorMsg);
+ if (mConfigurationProvider
+ .isRegistrationLimitEnabledInPlatformCompat(callingUid)) {
+ throw new IllegalStateException(errorMsg);
+ }
+ } else if (doesLimitApply && numRecordsForPid
+ >= PhoneStateListener.DEFAULT_PER_PID_REGISTRATION_LIMIT / 2) {
+ // Log the warning independently of the dynamically set limit -- apps shouldn't be
+ // doing this regardless of whether we're throwing them an exception for it.
+ Rlog.w(TAG, "Pid " + callingPid + " has exceeded half the number of permissible"
+ + "registered listeners. Now at " + numRecordsForPid);
+ }
+
r = new Record();
r.binder = binder;
r.deathRecipient = new TelephonyRegistryDeathRecipient(binder);
diff --git a/services/core/java/com/android/server/VibratorService.java b/services/core/java/com/android/server/VibratorService.java
index dd9cc641f2dd..ac4a42ca7024 100644
--- a/services/core/java/com/android/server/VibratorService.java
+++ b/services/core/java/com/android/server/VibratorService.java
@@ -605,15 +605,16 @@ public class VibratorService extends IVibratorService.Stub
}
@Override // Binder call
- public boolean[] areEffectsSupported(int[] effectIds) {
- // Return null to indicate that the HAL doesn't actually tell us what effects are
- // supported.
+ public int[] areEffectsSupported(int[] effectIds) {
+ int[] supported = new int[effectIds.length];
if (mSupportedEffects == null) {
- return null;
- }
- boolean[] supported = new boolean[effectIds.length];
- for (int i = 0; i < effectIds.length; i++) {
- supported[i] = mSupportedEffects.contains(effectIds[i]);
+ Arrays.fill(supported, Vibrator.VIBRATION_EFFECT_SUPPORT_UNKNOWN);
+ } else {
+ for (int i = 0; i < effectIds.length; i++) {
+ supported[i] = mSupportedEffects.contains(effectIds[i])
+ ? Vibrator.VIBRATION_EFFECT_SUPPORT_YES
+ : Vibrator.VIBRATION_EFFECT_SUPPORT_NO;
+ }
}
return supported;
}
diff --git a/services/core/java/com/android/server/am/ActiveServices.java b/services/core/java/com/android/server/am/ActiveServices.java
index d77bee35a89b..714aae1b70ca 100644
--- a/services/core/java/com/android/server/am/ActiveServices.java
+++ b/services/core/java/com/android/server/am/ActiveServices.java
@@ -4898,6 +4898,12 @@ public final class ActiveServices {
return true;
}
+ // Is the calling UID a device owner app?
+ final boolean isDeviceOwner = mAm.mInternal.isDeviceOwner(callingUid);
+ if (isDeviceOwner) {
+ return true;
+ }
+
r.mInfoDenyWhileInUsePermissionInFgs =
"Background FGS start while-in-use permission restriction [callingPackage: "
+ callingPackage
@@ -4933,7 +4939,8 @@ public final class ActiveServices {
+ r.mRecentCallingPackage
+ "; intent:" + r.intent.getIntent()
+ "] affected while-in-use permission:"
- + AppOpsManager.opToPublicName(op);
+ + AppOpsManager.opToPublicName(op)
+ + "; targetSdkVersion:" + r.appInfo.targetSdkVersion;
Slog.wtf(TAG, msg);
}
}
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index 8b2976d0e878..73d6fff37ac1 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -185,8 +185,6 @@ import android.app.PendingIntent;
import android.app.ProcessMemoryState;
import android.app.ProfilerInfo;
import android.app.WaitResult;
-import android.app.WindowConfiguration.ActivityType;
-import android.app.WindowConfiguration.WindowingMode;
import android.app.backup.IBackupManager;
import android.app.usage.UsageEvents;
import android.app.usage.UsageEvents.Event;
@@ -638,6 +636,8 @@ public class ActivityManagerService extends IActivityManager.Stub
*/
String mDeviceOwnerName;
+ private int mDeviceOwnerUid = Process.INVALID_UID;
+
final UserController mUserController;
@VisibleForTesting
public final PendingIntentController mPendingIntentController;
@@ -6513,13 +6513,6 @@ public class ActivityManagerService extends IActivityManager.Stub
}
@Override
- public List<RunningTaskInfo> getFilteredTasks(int maxNum, @ActivityType int ignoreActivityType,
- @WindowingMode int ignoreWindowingMode) {
- return mActivityTaskManager.getFilteredTasks(
- maxNum, ignoreActivityType, ignoreWindowingMode);
- }
-
- @Override
public void cancelTaskWindowTransition(int taskId) {
mActivityTaskManager.cancelTaskWindowTransition(taskId);
}
@@ -19500,6 +19493,20 @@ public class ActivityManagerService extends IActivityManager.Stub
uid, op, mode);
}
}
+
+ @Override
+ public void setDeviceOwnerUid(int uid) {
+ synchronized (ActivityManagerService.this) {
+ mDeviceOwnerUid = uid;
+ }
+ }
+
+ @Override
+ public boolean isDeviceOwner(int uid) {
+ synchronized (ActivityManagerService.this) {
+ return uid >= 0 && mDeviceOwnerUid == uid;
+ }
+ }
}
long inputDispatchingTimedOut(int pid, final boolean aboveSystem, String reason) {
diff --git a/services/core/java/com/android/server/am/OomAdjuster.java b/services/core/java/com/android/server/am/OomAdjuster.java
index d4a05025499f..1412112651c4 100644
--- a/services/core/java/com/android/server/am/OomAdjuster.java
+++ b/services/core/java/com/android/server/am/OomAdjuster.java
@@ -151,10 +151,14 @@ public final class OomAdjuster {
@EnabledAfter(targetSdkVersion=android.os.Build.VERSION_CODES.Q)
static final long CAMERA_MICROPHONE_CAPABILITY_CHANGE_ID = 136219221L;
- //TODO: remove this when development is done.
- private static final int TEMP_PROCESS_CAPABILITY_FOREGROUND_LOCATION = 1 << 31;
- private static final int TEMP_PROCESS_CAPABILITY_FOREGROUND_CAMERA = 1 << 30;
- private static final int TEMP_PROCESS_CAPABILITY_FOREGROUND_MICROPHONE = 1 << 29;
+ // TODO: remove this when development is done.
+ // These are debug flags used between OomAdjuster and AppOpsService to detect and report absence
+ // of the real flags.
+ public static final int DEBUG_PROCESS_CAPABILITY_FOREGROUND_MICROPHONE_Q = 1 << 27;
+ public static final int DEBUG_PROCESS_CAPABILITY_FOREGROUND_CAMERA_Q = 1 << 28;
+ public static final int DEBUG_PROCESS_CAPABILITY_FOREGROUND_MICROPHONE = 1 << 29;
+ public static final int DEBUG_PROCESS_CAPABILITY_FOREGROUND_CAMERA = 1 << 30;
+ public static final int DEBUG_PROCESS_CAPABILITY_FOREGROUND_LOCATION = 1 << 31;
/**
* For some direct access we need to power manager.
@@ -1501,7 +1505,7 @@ public final class OomAdjuster {
//TODO: remove this block when development is done.
capabilityFromFGS |=
(fgsType & FOREGROUND_SERVICE_TYPE_LOCATION)
- != 0 ? TEMP_PROCESS_CAPABILITY_FOREGROUND_LOCATION : 0;
+ != 0 ? DEBUG_PROCESS_CAPABILITY_FOREGROUND_LOCATION : 0;
}
if (s.mAllowWhileInUsePermissionInFgs) {
boolean enabled = false;
@@ -1514,22 +1518,22 @@ public final class OomAdjuster {
capabilityFromFGS |=
(fgsType & FOREGROUND_SERVICE_TYPE_CAMERA)
!= 0 ? PROCESS_CAPABILITY_FOREGROUND_CAMERA
- : TEMP_PROCESS_CAPABILITY_FOREGROUND_CAMERA;
+ : DEBUG_PROCESS_CAPABILITY_FOREGROUND_CAMERA;
capabilityFromFGS |=
(fgsType & FOREGROUND_SERVICE_TYPE_MICROPHONE)
!= 0 ? PROCESS_CAPABILITY_FOREGROUND_MICROPHONE
- : TEMP_PROCESS_CAPABILITY_FOREGROUND_MICROPHONE;
+ : DEBUG_PROCESS_CAPABILITY_FOREGROUND_MICROPHONE;
} else {
// Remove fgsType check and assign PROCESS_CAPABILITY_FOREGROUND_CAMERA
// and MICROPHONE when finish debugging.
capabilityFromFGS |=
(fgsType & FOREGROUND_SERVICE_TYPE_CAMERA)
!= 0 ? PROCESS_CAPABILITY_FOREGROUND_CAMERA
- : TEMP_PROCESS_CAPABILITY_FOREGROUND_CAMERA;
+ : DEBUG_PROCESS_CAPABILITY_FOREGROUND_CAMERA_Q;
capabilityFromFGS |=
(fgsType & FOREGROUND_SERVICE_TYPE_MICROPHONE)
!= 0 ? PROCESS_CAPABILITY_FOREGROUND_MICROPHONE
- : TEMP_PROCESS_CAPABILITY_FOREGROUND_MICROPHONE;
+ : DEBUG_PROCESS_CAPABILITY_FOREGROUND_MICROPHONE_Q;
}
}
}
diff --git a/services/core/java/com/android/server/am/ProcessList.java b/services/core/java/com/android/server/am/ProcessList.java
index bee0e055cf3f..4d08bd2e0ed7 100644
--- a/services/core/java/com/android/server/am/ProcessList.java
+++ b/services/core/java/com/android/server/am/ProcessList.java
@@ -98,7 +98,6 @@ import android.provider.DeviceConfig;
import android.system.Os;
import android.text.TextUtils;
import android.util.ArrayMap;
-import android.util.ArraySet;
import android.util.EventLog;
import android.util.LongSparseArray;
import android.util.Pair;
@@ -139,7 +138,6 @@ import java.util.BitSet;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
-import java.util.Set;
/**
* Activity manager code dealing with processes.
@@ -2157,6 +2155,15 @@ public final class ProcessList {
result.put(packageName, Pair.create(volumeUuid, inode));
}
}
+ if (mAppDataIsolationWhitelistedApps != null) {
+ for (String packageName : mAppDataIsolationWhitelistedApps) {
+ String volumeUuid = pmInt.getPackage(packageName).getVolumeUuid();
+ long inode = pmInt.getCeDataInode(packageName, userId);
+ if (inode != 0) {
+ result.put(packageName, Pair.create(volumeUuid, inode));
+ }
+ }
+ }
return result;
}
@@ -2177,42 +2184,34 @@ public final class ProcessList {
app.setHasForegroundActivities(true);
}
- final Map<String, Pair<String, Long>> pkgDataInfoMap;
- final Map<String, Pair<String, Long>> whitelistedAppDataInfoMap;
- boolean bindMountAppStorageDirs = false;
- boolean bindMountAppsData = shouldIsolateAppData(app);
-
- // Get all packages belongs to the same shared uid. sharedPackages is empty array
- // if it doesn't have shared uid.
- final PackageManagerInternal pmInt = mService.getPackageManagerInternalLocked();
- final String[] sharedPackages = pmInt.getSharedUserPackagesForPackage(
- app.info.packageName, app.userId);
- final String[] targetPackagesList = sharedPackages.length == 0
- ? new String[]{app.info.packageName} : sharedPackages;
- pkgDataInfoMap = getPackageAppDataInfoMap(pmInt, targetPackagesList, uid);
-
- // Remove all packages in pkgDataInfoMap from mAppDataIsolationWhitelistedApps, so
- // it won't be mounted twice.
- final Set<String> whitelistedApps = new ArraySet<>(mAppDataIsolationWhitelistedApps);
- for (String pkg : targetPackagesList) {
- whitelistedApps.remove(pkg);
- }
- whitelistedAppDataInfoMap = getPackageAppDataInfoMap(pmInt,
- whitelistedApps.toArray(new String[0]), uid);
-
- int userId = UserHandle.getUserId(uid);
StorageManagerInternal storageManagerInternal = LocalServices.getService(
StorageManagerInternal.class);
- if (mVoldAppDataIsolationEnabled && UserHandle.isApp(app.uid) &&
- !storageManagerInternal.isExternalStorageService(uid)) {
- bindMountAppStorageDirs = true;
- if (!storageManagerInternal.prepareStorageDirs(userId, pkgDataInfoMap.keySet(),
- app.processName)) {
- // Cannot prepare Android/app and Android/obb directory,
- // so we won't mount it in zygote.
- app.bindMountPending = true;
- bindMountAppStorageDirs = false;
+ final Map<String, Pair<String, Long>> pkgDataInfoMap;
+ boolean bindMountAppStorageDirs = false;
+
+ if (shouldIsolateAppData(app)) {
+ // Get all packages belongs to the same shared uid. sharedPackages is empty array
+ // if it doesn't have shared uid.
+ final PackageManagerInternal pmInt = mService.getPackageManagerInternalLocked();
+ final String[] sharedPackages = pmInt.getSharedUserPackagesForPackage(
+ app.info.packageName, app.userId);
+ pkgDataInfoMap = getPackageAppDataInfoMap(pmInt, sharedPackages.length == 0
+ ? new String[]{app.info.packageName} : sharedPackages, uid);
+
+ int userId = UserHandle.getUserId(uid);
+ if (mVoldAppDataIsolationEnabled && UserHandle.isApp(app.uid) &&
+ !storageManagerInternal.isExternalStorageService(uid)) {
+ bindMountAppStorageDirs = true;
+ if (!storageManagerInternal.prepareStorageDirs(userId, pkgDataInfoMap.keySet(),
+ app.processName)) {
+ // Cannot prepare Android/app and Android/obb directory,
+ // so we won't mount it in zygote.
+ app.bindMountPending = true;
+ bindMountAppStorageDirs = false;
+ }
}
+ } else {
+ pkgDataInfoMap = null;
}
final Process.ProcessStartResult startResult;
@@ -2230,8 +2229,7 @@ public final class ProcessList {
app.info.targetSdkVersion, seInfo, requiredAbi, instructionSet,
app.info.dataDir, null, app.info.packageName,
/*zygotePolicyFlags=*/ ZYGOTE_POLICY_FLAG_EMPTY, isTopApp,
- app.mDisabledCompatChanges, pkgDataInfoMap, whitelistedAppDataInfoMap,
- bindMountAppsData, bindMountAppStorageDirs,
+ app.mDisabledCompatChanges, pkgDataInfoMap, bindMountAppStorageDirs,
new String[]{PROC_START_SEQ_IDENT + app.startSeq});
} else {
startResult = Process.start(entryPoint,
@@ -2239,7 +2237,7 @@ public final class ProcessList {
app.info.targetSdkVersion, seInfo, requiredAbi, instructionSet,
app.info.dataDir, invokeWith, app.info.packageName, zygotePolicyFlags,
isTopApp, app.mDisabledCompatChanges, pkgDataInfoMap,
- whitelistedAppDataInfoMap, bindMountAppsData, bindMountAppStorageDirs,
+ bindMountAppStorageDirs,
new String[]{PROC_START_SEQ_IDENT + app.startSeq});
}
checkSlow(startTime, "startProcess: returned from zygote!");
diff --git a/services/core/java/com/android/server/am/UserController.java b/services/core/java/com/android/server/am/UserController.java
index 636a0e935289..e02c6f9d5497 100644
--- a/services/core/java/com/android/server/am/UserController.java
+++ b/services/core/java/com/android/server/am/UserController.java
@@ -159,6 +159,9 @@ class UserController implements Handler.Callback {
// when it never calls back.
private static final int USER_SWITCH_CALLBACKS_TIMEOUT_MS = 5 * 1000;
+ // TODO(b/149604218): STOPSHIP remove this constant and the logcat
+ private static final boolean TESTS_NEED_LOGCAT = true;
+
/**
* Maximum number of users we allow to be running at a time, including system user.
*
@@ -1668,6 +1671,9 @@ class UserController implements Handler.Callback {
}
void continueUserSwitch(UserState uss, int oldUserId, int newUserId) {
+ if (TESTS_NEED_LOGCAT) {
+ Slog.d(TAG, "Continue user switch oldUser #" + oldUserId + ", newUser #" + newUserId);
+ }
EventLog.writeEvent(EventLogTags.UC_CONTINUE_USER_SWITCH, oldUserId, newUserId);
if (isUserSwitchUiEnabled()) {
@@ -1675,8 +1681,7 @@ class UserController implements Handler.Callback {
}
uss.switching = false;
mHandler.removeMessages(REPORT_USER_SWITCH_COMPLETE_MSG);
- mHandler.sendMessage(mHandler.obtainMessage(REPORT_USER_SWITCH_COMPLETE_MSG,
- newUserId, 0));
+ mHandler.sendMessage(mHandler.obtainMessage(REPORT_USER_SWITCH_COMPLETE_MSG, newUserId, 0));
stopGuestOrEphemeralUserIfBackground(oldUserId);
stopBackgroundUsersIfEnforced(oldUserId);
}
diff --git a/services/core/java/com/android/server/appop/AppOpsService.java b/services/core/java/com/android/server/appop/AppOpsService.java
index 6613d5f8d57a..8e6ef75078b3 100644
--- a/services/core/java/com/android/server/appop/AppOpsService.java
+++ b/services/core/java/com/android/server/appop/AppOpsService.java
@@ -66,6 +66,11 @@ import static android.content.Intent.EXTRA_REPLACING;
import static android.content.pm.PermissionInfo.PROTECTION_DANGEROUS;
import static android.content.pm.PermissionInfo.PROTECTION_FLAG_APPOP;
+import static com.android.server.am.OomAdjuster.DEBUG_PROCESS_CAPABILITY_FOREGROUND_CAMERA;
+import static com.android.server.am.OomAdjuster.DEBUG_PROCESS_CAPABILITY_FOREGROUND_CAMERA_Q;
+import static com.android.server.am.OomAdjuster.DEBUG_PROCESS_CAPABILITY_FOREGROUND_LOCATION;
+import static com.android.server.am.OomAdjuster.DEBUG_PROCESS_CAPABILITY_FOREGROUND_MICROPHONE;
+import static com.android.server.am.OomAdjuster.DEBUG_PROCESS_CAPABILITY_FOREGROUND_MICROPHONE_Q;
import static com.android.server.appop.AppOpsService.ModeCallback.ALL_OPS;
import static java.lang.Long.max;
@@ -248,9 +253,6 @@ public class AppOpsService extends IAppOpsService.Stub {
private static final int RARELY_USED_PACKAGES_INITIALIZATION_DELAY_MILLIS = 300000;
//TODO: remove this when development is done.
- private static final int TEMP_PROCESS_CAPABILITY_FOREGROUND_LOCATION = 1 << 31;
- private static final int TEMP_PROCESS_CAPABILITY_FOREGROUND_CAMERA = 1 << 30;
- private static final int TEMP_PROCESS_CAPABILITY_FOREGROUND_MICROPHONE = 1 << 29;
private static final int DEBUG_FGS_ALLOW_WHILE_IN_USE = 0;
private static final int DEBUG_FGS_ENFORCE_TYPE = 1;
@@ -552,7 +554,7 @@ public class AppOpsService extends IAppOpsService.Stub {
if ((capability & PROCESS_CAPABILITY_FOREGROUND_LOCATION) != 0) {
return MODE_ALLOWED;
} else if ((capability
- & TEMP_PROCESS_CAPABILITY_FOREGROUND_LOCATION) != 0) {
+ & DEBUG_PROCESS_CAPABILITY_FOREGROUND_LOCATION) != 0) {
// The FGS has the location capability, but due to FGS BG start
// restriction it lost the capability, use temp location capability
// to mark this case.
@@ -564,11 +566,14 @@ public class AppOpsService extends IAppOpsService.Stub {
case OP_CAMERA:
if ((capability & PROCESS_CAPABILITY_FOREGROUND_CAMERA) != 0) {
return MODE_ALLOWED;
- } else if ((capability & TEMP_PROCESS_CAPABILITY_FOREGROUND_CAMERA)
+ } else if ((capability & DEBUG_PROCESS_CAPABILITY_FOREGROUND_CAMERA_Q)
!= 0) {
- // CHANGE TO MODE_IGNORED when enforce this feature.
maybeShowWhileInUseDebugToast(op, DEBUG_FGS_ENFORCE_TYPE);
return MODE_ALLOWED;
+ } else if ((capability & DEBUG_PROCESS_CAPABILITY_FOREGROUND_CAMERA)
+ != 0) {
+ maybeShowWhileInUseDebugToast(op, DEBUG_FGS_ENFORCE_TYPE);
+ return MODE_IGNORED;
} else {
maybeShowWhileInUseDebugToast(op, DEBUG_FGS_ALLOW_WHILE_IN_USE);
return MODE_IGNORED;
@@ -576,11 +581,14 @@ public class AppOpsService extends IAppOpsService.Stub {
case OP_RECORD_AUDIO:
if ((capability & PROCESS_CAPABILITY_FOREGROUND_MICROPHONE) != 0) {
return MODE_ALLOWED;
- } else if ((capability & TEMP_PROCESS_CAPABILITY_FOREGROUND_MICROPHONE)
- != 0) {
- // CHANGE TO MODE_IGNORED when enforce this feature.
+ } else if ((capability
+ & DEBUG_PROCESS_CAPABILITY_FOREGROUND_MICROPHONE_Q) != 0) {
maybeShowWhileInUseDebugToast(op, DEBUG_FGS_ENFORCE_TYPE);
return MODE_ALLOWED;
+ } else if ((capability
+ & DEBUG_PROCESS_CAPABILITY_FOREGROUND_MICROPHONE) != 0) {
+ maybeShowWhileInUseDebugToast(op, DEBUG_FGS_ENFORCE_TYPE);
+ return MODE_IGNORED;
} else {
maybeShowWhileInUseDebugToast(op, DEBUG_FGS_ALLOW_WHILE_IN_USE);
return MODE_IGNORED;
@@ -597,10 +605,13 @@ public class AppOpsService extends IAppOpsService.Stub {
case OP_CAMERA:
if ((capability & PROCESS_CAPABILITY_FOREGROUND_CAMERA) != 0) {
return MODE_ALLOWED;
- } else if ((capability & TEMP_PROCESS_CAPABILITY_FOREGROUND_CAMERA) != 0) {
- // CHANGE TO MODE_IGNORED when enforce this feature.
+ } else if ((capability
+ & DEBUG_PROCESS_CAPABILITY_FOREGROUND_CAMERA_Q) != 0) {
maybeShowWhileInUseDebugToast(op, DEBUG_FGS_ENFORCE_TYPE);
return MODE_ALLOWED;
+ } else if ((capability & DEBUG_PROCESS_CAPABILITY_FOREGROUND_CAMERA) != 0) {
+ maybeShowWhileInUseDebugToast(op, DEBUG_FGS_ENFORCE_TYPE);
+ return MODE_IGNORED;
} else {
maybeShowWhileInUseDebugToast(op, DEBUG_FGS_ALLOW_WHILE_IN_USE);
return MODE_IGNORED;
@@ -608,11 +619,14 @@ public class AppOpsService extends IAppOpsService.Stub {
case OP_RECORD_AUDIO:
if ((capability & PROCESS_CAPABILITY_FOREGROUND_MICROPHONE) != 0) {
return MODE_ALLOWED;
- } else if ((capability & TEMP_PROCESS_CAPABILITY_FOREGROUND_MICROPHONE)
+ } else if ((capability & DEBUG_PROCESS_CAPABILITY_FOREGROUND_MICROPHONE_Q)
!= 0) {
- // CHANGE TO MODE_IGNORED when enforce this feature.
maybeShowWhileInUseDebugToast(op, DEBUG_FGS_ENFORCE_TYPE);
return MODE_ALLOWED;
+ } else if ((capability & DEBUG_PROCESS_CAPABILITY_FOREGROUND_MICROPHONE)
+ != 0) {
+ maybeShowWhileInUseDebugToast(op, DEBUG_FGS_ENFORCE_TYPE);
+ return MODE_IGNORED;
} else {
maybeShowWhileInUseDebugToast(op, DEBUG_FGS_ALLOW_WHILE_IN_USE);
return MODE_IGNORED;
diff --git a/services/core/java/com/android/server/audio/AudioService.java b/services/core/java/com/android/server/audio/AudioService.java
index 94675ab7d795..8bce5043ad34 100644
--- a/services/core/java/com/android/server/audio/AudioService.java
+++ b/services/core/java/com/android/server/audio/AudioService.java
@@ -634,6 +634,9 @@ public class AudioService extends IAudioService.Stub
}
};
+ @GuardedBy("mSettingsLock")
+ private boolean mRttEnabled = false;
+
///////////////////////////////////////////////////////////////////////////
// Construction
///////////////////////////////////////////////////////////////////////////
@@ -1053,7 +1056,7 @@ public class AudioService extends IAudioService.Stub
sendEncodedSurroundMode(mContentResolver, "onAudioServerDied");
sendEnabledSurroundFormats(mContentResolver, true);
updateAssistantUId(true);
- updateRttEanbled(mContentResolver);
+ AudioSystem.setRttEnabled(mRttEnabled);
}
synchronized (mAccessibilityServiceUidsLock) {
AudioSystem.setA11yServicesUids(mAccessibilityServiceUids);
@@ -1598,12 +1601,6 @@ public class AudioService extends IAudioService.Stub
}
}
- private void updateRttEanbled(ContentResolver cr) {
- final boolean rttEnabled = Settings.Secure.getIntForUser(cr,
- Settings.Secure.RTT_CALLING_MODE, 0, UserHandle.USER_CURRENT) != 0;
- AudioSystem.setRttEnabled(rttEnabled);
- }
-
private void readPersistedSettings() {
final ContentResolver cr = mContentResolver;
@@ -1648,7 +1645,7 @@ public class AudioService extends IAudioService.Stub
sendEncodedSurroundMode(cr, "readPersistedSettings");
sendEnabledSurroundFormats(cr, true);
updateAssistantUId(true);
- updateRttEanbled(cr);
+ AudioSystem.setRttEnabled(mRttEnabled);
}
mMuteAffectedStreams = System.getIntForUser(cr,
@@ -3684,6 +3681,27 @@ public class AudioService extends IAudioService.Stub
return mIsCallScreeningModeSupported;
}
+ /** @see AudioManager#setRttEnabled() */
+ @Override
+ public void setRttEnabled(boolean rttEnabled) {
+ if (mContext.checkCallingOrSelfPermission(
+ android.Manifest.permission.MODIFY_PHONE_STATE)
+ != PackageManager.PERMISSION_GRANTED) {
+ Log.w(TAG, "MODIFY_PHONE_STATE Permission Denial: setRttEnabled from pid="
+ + Binder.getCallingPid() + ", uid=" + Binder.getCallingUid());
+ return;
+ }
+ synchronized (mSettingsLock) {
+ mRttEnabled = rttEnabled;
+ final long identity = Binder.clearCallingIdentity();
+ try {
+ AudioSystem.setRttEnabled(rttEnabled);
+ } finally {
+ Binder.restoreCallingIdentity(identity);
+ }
+ }
+ }
+
//==========================================================================================
// Sound Effects
//==========================================================================================
@@ -5825,8 +5843,6 @@ public class AudioService extends IAudioService.Stub
mContentResolver.registerContentObserver(Settings.Secure.getUriFor(
Settings.Secure.VOICE_INTERACTION_SERVICE), false, this);
- mContentResolver.registerContentObserver(Settings.Secure.getUriFor(
- Settings.Secure.RTT_CALLING_MODE), false, this);
}
@Override
@@ -5850,7 +5866,6 @@ public class AudioService extends IAudioService.Stub
updateEncodedSurroundOutput();
sendEnabledSurroundFormats(mContentResolver, mSurroundModeChanged);
updateAssistantUId(false);
- updateRttEanbled(mContentResolver);
}
}
diff --git a/services/core/java/com/android/server/biometrics/AuthService.java b/services/core/java/com/android/server/biometrics/AuthService.java
index ff8e3a973641..a0876c063fb3 100644
--- a/services/core/java/com/android/server/biometrics/AuthService.java
+++ b/services/core/java/com/android/server/biometrics/AuthService.java
@@ -158,7 +158,8 @@ public class AuthService extends SystemService {
|| bundle.getCharSequence(
BiometricPrompt.KEY_DEVICE_CREDENTIAL_SUBTITLE) != null
|| bundle.getCharSequence(
- BiometricPrompt.KEY_DEVICE_CREDENTIAL_DESCRIPTION) != null) {
+ BiometricPrompt.KEY_DEVICE_CREDENTIAL_DESCRIPTION) != null
+ || bundle.getBoolean(BiometricPrompt.KEY_RECEIVE_SYSTEM_EVENTS, false)) {
checkInternalPermission();
}
diff --git a/services/core/java/com/android/server/biometrics/BiometricService.java b/services/core/java/com/android/server/biometrics/BiometricService.java
index 233416d663d9..d49b590b8a4d 100644
--- a/services/core/java/com/android/server/biometrics/BiometricService.java
+++ b/services/core/java/com/android/server/biometrics/BiometricService.java
@@ -112,6 +112,7 @@ public class BiometricService extends SystemService {
private static final int MSG_CANCEL_AUTHENTICATION = 10;
private static final int MSG_ON_AUTHENTICATION_TIMED_OUT = 11;
private static final int MSG_ON_DEVICE_CREDENTIAL_PRESSED = 12;
+ private static final int MSG_ON_SYSTEM_EVENT = 13;
/**
* Authentication either just called and we have not transitioned to the CALLED state, or
@@ -360,6 +361,11 @@ public class BiometricService extends SystemService {
break;
}
+ case MSG_ON_SYSTEM_EVENT: {
+ handleOnSystemEvent((int) msg.obj);
+ break;
+ }
+
default:
Slog.e(TAG, "Unknown message: " + msg);
break;
@@ -632,6 +638,11 @@ public class BiometricService extends SystemService {
public void onDeviceCredentialPressed() {
mHandler.sendEmptyMessage(MSG_ON_DEVICE_CREDENTIAL_PRESSED);
}
+
+ @Override
+ public void onSystemEvent(int event) {
+ mHandler.obtainMessage(MSG_ON_SYSTEM_EVENT, event).sendToTarget();
+ }
};
@@ -1579,6 +1590,27 @@ public class BiometricService extends SystemService {
mCurrentAuthSession.mState = STATE_SHOWING_DEVICE_CREDENTIAL;
}
+ private void handleOnSystemEvent(int event) {
+ final boolean shouldReceive = mCurrentAuthSession.mBundle
+ .getBoolean(BiometricPrompt.KEY_RECEIVE_SYSTEM_EVENTS, false);
+ Slog.d(TAG, "onSystemEvent: " + event + ", shouldReceive: " + shouldReceive);
+
+ if (mCurrentAuthSession == null) {
+ Slog.e(TAG, "Auth session null");
+ return;
+ }
+
+ if (!shouldReceive) {
+ return;
+ }
+
+ try {
+ mCurrentAuthSession.mClientReceiver.onSystemEvent(event);
+ } catch (RemoteException e) {
+ Slog.e(TAG, "RemoteException", e);
+ }
+ }
+
/**
* Invoked when each service has notified that its client is ready to be started. When
* all biometrics are ready, this invokes the SystemUI dialog through StatusBar.
diff --git a/services/core/java/com/android/server/hdmi/README.md b/services/core/java/com/android/server/hdmi/README.md
new file mode 100644
index 000000000000..2b510b503671
--- /dev/null
+++ b/services/core/java/com/android/server/hdmi/README.md
@@ -0,0 +1,7 @@
+# Package com.android.server.hdmi
+
+HDMI service for Android with focus on CEC
+
+## Links
+
+* [CEC Key Handling](cec_key_handling.md)
diff --git a/services/core/java/com/android/server/hdmi/cec_key_handling.md b/services/core/java/com/android/server/hdmi/cec_key_handling.md
new file mode 100644
index 000000000000..d150dd3fceb9
--- /dev/null
+++ b/services/core/java/com/android/server/hdmi/cec_key_handling.md
@@ -0,0 +1,36 @@
+# CEC Key Handling
+
+The mapping of CEC key codes to Android key codes are at
+[HdmiCecKeycode](HdmiCecKeycode.java)
+
+# Android TV
+
+Android TV requires special handling of some keys.
+
+The general action for key handling is described in the table
+
+| Android Key | TV Panel | OTT | Soundbar |
+| ----------- | ----------------- | ------------------- | ------------------- |
+| general | Send to active source | handle on device | handle on device |
+| POWER | Toggle the device power state | Toggle the TV power state | Toggle the TV power state |
+| TV_POWER | Toggle the device power state | Toggle the TV power state | Toggle the TV power state |
+| HOME | Turn on TV, Set active Source to TV, go to home screen | OTP, and go to home screen | OTP, and go to home screen |
+| volume keys | Handle on device or send to soundbar | Send to TV or soundbar | Handle on device or send to TV |
+
+Special cases and flags for each key are described below
+
+## POWER
+
+### TV Panel
+
+TODO
+
+### OTT
+
+TODO
+
+### Soundbar
+
+TODO
+
+
diff --git a/services/core/java/com/android/server/incident/PendingReports.java b/services/core/java/com/android/server/incident/PendingReports.java
index 9fcbab71519d..f39bebf060f7 100644
--- a/services/core/java/com/android/server/incident/PendingReports.java
+++ b/services/core/java/com/android/server/incident/PendingReports.java
@@ -359,6 +359,8 @@ class PendingReports {
private void sendBroadcast(ComponentName receiver, int primaryUser) {
final Intent intent = new Intent(Intent.ACTION_PENDING_INCIDENT_REPORTS_CHANGED);
intent.setComponent(receiver);
+ intent.addFlags(Intent.FLAG_RECEIVER_FOREGROUND);
+ intent.addFlags(Intent.FLAG_RECEIVER_INCLUDE_BACKGROUND);
final BroadcastOptions options = BroadcastOptions.makeBasic();
options.setBackgroundActivityStartsAllowed(true);
diff --git a/services/core/java/com/android/server/input/InputManagerService.java b/services/core/java/com/android/server/input/InputManagerService.java
index e6129b9b1f32..0b22586bb373 100644
--- a/services/core/java/com/android/server/input/InputManagerService.java
+++ b/services/core/java/com/android/server/input/InputManagerService.java
@@ -76,6 +76,7 @@ import android.view.InputChannel;
import android.view.InputDevice;
import android.view.InputEvent;
import android.view.InputMonitor;
+import android.view.InputWindowHandle;
import android.view.KeyEvent;
import android.view.PointerIcon;
import android.view.Surface;
@@ -220,7 +221,8 @@ public class InputManagerService extends IInputManager.Stub
int policyFlags);
private static native VerifiedInputEvent nativeVerifyInputEvent(long ptr, InputEvent event);
private static native void nativeToggleCapsLock(long ptr, int deviceId);
- private static native void nativeDisplayRemoved(long ptr, int displayId);
+ private static native void nativeSetInputWindows(long ptr, InputWindowHandle[] windowHandles,
+ int displayId);
private static native void nativeSetInputDispatchMode(long ptr, boolean enabled, boolean frozen);
private static native void nativeSetSystemUiVisibility(long ptr, int visibility);
private static native void nativeSetFocusedApplication(long ptr,
@@ -1534,7 +1536,7 @@ public class InputManagerService extends IInputManager.Stub
/** Clean up input window handles of the given display. */
public void onDisplayRemoved(int displayId) {
- nativeDisplayRemoved(mPtr, displayId);
+ nativeSetInputWindows(mPtr, null /* windowHandles */, displayId);
}
@Override
diff --git a/services/core/java/com/android/server/location/RemoteListenerHelper.java b/services/core/java/com/android/server/location/RemoteListenerHelper.java
index 11f068533a6d..f6652892c3de 100644
--- a/services/core/java/com/android/server/location/RemoteListenerHelper.java
+++ b/services/core/java/com/android/server/location/RemoteListenerHelper.java
@@ -273,7 +273,7 @@ public abstract class RemoteListenerHelper<TRequest, TListener extends IInterfac
}
@Nullable
- protected TRequest getRequest() {
+ public TRequest getRequest() {
return mRequest;
}
}
diff --git a/services/core/java/com/android/server/location/ExponentialBackOff.java b/services/core/java/com/android/server/location/gnss/ExponentialBackOff.java
index 8c77b2176b74..05a534fa36e9 100644
--- a/services/core/java/com/android/server/location/ExponentialBackOff.java
+++ b/services/core/java/com/android/server/location/gnss/ExponentialBackOff.java
@@ -1,4 +1,20 @@
-package com.android.server.location;
+/*
+ * 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.location.gnss;
/**
* A simple implementation of exponential backoff.
diff --git a/services/core/java/com/android/server/location/GnssAntennaInfoProvider.java b/services/core/java/com/android/server/location/gnss/GnssAntennaInfoProvider.java
index bc50ebc2c5c3..d839095542c7 100644
--- a/services/core/java/com/android/server/location/GnssAntennaInfoProvider.java
+++ b/services/core/java/com/android/server/location/gnss/GnssAntennaInfoProvider.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package com.android.server.location;
+package com.android.server.location.gnss;
import android.content.Context;
import android.location.GnssAntennaInfo;
@@ -23,6 +23,8 @@ import android.os.Handler;
import android.util.Log;
import com.android.internal.annotations.VisibleForTesting;
+import com.android.server.location.CallerIdentity;
+import com.android.server.location.RemoteListenerHelper;
import java.util.List;
diff --git a/services/core/java/com/android/server/location/GnssBatchingProvider.java b/services/core/java/com/android/server/location/gnss/GnssBatchingProvider.java
index f3918ee9e8ff..f583a3ed3136 100644
--- a/services/core/java/com/android/server/location/GnssBatchingProvider.java
+++ b/services/core/java/com/android/server/location/gnss/GnssBatchingProvider.java
@@ -1,4 +1,20 @@
-package com.android.server.location;
+/*
+ * 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.location.gnss;
import android.util.Log;
diff --git a/services/core/java/com/android/server/location/GnssCapabilitiesProvider.java b/services/core/java/com/android/server/location/gnss/GnssCapabilitiesProvider.java
index 5c8507f7fde0..71b5b33c242b 100644
--- a/services/core/java/com/android/server/location/GnssCapabilitiesProvider.java
+++ b/services/core/java/com/android/server/location/gnss/GnssCapabilitiesProvider.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.server.location;
+package com.android.server.location.gnss;
import android.location.GnssCapabilities;
import android.util.Log;
diff --git a/services/core/java/com/android/server/location/GnssConfiguration.java b/services/core/java/com/android/server/location/gnss/GnssConfiguration.java
index a3523f23ddcf..14ab79e7ecde 100644
--- a/services/core/java/com/android/server/location/GnssConfiguration.java
+++ b/services/core/java/com/android/server/location/gnss/GnssConfiguration.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.server.location;
+package com.android.server.location.gnss;
import android.content.Context;
import android.os.PersistableBundle;
diff --git a/services/core/java/com/android/server/location/GnssGeofenceProvider.java b/services/core/java/com/android/server/location/gnss/GnssGeofenceProvider.java
index a84b0b1c4335..53883b91c36d 100644
--- a/services/core/java/com/android/server/location/GnssGeofenceProvider.java
+++ b/services/core/java/com/android/server/location/gnss/GnssGeofenceProvider.java
@@ -1,4 +1,20 @@
-package com.android.server.location;
+/*
+ * 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.location.gnss;
import android.location.IGpsGeofenceHardware;
import android.util.Log;
diff --git a/services/core/java/com/android/server/location/GnssLocationProvider.java b/services/core/java/com/android/server/location/gnss/GnssLocationProvider.java
index c1fbcfba864a..ad3c8a61182f 100644
--- a/services/core/java/com/android/server/location/GnssLocationProvider.java
+++ b/services/core/java/com/android/server/location/gnss/GnssLocationProvider.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2008 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.server.location;
+package com.android.server.location.gnss;
import android.app.AlarmManager;
import android.app.AppOpsManager;
@@ -78,8 +78,9 @@ import com.android.internal.util.FrameworkStatsLog;
import com.android.server.DeviceIdleInternal;
import com.android.server.FgThread;
import com.android.server.LocalServices;
-import com.android.server.location.GnssSatelliteBlacklistHelper.GnssSatelliteBlacklistCallback;
-import com.android.server.location.NtpTimeHelper.InjectNtpTimeCallback;
+import com.android.server.location.AbstractLocationProvider;
+import com.android.server.location.gnss.NtpTimeHelper.InjectNtpTimeCallback;
+import com.android.server.location.gnss.GnssSatelliteBlacklistHelper.GnssSatelliteBlacklistCallback;
import java.io.FileDescriptor;
import java.io.PrintWriter;
diff --git a/services/core/java/com/android/server/location/gnss/GnssManagerService.java b/services/core/java/com/android/server/location/gnss/GnssManagerService.java
index b57c261931f8..9e64e3aeae59 100644
--- a/services/core/java/com/android/server/location/gnss/GnssManagerService.java
+++ b/services/core/java/com/android/server/location/gnss/GnssManagerService.java
@@ -55,14 +55,6 @@ import com.android.server.LocationManagerServiceUtils.LinkedListener;
import com.android.server.LocationManagerServiceUtils.LinkedListenerBase;
import com.android.server.location.AppForegroundHelper;
import com.android.server.location.CallerIdentity;
-import com.android.server.location.GnssAntennaInfoProvider;
-import com.android.server.location.GnssBatchingProvider;
-import com.android.server.location.GnssCapabilitiesProvider;
-import com.android.server.location.GnssLocationProvider;
-import com.android.server.location.GnssMeasurementCorrectionsProvider;
-import com.android.server.location.GnssMeasurementsProvider;
-import com.android.server.location.GnssNavigationMessageProvider;
-import com.android.server.location.GnssStatusListenerHelper;
import com.android.server.location.LocationUsageLogger;
import com.android.server.location.RemoteListenerHelper;
import com.android.server.location.SettingsHelper;
diff --git a/services/core/java/com/android/server/location/GnssMeasurementCorrectionsProvider.java b/services/core/java/com/android/server/location/gnss/GnssMeasurementCorrectionsProvider.java
index 82528caa0b4e..ac165d1a206b 100644
--- a/services/core/java/com/android/server/location/GnssMeasurementCorrectionsProvider.java
+++ b/services/core/java/com/android/server/location/gnss/GnssMeasurementCorrectionsProvider.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.server.location;
+package com.android.server.location.gnss;
import android.location.GnssMeasurementCorrections;
import android.os.Handler;
diff --git a/services/core/java/com/android/server/location/GnssMeasurementsProvider.java b/services/core/java/com/android/server/location/gnss/GnssMeasurementsProvider.java
index 6ba5f079264c..76c3ad02e7e9 100644
--- a/services/core/java/com/android/server/location/GnssMeasurementsProvider.java
+++ b/services/core/java/com/android/server/location/gnss/GnssMeasurementsProvider.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2014 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.server.location;
+package com.android.server.location.gnss;
import android.content.Context;
import android.location.GnssMeasurementsEvent;
@@ -26,6 +26,8 @@ import android.provider.Settings;
import android.util.Log;
import com.android.internal.annotations.VisibleForTesting;
+import com.android.server.location.CallerIdentity;
+import com.android.server.location.RemoteListenerHelper;
/**
* An base implementation for GPS measurements provider. It abstracts out the responsibility of
diff --git a/services/core/java/com/android/server/location/GnssNavigationMessageProvider.java b/services/core/java/com/android/server/location/gnss/GnssNavigationMessageProvider.java
index fb901e86f494..722be3df2691 100644
--- a/services/core/java/com/android/server/location/GnssNavigationMessageProvider.java
+++ b/services/core/java/com/android/server/location/gnss/GnssNavigationMessageProvider.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2014 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.server.location;
+package com.android.server.location.gnss;
import android.content.Context;
import android.location.GnssNavigationMessage;
@@ -24,6 +24,8 @@ import android.os.RemoteException;
import android.util.Log;
import com.android.internal.annotations.VisibleForTesting;
+import com.android.server.location.CallerIdentity;
+import com.android.server.location.RemoteListenerHelper;
/**
* An base implementation for GPS navigation messages provider.
diff --git a/services/core/java/com/android/server/location/GnssNetworkConnectivityHandler.java b/services/core/java/com/android/server/location/gnss/GnssNetworkConnectivityHandler.java
index 5d6474bdbccc..3fb713bc01a5 100644
--- a/services/core/java/com/android/server/location/GnssNetworkConnectivityHandler.java
+++ b/services/core/java/com/android/server/location/gnss/GnssNetworkConnectivityHandler.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2018 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.server.location;
+package com.android.server.location.gnss;
import android.content.Context;
import android.database.Cursor;
diff --git a/services/core/java/com/android/server/location/GnssPositionMode.java b/services/core/java/com/android/server/location/gnss/GnssPositionMode.java
index 36838fc3647f..045118afbda0 100644
--- a/services/core/java/com/android/server/location/GnssPositionMode.java
+++ b/services/core/java/com/android/server/location/gnss/GnssPositionMode.java
@@ -1,4 +1,20 @@
-package com.android.server.location;
+/*
+ * 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.location.gnss;
import java.util.Arrays;
diff --git a/services/core/java/com/android/server/location/GnssSatelliteBlacklistHelper.java b/services/core/java/com/android/server/location/gnss/GnssSatelliteBlacklistHelper.java
index eb99a851115f..dccef9b9a9c4 100644
--- a/services/core/java/com/android/server/location/GnssSatelliteBlacklistHelper.java
+++ b/services/core/java/com/android/server/location/gnss/GnssSatelliteBlacklistHelper.java
@@ -1,4 +1,20 @@
-package com.android.server.location;
+/*
+ * 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.location.gnss;
import android.content.ContentResolver;
import android.content.Context;
diff --git a/services/core/java/com/android/server/location/GnssStatusListenerHelper.java b/services/core/java/com/android/server/location/gnss/GnssStatusListenerHelper.java
index 1d16c03fd6f7..d2ecdeebd9d0 100644
--- a/services/core/java/com/android/server/location/GnssStatusListenerHelper.java
+++ b/services/core/java/com/android/server/location/gnss/GnssStatusListenerHelper.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2014 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,16 +11,19 @@
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
- * limitations under the License
+ * limitations under the License.
*/
-package com.android.server.location;
+package com.android.server.location.gnss;
import android.content.Context;
import android.location.IGnssStatusListener;
import android.os.Handler;
import android.util.Log;
+import com.android.server.location.CallerIdentity;
+import com.android.server.location.RemoteListenerHelper;
+
/**
* Implementation of a handler for {@link IGnssStatusListener}.
*/
diff --git a/services/core/java/com/android/server/location/GnssVisibilityControl.java b/services/core/java/com/android/server/location/gnss/GnssVisibilityControl.java
index 2b5fc7989d8b..06fa0ea7791d 100644
--- a/services/core/java/com/android/server/location/GnssVisibilityControl.java
+++ b/services/core/java/com/android/server/location/gnss/GnssVisibilityControl.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.server.location;
+package com.android.server.location.gnss;
import android.annotation.Nullable;
import android.annotation.SuppressLint;
diff --git a/services/core/java/com/android/server/location/GpsPsdsDownloader.java b/services/core/java/com/android/server/location/gnss/GpsPsdsDownloader.java
index 6fcb7d1af2ce..273f9cb13a1b 100644
--- a/services/core/java/com/android/server/location/GpsPsdsDownloader.java
+++ b/services/core/java/com/android/server/location/gnss/GpsPsdsDownloader.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2008 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.server.location;
+package com.android.server.location.gnss;
import android.net.TrafficStats;
import android.text.TextUtils;
diff --git a/services/core/java/com/android/server/location/NtpTimeHelper.java b/services/core/java/com/android/server/location/gnss/NtpTimeHelper.java
index d2296ea27913..2bbb61fbe018 100644
--- a/services/core/java/com/android/server/location/NtpTimeHelper.java
+++ b/services/core/java/com/android/server/location/gnss/NtpTimeHelper.java
@@ -1,4 +1,20 @@
-package com.android.server.location;
+/*
+ * 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.location.gnss;
import android.content.Context;
import android.net.ConnectivityManager;
@@ -12,6 +28,7 @@ import android.util.NtpTrustedTime;
import com.android.internal.annotations.GuardedBy;
import com.android.internal.annotations.VisibleForTesting;
+import com.android.server.location.gnss.ExponentialBackOff;
import java.util.Date;
diff --git a/services/core/java/com/android/server/locksettings/LockSettingsService.java b/services/core/java/com/android/server/locksettings/LockSettingsService.java
index 1b4ec8a8fa32..01af83914800 100644
--- a/services/core/java/com/android/server/locksettings/LockSettingsService.java
+++ b/services/core/java/com/android/server/locksettings/LockSettingsService.java
@@ -3193,6 +3193,12 @@ public class LockSettingsService extends ILockSettings.Stub {
mStrongAuth.dump(pw);
pw.println();
pw.decreaseIndent();
+
+ pw.println("RebootEscrow:");
+ pw.increaseIndent();
+ mRebootEscrowManager.dump(pw);
+ pw.println();
+ pw.decreaseIndent();
}
/**
diff --git a/services/core/java/com/android/server/locksettings/RebootEscrowManager.java b/services/core/java/com/android/server/locksettings/RebootEscrowManager.java
index dabf88670639..8d4efed8604b 100644
--- a/services/core/java/com/android/server/locksettings/RebootEscrowManager.java
+++ b/services/core/java/com/android/server/locksettings/RebootEscrowManager.java
@@ -18,6 +18,7 @@ package com.android.server.locksettings;
import static android.os.UserHandle.USER_SYSTEM;
+import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.UserIdInt;
import android.content.Context;
@@ -25,6 +26,7 @@ import android.content.pm.UserInfo;
import android.hardware.rebootescrow.IRebootEscrow;
import android.os.RemoteException;
import android.os.ServiceManager;
+import android.os.SystemClock;
import android.os.UserManager;
import android.provider.Settings;
import android.util.Slog;
@@ -32,11 +34,15 @@ import android.util.Slog;
import com.android.internal.annotations.GuardedBy;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.util.FrameworkStatsLog;
+import com.android.internal.util.IndentingPrintWriter;
import com.android.internal.widget.RebootEscrowListener;
import java.io.IOException;
+import java.text.SimpleDateFormat;
import java.util.ArrayList;
+import java.util.Date;
import java.util.List;
+import java.util.Locale;
import java.util.NoSuchElementException;
class RebootEscrowManager {
@@ -63,6 +69,11 @@ class RebootEscrowManager {
private static final int BOOT_COUNT_TOLERANCE = 5;
/**
+ * Logs events for later debugging in bugreports.
+ */
+ private final RebootEscrowEventLog mEventLog;
+
+ /**
* Used to track when the reboot escrow is wanted. Should stay true once escrow is requested
* unless clearRebootEscrow is called. This will allow all the active users to be unlocked
* after reboot.
@@ -135,6 +146,10 @@ class RebootEscrowManager {
public void reportMetric(boolean success) {
FrameworkStatsLog.write(FrameworkStatsLog.REBOOT_ESCROW_RECOVERY_REPORTED, success);
}
+
+ public RebootEscrowEventLog getEventLog() {
+ return new RebootEscrowEventLog();
+ }
}
RebootEscrowManager(Context context, Callbacks callbacks, LockSettingsStorage storage) {
@@ -148,6 +163,7 @@ class RebootEscrowManager {
mCallbacks = callbacks;
mStorage = storage;
mUserManager = injector.getUserManager();
+ mEventLog = injector.getEventLog();
}
void loadRebootEscrowDataIfAvailable() {
@@ -173,6 +189,8 @@ class RebootEscrowManager {
return;
}
+ mEventLog.addEntry(RebootEscrowEvent.FOUND_ESCROW_DATA);
+
boolean allUsersUnlocked = true;
for (UserInfo user : rebootEscrowUsers) {
allUsersUnlocked &= restoreRebootEscrowForUser(user.id, escrowKey);
@@ -221,6 +239,7 @@ class RebootEscrowManager {
// Overwrite the existing key with the null key
rebootEscrow.storeKey(new byte[32]);
+ mEventLog.addEntry(RebootEscrowEvent.RETRIEVED_STORED_KEK);
return RebootEscrowKey.fromKeyBytes(escrowKeyBytes);
} catch (RemoteException e) {
Slog.w(TAG, "Could not retrieve escrow data");
@@ -242,6 +261,7 @@ class RebootEscrowManager {
mCallbacks.onRebootEscrowRestored(escrowData.getSpVersion(),
escrowData.getSyntheticPassword(), userId);
Slog.i(TAG, "Restored reboot escrow data for user " + userId);
+ mEventLog.addEntry(RebootEscrowEvent.RETRIEVED_LSKF_FOR_USER, userId);
return true;
} catch (IOException e) {
Slog.w(TAG, "Could not load reboot escrow data for user " + userId, e);
@@ -278,6 +298,7 @@ class RebootEscrowManager {
}
mStorage.writeRebootEscrow(userId, escrowData.getBlob());
+ mEventLog.addEntry(RebootEscrowEvent.STORED_LSKF_FOR_USER, userId);
setRebootEscrowReady(true);
}
@@ -322,6 +343,8 @@ class RebootEscrowManager {
for (UserInfo user : users) {
mStorage.removeRebootEscrow(user.id);
}
+
+ mEventLog.addEntry(RebootEscrowEvent.CLEARED_LSKF_REQUEST);
}
boolean armRebootEscrowIfNeeded() {
@@ -356,6 +379,7 @@ class RebootEscrowManager {
if (armedRebootEscrow) {
mStorage.setInt(REBOOT_ESCROW_ARMED_KEY, mInjector.getBootCount(), USER_SYSTEM);
+ mEventLog.addEntry(RebootEscrowEvent.SET_ARMED_STATUS);
}
return armedRebootEscrow;
@@ -375,6 +399,7 @@ class RebootEscrowManager {
clearRebootEscrowIfNeeded();
mRebootEscrowWanted = true;
+ mEventLog.addEntry(RebootEscrowEvent.REQUESTED_LSKF);
return true;
}
@@ -390,4 +415,123 @@ class RebootEscrowManager {
void setRebootEscrowListener(RebootEscrowListener listener) {
mRebootEscrowListener = listener;
}
+
+ @VisibleForTesting
+ public static class RebootEscrowEvent {
+ static final int FOUND_ESCROW_DATA = 1;
+ static final int SET_ARMED_STATUS = 2;
+ static final int CLEARED_LSKF_REQUEST = 3;
+ static final int RETRIEVED_STORED_KEK = 4;
+ static final int REQUESTED_LSKF = 5;
+ static final int STORED_LSKF_FOR_USER = 6;
+ static final int RETRIEVED_LSKF_FOR_USER = 7;
+
+ final int mEventId;
+ final Integer mUserId;
+ final long mWallTime;
+ final long mTimestamp;
+
+ RebootEscrowEvent(int eventId) {
+ this(eventId, null);
+ }
+
+ RebootEscrowEvent(int eventId, Integer userId) {
+ mEventId = eventId;
+ mUserId = userId;
+ mTimestamp = SystemClock.uptimeMillis();
+ mWallTime = System.currentTimeMillis();
+ }
+
+ String getEventDescription() {
+ switch (mEventId) {
+ case FOUND_ESCROW_DATA:
+ return "Found escrow data";
+ case SET_ARMED_STATUS:
+ return "Set armed status";
+ case CLEARED_LSKF_REQUEST:
+ return "Cleared request for LSKF";
+ case RETRIEVED_STORED_KEK:
+ return "Retrieved stored KEK";
+ case REQUESTED_LSKF:
+ return "Requested LSKF";
+ case STORED_LSKF_FOR_USER:
+ return "Stored LSKF for user";
+ case RETRIEVED_LSKF_FOR_USER:
+ return "Retrieved LSKF for user";
+ default:
+ return "Unknown event ID " + mEventId;
+ }
+ }
+ }
+
+ @VisibleForTesting
+ public static class RebootEscrowEventLog {
+ private RebootEscrowEvent[] mEntries = new RebootEscrowEvent[16];
+ private int mNextIndex = 0;
+
+ void addEntry(int eventId) {
+ addEntryInternal(new RebootEscrowEvent(eventId));
+ }
+
+ void addEntry(int eventId, int userId) {
+ addEntryInternal(new RebootEscrowEvent(eventId, userId));
+ }
+
+ private void addEntryInternal(RebootEscrowEvent event) {
+ final int index = mNextIndex;
+ mEntries[index] = event;
+ mNextIndex = (mNextIndex + 1) % mEntries.length;
+ }
+
+ void dump(@NonNull IndentingPrintWriter pw) {
+ SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS", Locale.US);
+
+ for (int i = 0; i < mEntries.length; ++i) {
+ RebootEscrowEvent event = mEntries[(i + mNextIndex) % mEntries.length];
+ if (event == null) {
+ continue;
+ }
+
+ pw.print("Event #");
+ pw.println(i);
+
+ pw.println(" time=" + sdf.format(new Date(event.mWallTime))
+ + " (timestamp=" + event.mTimestamp + ")");
+
+ pw.print(" event=");
+ pw.println(event.getEventDescription());
+
+ if (event.mUserId != null) {
+ pw.print(" user=");
+ pw.println(event.mUserId);
+ }
+ }
+ }
+ }
+
+ void dump(@NonNull IndentingPrintWriter pw) {
+ pw.print("mRebootEscrowWanted=");
+ pw.println(mRebootEscrowWanted);
+
+ pw.print("mRebootEscrowReady=");
+ pw.println(mRebootEscrowReady);
+
+ pw.print("mRebootEscrowListener=");
+ pw.println(mRebootEscrowListener);
+
+ boolean keySet;
+ synchronized (mKeyGenerationLock) {
+ keySet = mPendingRebootEscrowKey != null;
+ }
+
+ pw.print("mPendingRebootEscrowKey is ");
+ pw.println(keySet ? "set" : "not set");
+
+ pw.println();
+ pw.println("Event log:");
+ pw.increaseIndent();
+ mEventLog.dump(pw);
+ pw.println();
+ pw.decreaseIndent();
+ }
}
diff --git a/services/core/java/com/android/server/media/MediaRouter2ServiceImpl.java b/services/core/java/com/android/server/media/MediaRouter2ServiceImpl.java
index 9bbbc3b93fd7..6aae62ea3f18 100644
--- a/services/core/java/com/android/server/media/MediaRouter2ServiceImpl.java
+++ b/services/core/java/com/android/server/media/MediaRouter2ServiceImpl.java
@@ -708,7 +708,7 @@ class MediaRouter2ServiceImpl {
}
List<RoutingSessionInfo> sessionInfos = new ArrayList<>();
- for (MediaRoute2Provider provider : managerRecord.mUserRecord.mHandler.mMediaProviders) {
+ for (MediaRoute2Provider provider : managerRecord.mUserRecord.mHandler.mRouteProviders) {
sessionInfos.addAll(provider.getSessionInfos());
}
return sessionInfos;
@@ -1059,7 +1059,7 @@ class MediaRouter2ServiceImpl {
//TODO: Make this thread-safe.
private final SystemMediaRoute2Provider mSystemProvider;
- private final ArrayList<MediaRoute2Provider> mMediaProviders =
+ private final ArrayList<MediaRoute2Provider> mRouteProviders =
new ArrayList<>();
private final List<MediaRoute2ProviderInfo> mLastProviderInfos = new ArrayList<>();
@@ -1074,7 +1074,7 @@ class MediaRouter2ServiceImpl {
mServiceRef = new WeakReference<>(service);
mUserRecord = userRecord;
mSystemProvider = new SystemMediaRoute2Provider(service.mContext, this);
- mMediaProviders.add(mSystemProvider);
+ mRouteProviders.add(mSystemProvider);
mWatcher = new MediaRoute2ProviderWatcher(service.mContext, this,
this, mUserRecord.mUserId);
}
@@ -1097,13 +1097,13 @@ class MediaRouter2ServiceImpl {
@Override
public void onAddProviderService(@NonNull MediaRoute2ProviderServiceProxy proxy) {
proxy.setCallback(this);
- mMediaProviders.add(proxy);
+ mRouteProviders.add(proxy);
proxy.updateDiscoveryPreference(mUserRecord.mCompositeDiscoveryPreference);
}
@Override
public void onRemoveProviderService(@NonNull MediaRoute2ProviderServiceProxy proxy) {
- mMediaProviders.remove(proxy);
+ mRouteProviders.remove(proxy);
}
@Override
@@ -1148,10 +1148,10 @@ class MediaRouter2ServiceImpl {
//TODO: notify session info updates
private void onProviderStateChangedOnHandler(@NonNull MediaRoute2Provider provider) {
- int providerIndex = getProviderInfoIndex(provider.getUniqueId());
+ int providerInfoIndex = getLastProviderInfoIndex(provider.getUniqueId());
MediaRoute2ProviderInfo providerInfo = provider.getProviderInfo();
MediaRoute2ProviderInfo prevInfo =
- (providerIndex < 0) ? null : mLastProviderInfos.get(providerIndex);
+ (providerInfoIndex < 0) ? null : mLastProviderInfos.get(providerInfoIndex);
if (Objects.equals(prevInfo, providerInfo)) return;
@@ -1171,7 +1171,7 @@ class MediaRouter2ServiceImpl {
this, getRouters(), new ArrayList<>(removedRoutes)));
}
} else {
- mLastProviderInfos.set(providerIndex, providerInfo);
+ mLastProviderInfos.set(providerInfoIndex, providerInfo);
List<MediaRoute2Info> addedRoutes = new ArrayList<>();
List<MediaRoute2Info> removedRoutes = new ArrayList<>();
List<MediaRoute2Info> changedRoutes = new ArrayList<>();
@@ -1219,7 +1219,7 @@ class MediaRouter2ServiceImpl {
}
}
- private int getProviderInfoIndex(@NonNull String providerId) {
+ private int getLastProviderInfoIndex(@NonNull String providerId) {
for (int i = 0; i < mLastProviderInfos.size(); i++) {
MediaRoute2ProviderInfo providerInfo = mLastProviderInfos.get(i);
if (TextUtils.equals(providerInfo.getUniqueId(), providerId)) {
@@ -1795,13 +1795,13 @@ class MediaRouter2ServiceImpl {
new RouteDiscoveryPreference.Builder(discoveryPreferences)
.build();
}
- for (MediaRoute2Provider provider : mMediaProviders) {
+ for (MediaRoute2Provider provider : mRouteProviders) {
provider.updateDiscoveryPreference(mUserRecord.mCompositeDiscoveryPreference);
}
}
private MediaRoute2Provider findProvider(@Nullable String providerId) {
- for (MediaRoute2Provider provider : mMediaProviders) {
+ for (MediaRoute2Provider provider : mRouteProviders) {
if (TextUtils.equals(provider.getUniqueId(), providerId)) {
return provider;
}
diff --git a/services/core/java/com/android/server/media/SystemMediaRoute2Provider.java b/services/core/java/com/android/server/media/SystemMediaRoute2Provider.java
index c7d14e0afe7b..c69787d602e2 100644
--- a/services/core/java/com/android/server/media/SystemMediaRoute2Provider.java
+++ b/services/core/java/com/android/server/media/SystemMediaRoute2Provider.java
@@ -54,6 +54,7 @@ class SystemMediaRoute2Provider extends MediaRoute2Provider {
private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
static final String DEFAULT_ROUTE_ID = "DEFAULT_ROUTE";
+ static final String DEVICE_ROUTE_ID = "DEVICE_ROUTE";
static final String SYSTEM_SESSION_ID = "SYSTEM_SESSION";
private final AudioManager mAudioManager;
@@ -67,14 +68,17 @@ class SystemMediaRoute2Provider extends MediaRoute2Provider {
SystemMediaRoute2Provider.class.getName());
private String mSelectedRouteId;
+ // For apps without MODIFYING_AUDIO_ROUTING permission.
+ // This should be the currently selected route.
MediaRoute2Info mDefaultRoute;
+ MediaRoute2Info mDeviceRoute;
final AudioRoutesInfo mCurAudioRoutesInfo = new AudioRoutesInfo();
final IAudioRoutesObserver.Stub mAudioRoutesObserver = new IAudioRoutesObserver.Stub() {
@Override
public void dispatchAudioRoutesChanged(final AudioRoutesInfo newRoutes) {
mHandler.post(() -> {
- updateDefaultRoute(newRoutes);
+ updateDeviceRoute(newRoutes);
notifyProviderState();
});
}
@@ -97,7 +101,7 @@ class SystemMediaRoute2Provider extends MediaRoute2Provider {
newAudioRoutes = mAudioService.startWatchingRoutes(mAudioRoutesObserver);
} catch (RemoteException e) {
}
- updateDefaultRoute(newAudioRoutes);
+ updateDeviceRoute(newAudioRoutes);
mBtRouteProvider = BluetoothRouteProvider.getInstance(context, (routes) -> {
publishProviderState();
@@ -109,7 +113,6 @@ class SystemMediaRoute2Provider extends MediaRoute2Provider {
}
});
updateSessionInfosIfNeeded();
-
mContext.registerReceiver(new VolumeChangeReceiver(),
new IntentFilter(AudioManager.VOLUME_CHANGED_ACTION));
@@ -150,7 +153,7 @@ class SystemMediaRoute2Provider extends MediaRoute2Provider {
@Override
public void transferToRoute(long requestId, String sessionId, String routeId) {
- if (TextUtils.equals(routeId, mDefaultRoute.getId())) {
+ if (TextUtils.equals(routeId, mDeviceRoute.getId())) {
mBtRouteProvider.transferTo(null);
} else {
mBtRouteProvider.transferTo(routeId);
@@ -170,7 +173,11 @@ class SystemMediaRoute2Provider extends MediaRoute2Provider {
// Do nothing since we don't support grouping volume yet.
}
- private void updateDefaultRoute(AudioRoutesInfo newRoutes) {
+ public MediaRoute2Info getDefaultRoute() {
+ return mDefaultRoute;
+ }
+
+ private void updateDeviceRoute(AudioRoutesInfo newRoutes) {
int name = R.string.default_audio_route_name;
if (newRoutes != null) {
mCurAudioRoutesInfo.mainType = newRoutes.mainType;
@@ -185,8 +192,8 @@ class SystemMediaRoute2Provider extends MediaRoute2Provider {
name = com.android.internal.R.string.default_audio_route_name_usb;
}
}
- mDefaultRoute = new MediaRoute2Info.Builder(
- DEFAULT_ROUTE_ID, mContext.getResources().getText(name).toString())
+ mDeviceRoute = new MediaRoute2Info.Builder(
+ DEVICE_ROUTE_ID, mContext.getResources().getText(name).toString())
.setVolumeHandling(mAudioManager.isVolumeFixed()
? MediaRoute2Info.PLAYBACK_VOLUME_FIXED
: MediaRoute2Info.PLAYBACK_VOLUME_VARIABLE)
@@ -203,7 +210,7 @@ class SystemMediaRoute2Provider extends MediaRoute2Provider {
private void updateProviderState() {
MediaRoute2ProviderInfo.Builder builder = new MediaRoute2ProviderInfo.Builder();
- builder.addRoute(mDefaultRoute);
+ builder.addRoute(mDeviceRoute);
if (mBtRouteProvider != null) {
for (MediaRoute2Info route : mBtRouteProvider.getAllBluetoothRoutes()) {
builder.addRoute(route);
@@ -228,11 +235,12 @@ class SystemMediaRoute2Provider extends MediaRoute2Provider {
MediaRoute2Info selectedRoute = mBtRouteProvider.getSelectedRoute();
if (selectedRoute == null) {
- selectedRoute = mDefaultRoute;
+ selectedRoute = mDeviceRoute;
} else {
- builder.addTransferableRoute(mDefaultRoute.getId());
+ builder.addTransferableRoute(mDeviceRoute.getId());
}
mSelectedRouteId = selectedRoute.getId();
+ mDefaultRoute = new MediaRoute2Info.Builder(DEFAULT_ROUTE_ID, selectedRoute).build();
builder.addSelectedRoute(mSelectedRouteId);
for (MediaRoute2Info route : mBtRouteProvider.getTransferableRoutes()) {
@@ -282,8 +290,8 @@ class SystemMediaRoute2Provider extends MediaRoute2Provider {
AudioManager.EXTRA_PREV_VOLUME_STREAM_VALUE, 0);
if (newVolume != oldVolume) {
- if (TextUtils.equals(mDefaultRoute.getId(), mSelectedRouteId)) {
- mDefaultRoute = new MediaRoute2Info.Builder(mDefaultRoute)
+ if (TextUtils.equals(mDeviceRoute.getId(), mSelectedRouteId)) {
+ mDeviceRoute = new MediaRoute2Info.Builder(mDeviceRoute)
.setVolume(newVolume)
.build();
} else {
diff --git a/services/core/java/com/android/server/notification/BubbleExtractor.java b/services/core/java/com/android/server/notification/BubbleExtractor.java
index f2eb176aa676..2fa80cd8e4e4 100644
--- a/services/core/java/com/android/server/notification/BubbleExtractor.java
+++ b/services/core/java/com/android/server/notification/BubbleExtractor.java
@@ -76,7 +76,8 @@ public class BubbleExtractor implements NotificationSignalExtractor {
record.setAllowBubble(appCanShowBubble);
}
}
- final boolean applyFlag = mBubbleChecker.isNotificationAppropriateToBubble(record);
+ final boolean applyFlag = mBubbleChecker.isNotificationAppropriateToBubble(record)
+ && !record.isFlagBubbleRemoved();
if (applyFlag) {
record.getNotification().flags |= FLAG_BUBBLE;
} else {
diff --git a/services/core/java/com/android/server/notification/NotificationManagerService.java b/services/core/java/com/android/server/notification/NotificationManagerService.java
index 31dc09416ac8..4aeddc89f6ed 100755
--- a/services/core/java/com/android/server/notification/NotificationManagerService.java
+++ b/services/core/java/com/android/server/notification/NotificationManagerService.java
@@ -107,6 +107,7 @@ import android.annotation.CallbackExecutor;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.RequiresPermission;
+import android.annotation.UserIdInt;
import android.annotation.WorkerThread;
import android.app.ActivityManager;
import android.app.ActivityManagerInternal;
@@ -1213,10 +1214,12 @@ public class NotificationManagerService extends SystemService {
// apps querying noMan will know that their notification is not showing
// as a bubble.
r.getNotification().flags &= ~FLAG_BUBBLE;
+ r.setFlagBubbleRemoved(true);
} else {
// Enqueue will trigger resort & if the flag is allowed to be true it'll
// be applied there.
r.getNotification().flags |= FLAG_ONLY_ALERT_ONCE;
+ r.setFlagBubbleRemoved(false);
mHandler.post(new EnqueueNotificationRunnable(r.getUser().getIdentifier(),
r, isAppForeground));
}
@@ -1867,7 +1870,8 @@ public class NotificationManagerService extends SystemService {
ActivityTaskManagerInternal atm, UsageStatsManagerInternal appUsageStats,
DevicePolicyManagerInternal dpm, IUriGrantsManager ugm,
UriGrantsManagerInternal ugmInternal, AppOpsManager appOps, UserManager userManager,
- NotificationHistoryManager historyManager, StatsManager statsManager) {
+ NotificationHistoryManager historyManager, StatsManager statsManager,
+ TelephonyManager telephonyManager) {
mHandler = handler;
Resources resources = getContext().getResources();
mMaxPackageEnqueueRate = Settings.Global.getFloat(getContext().getContentResolver(),
@@ -2010,7 +2014,15 @@ public class NotificationManagerService extends SystemService {
mInterruptionFilter = mZenModeHelper.getZenModeListenerInterruptionFilter();
mUserProfiles.updateCache(getContext());
- listenForCallState();
+
+ telephonyManager.listen(new PhoneStateListener() {
+ @Override
+ public void onCallStateChanged(int state, String incomingNumber) {
+ if (mCallState == state) return;
+ if (DBG) Slog.d(TAG, "Call state changed: " + callStateToString(state));
+ mCallState = state;
+ }
+ }, PhoneStateListener.LISTEN_CALL_STATE);
mSettingsObserver = new SettingsObserver(mHandler);
@@ -2080,7 +2092,8 @@ public class NotificationManagerService extends SystemService {
getContext().getSystemService(UserManager.class),
new NotificationHistoryManager(getContext(), handler),
mStatsManager = (StatsManager) getContext().getSystemService(
- Context.STATS_MANAGER));
+ Context.STATS_MANAGER),
+ getContext().getSystemService(TelephonyManager.class));
// register for various Intents
IntentFilter filter = new IntentFilter();
@@ -2842,20 +2855,18 @@ public class NotificationManagerService extends SystemService {
record = mToastQueue.get(index);
record.update(duration);
} else {
- // Limit the number of toasts that any given package except the android
- // package can enqueue. Prevents DOS attacks and deals with leaks.
- if (!isSystemToast) {
- int count = 0;
- final int N = mToastQueue.size();
- for (int i = 0; i < N; i++) {
- final ToastRecord r = mToastQueue.get(i);
- if (r.pkg.equals(pkg)) {
- count++;
- if (count >= MAX_PACKAGE_NOTIFICATIONS) {
- Slog.e(TAG, "Package has already posted " + count
- + " toasts. Not showing more. Package=" + pkg);
- return;
- }
+ // Limit the number of toasts that any given package can enqueue.
+ // Prevents DOS attacks and deals with leaks.
+ int count = 0;
+ final int N = mToastQueue.size();
+ for (int i = 0; i < N; i++) {
+ final ToastRecord r = mToastQueue.get(i);
+ if (r.pkg.equals(pkg)) {
+ count++;
+ if (count >= MAX_PACKAGE_NOTIFICATIONS) {
+ Slog.e(TAG, "Package has already posted " + count
+ + " toasts. Not showing more. Package=" + pkg);
+ return;
}
}
}
@@ -5638,6 +5649,7 @@ public class NotificationManagerService extends SystemService {
final NotificationRecord r = new NotificationRecord(getContext(), n, channel);
r.setIsAppImportanceLocked(mPreferencesHelper.getIsAppImportanceLocked(pkg, callingUid));
r.setPostSilently(postSilently);
+ r.setFlagBubbleRemoved(false);
if ((notification.flags & Notification.FLAG_FOREGROUND_SERVICE) != 0) {
final boolean fgServiceShown = channel.isFgServiceShown();
@@ -8356,17 +8368,6 @@ public class NotificationManagerService extends SystemService {
}
}
- private void listenForCallState() {
- getContext().getSystemService(TelephonyManager.class).listen(new PhoneStateListener() {
- @Override
- public void onCallStateChanged(int state, String incomingNumber) {
- if (mCallState == state) return;
- if (DBG) Slog.d(TAG, "Call state changed: " + callStateToString(state));
- mCallState = state;
- }
- }, PhoneStateListener.LISTEN_CALL_STATE);
- }
-
/**
* Generates a NotificationRankingUpdate from 'sbns', considering only
* notifications visible to the given listener.
diff --git a/services/core/java/com/android/server/notification/NotificationRecord.java b/services/core/java/com/android/server/notification/NotificationRecord.java
index 3f24b38161c3..54a0f9f46892 100644
--- a/services/core/java/com/android/server/notification/NotificationRecord.java
+++ b/services/core/java/com/android/server/notification/NotificationRecord.java
@@ -187,6 +187,7 @@ public final class NotificationRecord {
private boolean mSuggestionsGeneratedByAssistant;
private boolean mEditChoicesBeforeSending;
private boolean mHasSeenSmartReplies;
+ private boolean mFlagBubbleRemoved;
private boolean mPostSilently;
/**
* Whether this notification (and its channels) should be considered user locked. Used in
@@ -1201,6 +1202,19 @@ public final class NotificationRecord {
return stats.hasBeenVisiblyExpanded();
}
+ /**
+ * When the bubble state on a notif changes due to user action (e.g. dismiss a bubble) then
+ * this value is set until an update or bubble change event due to user action (e.g. create
+ * bubble from sysui)
+ **/
+ public boolean isFlagBubbleRemoved() {
+ return mFlagBubbleRemoved;
+ }
+
+ public void setFlagBubbleRemoved(boolean flagBubbleRemoved) {
+ mFlagBubbleRemoved = flagBubbleRemoved;
+ }
+
public void setSystemGeneratedSmartActions(
ArrayList<Notification.Action> systemGeneratedSmartActions) {
mSystemGeneratedSmartActions = systemGeneratedSmartActions;
diff --git a/services/core/java/com/android/server/pm/PackageInstallerSession.java b/services/core/java/com/android/server/pm/PackageInstallerSession.java
index 42ed20654a2c..1248ec01e020 100644
--- a/services/core/java/com/android/server/pm/PackageInstallerSession.java
+++ b/services/core/java/com/android/server/pm/PackageInstallerSession.java
@@ -3245,8 +3245,7 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub {
new ComponentName(
readStringAttribute(in, ATTR_DATALOADER_PACKAGE_NAME),
readStringAttribute(in, ATTR_DATALOADER_CLASS_NAME)),
- readStringAttribute(in, ATTR_DATALOADER_ARGUMENTS),
- null);
+ readStringAttribute(in, ATTR_DATALOADER_ARGUMENTS));
}
final File appIconFile = buildAppIconFile(sessionId, sessionsDir);
diff --git a/services/core/java/com/android/server/pm/PackageManagerShellCommand.java b/services/core/java/com/android/server/pm/PackageManagerShellCommand.java
index 8a9f1b3afd02..4d49a643485f 100644
--- a/services/core/java/com/android/server/pm/PackageManagerShellCommand.java
+++ b/services/core/java/com/android/server/pm/PackageManagerShellCommand.java
@@ -105,6 +105,7 @@ import com.android.internal.util.ArrayUtils;
import com.android.internal.util.IndentingPrintWriter;
import com.android.server.LocalServices;
import com.android.server.SystemConfig;
+import com.android.server.pm.PackageManagerShellCommandDataLoader.Metadata;
import dalvik.system.DexFile;
@@ -118,7 +119,6 @@ import java.io.InputStream;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.net.URISyntaxException;
-import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.Base64;
import java.util.Collection;
@@ -3025,9 +3025,9 @@ class PackageManagerShellCommand extends ShellCommand {
// 1. Single file from stdin.
if (args.isEmpty() || STDIN_PATH.equals(args.get(0))) {
final String name = "base." + (isApex ? "apex" : "apk");
- final String metadata = "-" + name;
+ final Metadata metadata = Metadata.forStdIn(name);
session.addFile(LOCATION_DATA_APP, name, sessionSizeBytes,
- metadata.getBytes(StandardCharsets.UTF_8), null);
+ metadata.toByteArray(), null);
return 0;
}
@@ -3056,9 +3056,10 @@ class PackageManagerShellCommand extends ShellCommand {
private int processArgForStdin(String arg, PackageInstaller.Session session) {
final String[] fileDesc = arg.split(":");
- String name, metadata;
+ String name, fileId;
long sizeBytes;
byte[] signature = null;
+ int streamingVersion = 0;
try {
if (fileDesc.length < 2) {
@@ -3067,14 +3068,22 @@ class PackageManagerShellCommand extends ShellCommand {
}
name = fileDesc[0];
sizeBytes = Long.parseUnsignedLong(fileDesc[1]);
- metadata = name;
+ fileId = name;
if (fileDesc.length > 2 && !TextUtils.isEmpty(fileDesc[2])) {
- metadata = fileDesc[2];
+ fileId = fileDesc[2];
}
if (fileDesc.length > 3) {
signature = Base64.getDecoder().decode(fileDesc[3]);
}
+ if (fileDesc.length > 4) {
+ streamingVersion = Integer.parseUnsignedInt(fileDesc[4]);
+ if (streamingVersion < 0 || streamingVersion > 1) {
+ getErrPrintWriter().println(
+ "Unsupported streaming version: " + streamingVersion);
+ return 1;
+ }
+ }
} catch (IllegalArgumentException e) {
getErrPrintWriter().println(
"Unable to parse file parameters: " + arg + ", reason: " + e);
@@ -3086,9 +3095,14 @@ class PackageManagerShellCommand extends ShellCommand {
return 1;
}
+ final Metadata metadata;
+
if (signature != null) {
- // Streaming/adb mode.
- metadata = "+" + metadata;
+ // Streaming/adb mode. Versions:
+ // 0: data only streaming, tree has to be fully available,
+ // 1: tree and data streaming.
+ metadata = (streamingVersion == 0) ? Metadata.forDataOnlyStreaming(fileId)
+ : Metadata.forStreaming(fileId);
try {
if (V4Signature.readFrom(signature) == null) {
getErrPrintWriter().println("V4 signature is invalid in: " + arg);
@@ -3101,11 +3115,10 @@ class PackageManagerShellCommand extends ShellCommand {
}
} else {
// Single-shot read from stdin.
- metadata = "-" + metadata;
+ metadata = Metadata.forStdIn(fileId);
}
- session.addFile(LOCATION_DATA_APP, name, sizeBytes,
- metadata.getBytes(StandardCharsets.UTF_8), signature);
+ session.addFile(LOCATION_DATA_APP, name, sizeBytes, metadata.toByteArray(), signature);
return 0;
}
@@ -3115,7 +3128,7 @@ class PackageManagerShellCommand extends ShellCommand {
final File file = new File(inPath);
final String name = file.getName();
final long size = file.length();
- final byte[] metadata = inPath.getBytes(StandardCharsets.UTF_8);
+ final Metadata metadata = Metadata.forLocalFile(inPath);
byte[] v4signatureBytes = null;
// Try to load the v4 signature file for the APK; it might not exist.
@@ -3132,7 +3145,7 @@ class PackageManagerShellCommand extends ShellCommand {
}
}
- session.addFile(LOCATION_DATA_APP, name, size, metadata, v4signatureBytes);
+ session.addFile(LOCATION_DATA_APP, name, size, metadata.toByteArray(), v4signatureBytes);
}
private int doWriteSplits(int sessionId, ArrayList<String> splitPaths, long sessionSizeBytes,
diff --git a/services/core/java/com/android/server/pm/PackageManagerShellCommandDataLoader.java b/services/core/java/com/android/server/pm/PackageManagerShellCommandDataLoader.java
index 6d83d70f1cb1..2aa6e5737e9b 100644
--- a/services/core/java/com/android/server/pm/PackageManagerShellCommandDataLoader.java
+++ b/services/core/java/com/android/server/pm/PackageManagerShellCommandDataLoader.java
@@ -24,7 +24,6 @@ import android.content.pm.PackageInstaller;
import android.os.ParcelFileDescriptor;
import android.os.ShellCommand;
import android.service.dataloader.DataLoaderService;
-import android.text.TextUtils;
import android.util.Slog;
import android.util.SparseArray;
@@ -114,6 +113,74 @@ public class PackageManagerShellCommandDataLoader extends DataLoaderService {
}
}
+ static class Metadata {
+ /**
+ * Full files read from stdin.
+ */
+ static final byte STDIN = 0;
+ /**
+ * Full files read from local file.
+ */
+ static final byte LOCAL_FILE = 1;
+ /**
+ * Signature tree read from stdin, data streamed.
+ */
+ static final byte DATA_ONLY_STREAMING = 2;
+ /**
+ * Everything streamed.
+ */
+ static final byte STREAMING = 3;
+
+ private final byte mMode;
+ private final String mData;
+
+ static Metadata forStdIn(String fileId) {
+ return new Metadata(STDIN, fileId);
+ }
+
+ static Metadata forLocalFile(String filePath) {
+ return new Metadata(LOCAL_FILE, filePath);
+ }
+
+ static Metadata forDataOnlyStreaming(String fileId) {
+ return new Metadata(DATA_ONLY_STREAMING, fileId);
+ }
+
+ static Metadata forStreaming(String fileId) {
+ return new Metadata(STREAMING, fileId);
+ }
+
+ private Metadata(byte mode, String data) {
+ this.mMode = mode;
+ this.mData = (data == null) ? "" : data;
+ }
+
+ static Metadata fromByteArray(byte[] bytes) throws IOException {
+ if (bytes == null || bytes.length == 0) {
+ return null;
+ }
+ byte mode = bytes[0];
+ String data = new String(bytes, 1, bytes.length - 1, StandardCharsets.UTF_8);
+ return new Metadata(mode, data);
+ }
+
+ byte[] toByteArray() {
+ byte[] dataBytes = this.mData.getBytes(StandardCharsets.UTF_8);
+ byte[] result = new byte[1 + dataBytes.length];
+ result[0] = this.mMode;
+ System.arraycopy(dataBytes, 0, result, 1, dataBytes.length);
+ return result;
+ }
+
+ byte getMode() {
+ return this.mMode;
+ }
+
+ String getData() {
+ return this.mData;
+ }
+ }
+
private static class DataLoader implements DataLoaderService.DataLoader {
private DataLoaderParams mParams = null;
private FileSystemConnector mConnector = null;
@@ -136,19 +203,31 @@ public class PackageManagerShellCommandDataLoader extends DataLoaderService {
}
try {
for (InstallationFile file : addedFiles) {
- String filePath = new String(file.getMetadata(), StandardCharsets.UTF_8);
- if (TextUtils.isEmpty(filePath) || filePath.startsWith(STDIN_PATH)) {
- final ParcelFileDescriptor inFd = getStdInPFD(shellCommand);
- mConnector.writeData(file.getName(), 0, file.getLengthBytes(), inFd);
- } else {
- ParcelFileDescriptor incomingFd = null;
- try {
- incomingFd = getLocalFile(shellCommand, filePath);
- mConnector.writeData(file.getName(), 0, incomingFd.getStatSize(),
- incomingFd);
- } finally {
- IoUtils.closeQuietly(incomingFd);
+ Metadata metadata = Metadata.fromByteArray(file.getMetadata());
+ if (metadata == null) {
+ Slog.e(TAG, "Invalid metadata for file: " + file.getName());
+ return false;
+ }
+ switch (metadata.getMode()) {
+ case Metadata.STDIN: {
+ final ParcelFileDescriptor inFd = getStdInPFD(shellCommand);
+ mConnector.writeData(file.getName(), 0, file.getLengthBytes(), inFd);
+ break;
+ }
+ case Metadata.LOCAL_FILE: {
+ ParcelFileDescriptor incomingFd = null;
+ try {
+ incomingFd = getLocalFile(shellCommand, metadata.getData());
+ mConnector.writeData(file.getName(), 0, incomingFd.getStatSize(),
+ incomingFd);
+ } finally {
+ IoUtils.closeQuietly(incomingFd);
+ }
+ break;
}
+ default:
+ Slog.e(TAG, "Unsupported metadata mode: " + metadata.getMode());
+ return false;
}
}
return true;
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 765ecb9710cb..82c02a4ebefe 100644
--- a/services/core/java/com/android/server/pm/permission/PermissionManagerService.java
+++ b/services/core/java/com/android/server/pm/permission/PermissionManagerService.java
@@ -3319,47 +3319,51 @@ public class PermissionManagerService extends IPermissionManager.Stub {
if (!privappPermissionsDisable && privilegedPermission && pkg.isPrivileged()
&& !platformPackage && platformPermission) {
if (!hasPrivappWhitelistEntry(perm, pkg)) {
- ApexManager apexMgr = ApexManager.getInstance();
- String apexContainingPkg = apexMgr.getActiveApexPackageNameContainingPackage(pkg);
-
// Only enforce whitelist this on boot
if (!mSystemReady
// Updated system apps do not need to be whitelisted
- && !pkgSetting.getPkgState().isUpdatedSystemApp()
- // Apps that are in updated apexs' do not need to be whitelisted
- && (apexContainingPkg == null || apexMgr.isFactory(
- apexMgr.getPackageInfo(apexContainingPkg, MATCH_ACTIVE_PACKAGE)))) {
- // it's only a reportable violation if the permission isn't explicitly denied
- ArraySet<String> deniedPermissions = null;
- if (pkg.isVendor()) {
- deniedPermissions = SystemConfig.getInstance()
- .getVendorPrivAppDenyPermissions(pkg.getPackageName());
- } else if (pkg.isProduct()) {
- deniedPermissions = SystemConfig.getInstance()
- .getProductPrivAppDenyPermissions(pkg.getPackageName());
- } else if (pkg.isSystemExt()) {
- deniedPermissions = SystemConfig.getInstance()
- .getSystemExtPrivAppDenyPermissions(pkg.getPackageName());
- } else {
- deniedPermissions = SystemConfig.getInstance()
- .getPrivAppDenyPermissions(pkg.getPackageName());
- }
- final boolean permissionViolation =
- deniedPermissions == null || !deniedPermissions.contains(perm);
- if (permissionViolation) {
- Slog.w(TAG, "Privileged permission " + perm + " for package "
- + pkg.getPackageName() + " (" + pkg.getCodePath()
- + ") not in privapp-permissions whitelist");
-
- if (RoSystemProperties.CONTROL_PRIVAPP_PERMISSIONS_ENFORCE) {
- if (mPrivappPermissionsViolations == null) {
- mPrivappPermissionsViolations = new ArraySet<>();
+ && !pkgSetting.getPkgState().isUpdatedSystemApp()) {
+ ApexManager apexMgr = ApexManager.getInstance();
+ String apexContainingPkg = apexMgr.getActiveApexPackageNameContainingPackage(
+ pkg);
+
+ // Apps that are in updated apexs' do not need to be whitelisted
+ if (apexContainingPkg == null || apexMgr.isFactory(
+ apexMgr.getPackageInfo(apexContainingPkg, MATCH_ACTIVE_PACKAGE))) {
+ // it's only a reportable violation if the permission isn't explicitly
+ // denied
+ ArraySet<String> deniedPermissions = null;
+ if (pkg.isVendor()) {
+ deniedPermissions = SystemConfig.getInstance()
+ .getVendorPrivAppDenyPermissions(pkg.getPackageName());
+ } else if (pkg.isProduct()) {
+ deniedPermissions = SystemConfig.getInstance()
+ .getProductPrivAppDenyPermissions(pkg.getPackageName());
+ } else if (pkg.isSystemExt()) {
+ deniedPermissions = SystemConfig.getInstance()
+ .getSystemExtPrivAppDenyPermissions(pkg.getPackageName());
+ } else {
+ deniedPermissions = SystemConfig.getInstance()
+ .getPrivAppDenyPermissions(pkg.getPackageName());
+ }
+ final boolean permissionViolation =
+ deniedPermissions == null || !deniedPermissions.contains(perm);
+ if (permissionViolation) {
+ Slog.w(TAG, "Privileged permission " + perm + " for package "
+ + pkg.getPackageName() + " (" + pkg.getCodePath()
+ + ") not in privapp-permissions whitelist");
+
+ if (RoSystemProperties.CONTROL_PRIVAPP_PERMISSIONS_ENFORCE) {
+ if (mPrivappPermissionsViolations == null) {
+ mPrivappPermissionsViolations = new ArraySet<>();
+ }
+ mPrivappPermissionsViolations.add(
+ pkg.getPackageName() + " (" + pkg.getCodePath() + "): "
+ + perm);
}
- mPrivappPermissionsViolations.add(
- pkg.getPackageName() + " (" + pkg.getCodePath() + "): " + perm);
+ } else {
+ return false;
}
- } else {
- return false;
}
}
if (RoSystemProperties.CONTROL_PRIVAPP_PERMISSIONS_ENFORCE) {
diff --git a/services/core/java/com/android/server/policy/PhoneWindowManager.java b/services/core/java/com/android/server/policy/PhoneWindowManager.java
index 1e1256547f2c..c9736401f680 100644
--- a/services/core/java/com/android/server/policy/PhoneWindowManager.java
+++ b/services/core/java/com/android/server/policy/PhoneWindowManager.java
@@ -49,7 +49,6 @@ import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_SYSTEM_ERROR;
import static android.view.WindowManager.LayoutParams.TYPE_ACCESSIBILITY_OVERLAY;
import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY;
import static android.view.WindowManager.LayoutParams.TYPE_DOCK_DIVIDER;
-import static android.view.WindowManager.LayoutParams.TYPE_DREAM;
import static android.view.WindowManager.LayoutParams.TYPE_INPUT_METHOD;
import static android.view.WindowManager.LayoutParams.TYPE_KEYGUARD_DIALOG;
import static android.view.WindowManager.LayoutParams.TYPE_NAVIGATION_BAR;
@@ -2091,7 +2090,6 @@ public class PhoneWindowManager implements WindowManagerPolicy {
// Window manager does the checking for this.
outAppOp[0] = OP_TOAST_WINDOW;
return ADD_OKAY;
- case TYPE_DREAM:
case TYPE_INPUT_METHOD:
case TYPE_WALLPAPER:
case TYPE_PRESENTATION:
@@ -2230,7 +2228,6 @@ public class PhoneWindowManager implements WindowManagerPolicy {
case TYPE_STATUS_BAR:
case TYPE_NAVIGATION_BAR:
case TYPE_WALLPAPER:
- case TYPE_DREAM:
return false;
default:
// Hide only windows below the keyguard host window.
diff --git a/services/core/java/com/android/server/policy/WindowManagerPolicy.java b/services/core/java/com/android/server/policy/WindowManagerPolicy.java
index efe2af3352c2..7eb3f01798c5 100644
--- a/services/core/java/com/android/server/policy/WindowManagerPolicy.java
+++ b/services/core/java/com/android/server/policy/WindowManagerPolicy.java
@@ -31,7 +31,6 @@ import static android.view.WindowManager.LayoutParams.TYPE_BOOT_PROGRESS;
import static android.view.WindowManager.LayoutParams.TYPE_DISPLAY_OVERLAY;
import static android.view.WindowManager.LayoutParams.TYPE_DOCK_DIVIDER;
import static android.view.WindowManager.LayoutParams.TYPE_DRAG;
-import static android.view.WindowManager.LayoutParams.TYPE_DREAM;
import static android.view.WindowManager.LayoutParams.TYPE_INPUT_CONSUMER;
import static android.view.WindowManager.LayoutParams.TYPE_INPUT_METHOD;
import static android.view.WindowManager.LayoutParams.TYPE_INPUT_METHOD_DIALOG;
@@ -806,9 +805,6 @@ public interface WindowManagerPolicy extends WindowManagerPolicyConstants {
return canAddInternalSystemWindow ? 13 : 10;
case TYPE_APPLICATION_OVERLAY:
return 12;
- case TYPE_DREAM:
- // used for Dreams (screensavers with TYPE_DREAM windows)
- return 14;
case TYPE_INPUT_METHOD:
// on-screen keyboards and other such input method user interfaces go here.
return 15;
diff --git a/services/core/java/com/android/server/security/FileIntegrityService.java b/services/core/java/com/android/server/security/FileIntegrityService.java
index 482090a02025..841aca5a8d6f 100644
--- a/services/core/java/com/android/server/security/FileIntegrityService.java
+++ b/services/core/java/com/android/server/security/FileIntegrityService.java
@@ -18,14 +18,19 @@ package com.android.server.security;
import android.annotation.NonNull;
import android.annotation.Nullable;
+import android.app.AppOpsManager;
import android.content.Context;
import android.content.pm.PackageManager;
+import android.content.pm.PackageManagerInternal;
+import android.os.Binder;
import android.os.Build;
import android.os.IBinder;
import android.os.SystemProperties;
+import android.os.UserHandle;
import android.security.IFileIntegrityService;
import android.util.Slog;
+import com.android.server.LocalServices;
import com.android.server.SystemService;
import java.io.ByteArrayInputStream;
@@ -58,10 +63,10 @@ public class FileIntegrityService extends SystemService {
}
@Override
- public boolean isAppSourceCertificateTrusted(@Nullable byte[] certificateBytes) {
- enforceAnyCallingPermissions(
- android.Manifest.permission.REQUEST_INSTALL_PACKAGES,
- android.Manifest.permission.INSTALL_PACKAGES);
+ public boolean isAppSourceCertificateTrusted(@Nullable byte[] certificateBytes,
+ @NonNull String packageName) {
+ checkCallerPermission(packageName);
+
try {
if (!isApkVeritySupported()) {
return false;
@@ -77,14 +82,30 @@ public class FileIntegrityService extends SystemService {
}
}
- private void enforceAnyCallingPermissions(String ...permissions) {
- for (String permission : permissions) {
- if (getContext().checkCallingPermission(permission)
- == PackageManager.PERMISSION_GRANTED) {
- return;
- }
+ private void checkCallerPermission(String packageName) {
+ final int callingUid = Binder.getCallingUid();
+ final int callingUserId = UserHandle.getUserId(callingUid);
+ final PackageManagerInternal packageManager =
+ LocalServices.getService(PackageManagerInternal.class);
+ final int packageUid = packageManager.getPackageUid(
+ packageName, 0 /*flag*/, callingUserId);
+ if (callingUid != packageUid) {
+ throw new SecurityException(
+ "Calling uid " + callingUid + " does not own package " + packageName);
+ }
+
+ if (getContext().checkCallingPermission(android.Manifest.permission.INSTALL_PACKAGES)
+ == PackageManager.PERMISSION_GRANTED) {
+ return;
+ }
+
+ final AppOpsManager appOpsManager = getContext().getSystemService(AppOpsManager.class);
+ final int mode = appOpsManager.checkOpNoThrow(
+ AppOpsManager.OP_REQUEST_INSTALL_PACKAGES, callingUid, packageName);
+ if (mode != AppOpsManager.MODE_ALLOWED) {
+ throw new SecurityException(
+ "Caller should have INSTALL_PACKAGES or REQUEST_INSTALL_PACKAGES");
}
- throw new SecurityException("Insufficient permission");
}
};
diff --git a/services/core/java/com/android/server/soundtrigger_middleware/SoundTriggerMiddlewareValidation.java b/services/core/java/com/android/server/soundtrigger_middleware/SoundTriggerMiddlewareValidation.java
index a9e8d3fc7a3a..06f2d65c13b2 100644
--- a/services/core/java/com/android/server/soundtrigger_middleware/SoundTriggerMiddlewareValidation.java
+++ b/services/core/java/com/android/server/soundtrigger_middleware/SoundTriggerMiddlewareValidation.java
@@ -108,6 +108,12 @@ import java.util.Set;
public class SoundTriggerMiddlewareValidation implements ISoundTriggerMiddlewareService, Dumpable {
private static final String TAG = "SoundTriggerMiddlewareValidation";
+ private enum ModuleState {
+ ALIVE,
+ DETACHED,
+ DEAD
+ };
+
private final @NonNull ISoundTriggerMiddlewareService mDelegate;
private final @NonNull Context mContext;
private Map<Integer, Set<ModuleService>> mModules;
@@ -381,6 +387,7 @@ public class SoundTriggerMiddlewareValidation implements ISoundTriggerMiddleware
private ISoundTriggerModule mDelegate;
private @NonNull Map<Integer, ModelState> mLoadedModels = new HashMap<>();
private final int mHandle;
+ private ModuleState mState = ModuleState.ALIVE;
ModuleService(int handle, @NonNull ISoundTriggerCallback callback) {
mCallback = callback;
@@ -406,7 +413,7 @@ public class SoundTriggerMiddlewareValidation implements ISoundTriggerMiddleware
synchronized (SoundTriggerMiddlewareValidation.this) {
// State validation.
- if (mDelegate == null) {
+ if (mState == ModuleState.DETACHED) {
throw new IllegalStateException("Module has been detached.");
}
@@ -430,7 +437,7 @@ public class SoundTriggerMiddlewareValidation implements ISoundTriggerMiddleware
synchronized (SoundTriggerMiddlewareValidation.this) {
// State validation.
- if (mDelegate == null) {
+ if (mState == ModuleState.DETACHED) {
throw new IllegalStateException("Module has been detached.");
}
@@ -453,7 +460,7 @@ public class SoundTriggerMiddlewareValidation implements ISoundTriggerMiddleware
synchronized (SoundTriggerMiddlewareValidation.this) {
// State validation.
- if (mDelegate == null) {
+ if (mState == ModuleState.DETACHED) {
throw new IllegalStateException("Module has been detached.");
}
ModelState modelState = mLoadedModels.get(
@@ -486,7 +493,7 @@ public class SoundTriggerMiddlewareValidation implements ISoundTriggerMiddleware
synchronized (SoundTriggerMiddlewareValidation.this) {
// State validation.
- if (mDelegate == null) {
+ if (mState == ModuleState.DETACHED) {
throw new IllegalStateException("Module has been detached.");
}
ModelState modelState = mLoadedModels.get(
@@ -520,7 +527,7 @@ public class SoundTriggerMiddlewareValidation implements ISoundTriggerMiddleware
synchronized (SoundTriggerMiddlewareValidation.this) {
// State validation.
- if (mDelegate == null) {
+ if (mState == ModuleState.DETACHED) {
throw new IllegalStateException("Module has been detached.");
}
ModelState modelState = mLoadedModels.get(
@@ -549,7 +556,7 @@ public class SoundTriggerMiddlewareValidation implements ISoundTriggerMiddleware
synchronized (SoundTriggerMiddlewareValidation.this) {
// State validation.
- if (mDelegate == null) {
+ if (mState == ModuleState.DETACHED) {
throw new IllegalStateException("Module has been detached.");
}
ModelState modelState = mLoadedModels.get(
@@ -577,7 +584,7 @@ public class SoundTriggerMiddlewareValidation implements ISoundTriggerMiddleware
synchronized (SoundTriggerMiddlewareValidation.this) {
// State validation.
- if (mDelegate == null) {
+ if (mState == ModuleState.DETACHED) {
throw new IllegalStateException("Module has been detached.");
}
ModelState modelState = mLoadedModels.get(
@@ -605,7 +612,7 @@ public class SoundTriggerMiddlewareValidation implements ISoundTriggerMiddleware
synchronized (SoundTriggerMiddlewareValidation.this) {
// State validation.
- if (mDelegate == null) {
+ if (mState == ModuleState.DETACHED) {
throw new IllegalStateException("Module has been detached.");
}
ModelState modelState = mLoadedModels.get(
@@ -634,7 +641,7 @@ public class SoundTriggerMiddlewareValidation implements ISoundTriggerMiddleware
synchronized (SoundTriggerMiddlewareValidation.this) {
// State validation.
- if (mDelegate == null) {
+ if (mState == ModuleState.DETACHED) {
throw new IllegalStateException("Module has been detached.");
}
ModelState modelState = mLoadedModels.get(
@@ -663,10 +670,10 @@ public class SoundTriggerMiddlewareValidation implements ISoundTriggerMiddleware
synchronized (SoundTriggerMiddlewareValidation.this) {
// State validation.
- if (mDelegate == null) {
+ if (mState == ModuleState.DETACHED) {
throw new IllegalStateException("Module has already been detached.");
}
- if (!mLoadedModels.isEmpty()) {
+ if (mState == ModuleState.ALIVE && !mLoadedModels.isEmpty()) {
throw new IllegalStateException("Cannot detach while models are loaded.");
}
@@ -682,13 +689,13 @@ public class SoundTriggerMiddlewareValidation implements ISoundTriggerMiddleware
// Override toString() in order to have the delegate's ID in it.
@Override
public String toString() {
- return mDelegate.toString();
+ return Objects.toString(mDelegate.toString());
}
private void detachInternal() {
try {
mDelegate.detach();
- mDelegate = null;
+ mState = ModuleState.DETACHED;
mCallback.asBinder().unlinkToDeath(this, 0);
mModules.get(mHandle).remove(this);
} catch (RemoteException e) {
@@ -697,13 +704,18 @@ public class SoundTriggerMiddlewareValidation implements ISoundTriggerMiddleware
}
void dump(PrintWriter pw) {
- pw.printf("Loaded models for session %s (handle, active)", toString());
- pw.println();
- pw.println("-------------------------------");
- for (Map.Entry<Integer, ModelState> entry : mLoadedModels.entrySet()) {
- pw.print(entry.getKey());
- pw.print('\t');
- pw.print(entry.getValue().activityState.name());
+ if (mState == ModuleState.ALIVE) {
+ pw.printf("Loaded models for session %s (handle, active)", toString());
+ pw.println();
+ pw.println("-------------------------------");
+ for (Map.Entry<Integer, ModelState> entry : mLoadedModels.entrySet()) {
+ pw.print(entry.getKey());
+ pw.print('\t');
+ pw.print(entry.getValue().activityState.name());
+ pw.println();
+ }
+ } else {
+ pw.printf("Session %s is dead", toString());
pw.println();
}
}
@@ -762,6 +774,7 @@ public class SoundTriggerMiddlewareValidation implements ISoundTriggerMiddleware
public void onModuleDied() {
synchronized (SoundTriggerMiddlewareValidation.this) {
try {
+ mState = ModuleState.DEAD;
mCallback.onModuleDied();
} catch (RemoteException e) {
// Dead client will be handled by binderDied() - no need to handle here.
diff --git a/services/core/java/com/android/server/wm/ActivityRecord.java b/services/core/java/com/android/server/wm/ActivityRecord.java
index 2f814f598a05..29f7d523e9a0 100644
--- a/services/core/java/com/android/server/wm/ActivityRecord.java
+++ b/services/core/java/com/android/server/wm/ActivityRecord.java
@@ -5201,7 +5201,7 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
}
finishLaunchTickingLocked();
if (task != null) {
- task.hasBeenVisible = true;
+ task.setHasBeenVisible(true);
}
}
diff --git a/services/core/java/com/android/server/wm/ActivityStack.java b/services/core/java/com/android/server/wm/ActivityStack.java
index 2378813e78b3..90898597c265 100644
--- a/services/core/java/com/android/server/wm/ActivityStack.java
+++ b/services/core/java/com/android/server/wm/ActivityStack.java
@@ -2342,8 +2342,7 @@ class ActivityStack extends Task {
if (!newTask && isOrhasTask) {
// Starting activity cannot be occluding activity, otherwise starting window could be
// remove immediately without transferring to starting activity.
- final ActivityRecord occludingActivity = getActivity(
- (ar) -> ar.occludesParent(), true, r);
+ final ActivityRecord occludingActivity = getOccludingActivityAbove(r);
if (occludingActivity != null) {
// Here it is! Now, if this is not yet visible (occluded by another task) to the
// user, then just add it without starting; it will get started when the user
@@ -3069,6 +3068,14 @@ class ActivityStack extends Task {
task.setOverrideDisplayedBounds(bounds == null || bounds.isEmpty() ? null : bounds);
}
+ /**
+ * Returns the top-most activity that occludes the given one, or @{code null} if none.
+ */
+ @Nullable
+ private ActivityRecord getOccludingActivityAbove(ActivityRecord activity) {
+ return getActivity((ar) -> ar.occludesParent(), true /* traverseTopToBottom */, activity);
+ }
+
boolean willActivityBeVisible(IBinder token) {
final ActivityRecord r = ActivityRecord.forTokenLocked(token);
if (r == null) {
@@ -3076,8 +3083,7 @@ class ActivityStack extends Task {
}
// See if there is an occluding activity on-top of this one.
- final ActivityRecord occludingActivity = getActivity((ar) -> ar.occludesParent(), r,
- false /*includeBoundary*/, true /*traverseTopToBottom*/);
+ final ActivityRecord occludingActivity = getOccludingActivityAbove(r);
if (occludingActivity != null) return false;
if (r.finishing) Slog.e(TAG, "willActivityBeVisible: Returning false,"
diff --git a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
index a5b0026398b6..ce885ab543bc 100644
--- a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
+++ b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
@@ -32,7 +32,6 @@ import static android.app.ActivityManagerInternal.ALLOW_NON_FULL;
import static android.app.ActivityTaskManager.INVALID_TASK_ID;
import static android.app.ActivityTaskManager.RESIZE_MODE_PRESERVE_WINDOW;
import static android.app.WindowConfiguration.ACTIVITY_TYPE_DREAM;
-import static android.app.WindowConfiguration.ACTIVITY_TYPE_UNDEFINED;
import static android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM;
import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
import static android.app.WindowConfiguration.WINDOWING_MODE_PINNED;
@@ -2615,13 +2614,16 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub {
@Override
public List<ActivityManager.RunningTaskInfo> getTasks(int maxNum) {
- return getFilteredTasks(maxNum, ACTIVITY_TYPE_UNDEFINED, WINDOWING_MODE_UNDEFINED);
+ return getFilteredTasks(maxNum, false /* filterForVisibleRecents */);
}
+ /**
+ * @param filterOnlyVisibleRecents whether to filter the tasks based on whether they would ever
+ * be visible in the recent task list in systemui
+ */
@Override
public List<ActivityManager.RunningTaskInfo> getFilteredTasks(int maxNum,
- @WindowConfiguration.ActivityType int ignoreActivityType,
- @WindowConfiguration.WindowingMode int ignoreWindowingMode) {
+ boolean filterOnlyVisibleRecents) {
final int callingUid = Binder.getCallingUid();
final int callingPid = Binder.getCallingPid();
final boolean crossUser = isCrossUserAllowed(callingPid, callingUid);
@@ -2637,8 +2639,8 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub {
if (DEBUG_ALL) Slog.v(TAG, "getTasks: max=" + maxNum);
final boolean allowed = isGetTasksAllowed("getTasks", callingPid, callingUid);
- mRootWindowContainer.getRunningTasks(maxNum, list, ignoreActivityType,
- ignoreWindowingMode, callingUid, allowed, crossUser, callingProfileIds);
+ mRootWindowContainer.getRunningTasks(maxNum, list, filterOnlyVisibleRecents, callingUid,
+ allowed, crossUser, callingProfileIds);
}
return list;
@@ -3984,35 +3986,6 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub {
}
}
- /**
- * Dismisses Pip
- * @param animate True if the dismissal should be animated.
- * @param animationDuration The duration of the resize animation in milliseconds or -1 if the
- * default animation duration should be used.
- */
- @Override
- public void dismissPip(boolean animate, int animationDuration) {
- enforceCallerIsRecentsOrHasPermission(MANAGE_ACTIVITY_STACKS, "dismissPip()");
- final long ident = Binder.clearCallingIdentity();
- try {
- synchronized (mGlobalLock) {
- final ActivityStack stack =
- mRootWindowContainer.getDefaultDisplay().getRootPinnedTask();
- if (stack == null) {
- Slog.w(TAG, "dismissPip: pinned stack not found.");
- return;
- }
- if (stack.getWindowingMode() != WINDOWING_MODE_PINNED) {
- throw new IllegalArgumentException("Stack: " + stack
- + " doesn't support animated resize.");
- }
- stack.dismissPip();
- }
- } finally {
- Binder.restoreCallingIdentity(ident);
- }
- }
-
@Override
public void suppressResizeConfigChanges(boolean suppress) throws RemoteException {
mAmInternal.enforceCallingPermission(MANAGE_ACTIVITY_STACKS, "suppressResizeConfigChanges()");
diff --git a/services/core/java/com/android/server/wm/DisplayContent.java b/services/core/java/com/android/server/wm/DisplayContent.java
index a90016afcc49..9fc90daaccfc 100644
--- a/services/core/java/com/android/server/wm/DisplayContent.java
+++ b/services/core/java/com/android/server/wm/DisplayContent.java
@@ -17,6 +17,7 @@
package com.android.server.wm;
import static android.app.ActivityTaskManager.INVALID_TASK_ID;
+import static android.app.WindowConfiguration.ACTIVITY_TYPE_DREAM;
import static android.app.WindowConfiguration.ACTIVITY_TYPE_HOME;
import static android.app.WindowConfiguration.ACTIVITY_TYPE_RECENTS;
import static android.app.WindowConfiguration.ACTIVITY_TYPE_STANDARD;
@@ -67,7 +68,6 @@ import static android.view.WindowManager.LayoutParams.TYPE_ACCESSIBILITY_MAGNIFI
import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_STARTING;
import static android.view.WindowManager.LayoutParams.TYPE_BASE_APPLICATION;
import static android.view.WindowManager.LayoutParams.TYPE_BOOT_PROGRESS;
-import static android.view.WindowManager.LayoutParams.TYPE_DREAM;
import static android.view.WindowManager.LayoutParams.TYPE_INPUT_METHOD;
import static android.view.WindowManager.LayoutParams.TYPE_INPUT_METHOD_DIALOG;
import static android.view.WindowManager.LayoutParams.TYPE_NAVIGATION_BAR;
@@ -766,11 +766,6 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo
if (mTmpInitial) {
w.resetContentChanged();
}
- if (w.mAttrs.type == TYPE_DREAM) {
- // Don't layout windows behind a dream, so that if it does stuff like hide
- // the status bar we won't get a bad transition when it goes away.
- mTmpWindow = w;
- }
w.mLayoutNeeded = false;
w.prelayout();
final boolean firstLayout = !w.isLaidOut();
@@ -824,10 +819,6 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo
+ " mContainingFrame=" + w.getContainingFrame()
+ " mDisplayFrame=" + w.getDisplayFrameLw());
}
- } else if (w.mAttrs.type == TYPE_DREAM) {
- // Don't layout windows behind a dream, so that if it does stuff like hide the
- // status bar we won't get a bad transition when it goes away.
- mTmpWindow = mTmpWindow2;
}
};
@@ -911,17 +902,6 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo
// Take care of the window being ready to display.
final boolean committed = winAnimator.commitFinishDrawingLocked();
if (isDefaultDisplay && committed) {
- if (w.mAttrs.type == TYPE_DREAM) {
- // HACK: When a dream is shown, it may at that point hide the lock screen.
- // So we need to redo the layout to let the phone window manager make this
- // happen.
- pendingLayoutChanges |= FINISH_LAYOUT_REDO_LAYOUT;
- if (DEBUG_LAYOUT_REPEATS) {
- surfacePlacer.debugLayoutRepeats(
- "dream and commitFinishDrawingLocked true",
- pendingLayoutChanges);
- }
- }
if ((w.mAttrs.flags & FLAG_SHOW_WALLPAPER) != 0) {
if (DEBUG_WALLPAPER_LIGHT) Slog.v(TAG,
"First draw done in potential wallpaper target " + w);
@@ -3021,6 +3001,11 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo
if (recentsStack != null) {
pw.println(prefix + "recentsStack=" + recentsStack.getName());
}
+ final ActivityStack dreamStack =
+ getStack(WINDOWING_MODE_UNDEFINED, ACTIVITY_TYPE_DREAM);
+ if (dreamStack != null) {
+ pw.println(prefix + "dreamStack=" + dreamStack.getName());
+ }
pw.println();
mPinnedStackControllerLocked.dump(prefix, pw);
@@ -3209,7 +3194,7 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo
if (mode == UPDATE_FOCUS_PLACING_SURFACES) {
performLayout(true /*initial*/, updateInputWindows);
} else if (mode == UPDATE_FOCUS_REMOVING_FOCUS) {
- mWmService.mRoot.performSurfacePlacement(false);
+ mWmService.mRoot.performSurfacePlacement();
}
}
@@ -3846,7 +3831,7 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo
}
// TODO: Super crazy long method that should be broken down...
- void applySurfaceChangesTransaction(boolean recoveringMemory) {
+ void applySurfaceChangesTransaction() {
final WindowSurfacePlacer surfacePlacer = mWmService.mWindowPlacerLocked;
mTmpUpdateAllDrawn.clear();
@@ -5628,6 +5613,10 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo
}
void onDisplayChanged() {
+ mDisplay.getRealSize(mTmpDisplaySize);
+ setBounds(0, 0, mTmpDisplaySize.x, mTmpDisplaySize.y);
+ updateDisplayInfo();
+
// The window policy is responsible for stopping activities on the default display.
final int displayId = mDisplay.getDisplayId();
if (displayId != DEFAULT_DISPLAY) {
@@ -5639,10 +5628,6 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo
mOffToken = null;
}
}
-
- mDisplay.getRealSize(mTmpDisplaySize);
- setBounds(0, 0, mTmpDisplaySize.x, mTmpDisplaySize.y);
- updateDisplayInfo();
mWmService.requestTraversal();
}
diff --git a/services/core/java/com/android/server/wm/DisplayPolicy.java b/services/core/java/com/android/server/wm/DisplayPolicy.java
index f593393eecfb..367151cf0f79 100644
--- a/services/core/java/com/android/server/wm/DisplayPolicy.java
+++ b/services/core/java/com/android/server/wm/DisplayPolicy.java
@@ -78,7 +78,6 @@ import static android.view.WindowManager.LayoutParams.SOFT_INPUT_MASK_ADJUST;
import static android.view.WindowManager.LayoutParams.TYPE_BASE_APPLICATION;
import static android.view.WindowManager.LayoutParams.TYPE_BOOT_PROGRESS;
import static android.view.WindowManager.LayoutParams.TYPE_DOCK_DIVIDER;
-import static android.view.WindowManager.LayoutParams.TYPE_DREAM;
import static android.view.WindowManager.LayoutParams.TYPE_INPUT_CONSUMER;
import static android.view.WindowManager.LayoutParams.TYPE_INPUT_METHOD;
import static android.view.WindowManager.LayoutParams.TYPE_KEYGUARD_DIALOG;
@@ -850,7 +849,6 @@ public class DisplayPolicy {
| WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE;
attrs.flags &= ~WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH;
break;
- case TYPE_DREAM:
case TYPE_WALLPAPER:
// Dreams and wallpapers don't have an app window token and can thus not be
// letterboxed. Hence always let them extend under the cutout.
@@ -1225,13 +1223,6 @@ public class DisplayPolicy {
if (DEBUG_ANIM) Slog.i(TAG, "**** STARTING EXIT");
return R.anim.app_starting_exit;
}
- } else if (win.getAttrs().type == TYPE_DREAM && mDreamingLockscreen
- && transit == TRANSIT_ENTER) {
- // Special case: we are animating in a dream, while the keyguard
- // is shown. We don't want an animation on the dream, because
- // we need it shown immediately with the keyguard animating away
- // to reveal it.
- return ANIMATION_NONE;
}
return ANIMATION_STYLEABLE;
@@ -2528,7 +2519,7 @@ public class DisplayPolicy {
if ((fl & FLAG_FORCE_NOT_FULLSCREEN) != 0) {
mForceStatusBar = true;
}
- if (attrs.type == TYPE_DREAM) {
+ if (win.isDreamWindow()) {
// If the lockscreen was showing when the dream started then wait
// for the dream to draw before hiding the lockscreen.
if (!mDreamingLockscreen
diff --git a/services/core/java/com/android/server/wm/InputMonitor.java b/services/core/java/com/android/server/wm/InputMonitor.java
index 18332b9484c0..88cdd1781aee 100644
--- a/services/core/java/com/android/server/wm/InputMonitor.java
+++ b/services/core/java/com/android/server/wm/InputMonitor.java
@@ -62,7 +62,7 @@ final class InputMonitor {
// When true, need to call updateInputWindowsLw().
private boolean mUpdateInputWindowsNeeded = true;
private boolean mUpdateInputWindowsPending;
- private boolean mUpdateInputWindowsImmediately;
+ private boolean mApplyImmediately;
// Currently focused input window handle.
private InputWindowHandle mFocusedInputWindowHandle;
@@ -347,20 +347,14 @@ final class InputMonitor {
}
}
- /**
- * Immediately update the input transaction and merge into the passing Transaction that could be
- * collected and applied later.
- */
- void updateInputWindowsImmediately(SurfaceControl.Transaction t) {
+ void updateInputWindowsImmediately() {
mHandler.removeCallbacks(mUpdateInputWindows);
- mUpdateInputWindowsImmediately = true;
+ mApplyImmediately = true;
mUpdateInputWindows.run();
- mUpdateInputWindowsImmediately = false;
- t.merge(mInputTransaction);
+ mApplyImmediately = false;
}
- /**
- * Called when the current input focus changes.
+ /* Called when the current input focus changes.
* Layer assignment is assumed to be complete by the time this is called.
*/
public void setInputFocusLw(WindowState newWindow, boolean updateInputWindows) {
@@ -471,7 +465,10 @@ final class InputMonitor {
if (mAddWallpaperInputConsumerHandle) {
mWallpaperInputConsumer.show(mInputTransaction, 0);
}
- if (!mUpdateInputWindowsImmediately) {
+
+ if (mApplyImmediately) {
+ mInputTransaction.apply();
+ } else {
mDisplayContent.getPendingTransaction().merge(mInputTransaction);
mDisplayContent.scheduleAnimation();
}
diff --git a/services/core/java/com/android/server/wm/RecentTasks.java b/services/core/java/com/android/server/wm/RecentTasks.java
index 244ba82ce32c..12be9df55fad 100644
--- a/services/core/java/com/android/server/wm/RecentTasks.java
+++ b/services/core/java/com/android/server/wm/RecentTasks.java
@@ -25,6 +25,7 @@ import static android.app.WindowConfiguration.ACTIVITY_TYPE_DREAM;
import static android.app.WindowConfiguration.ACTIVITY_TYPE_HOME;
import static android.app.WindowConfiguration.ACTIVITY_TYPE_RECENTS;
import static android.app.WindowConfiguration.ACTIVITY_TYPE_UNDEFINED;
+import static android.app.WindowConfiguration.WINDOWING_MODE_MULTI_WINDOW;
import static android.app.WindowConfiguration.WINDOWING_MODE_PINNED;
import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_PRIMARY;
import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED;
@@ -1309,6 +1310,7 @@ class RecentTasks {
== FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS) {
return false;
}
+ break;
}
// Ignore certain windowing modes
@@ -1316,23 +1318,21 @@ class RecentTasks {
case WINDOWING_MODE_PINNED:
return false;
case WINDOWING_MODE_SPLIT_SCREEN_PRIMARY:
- if (DEBUG_RECENTS_TRIM_TASKS) Slog.d(TAG, "\ttop=" + task.getStack().getTopMostTask());
+ if (DEBUG_RECENTS_TRIM_TASKS) {
+ Slog.d(TAG, "\ttop=" + task.getStack().getTopMostTask());
+ }
final ActivityStack stack = task.getStack();
if (stack != null && stack.getTopMostTask() == task) {
// Only the non-top task of the primary split screen mode is visible
return false;
}
- }
-
- // 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 ActivityStack stack = task.getStack();
- if (stack != null) {
- DisplayContent display = stack.getDisplay();
- if (display != null && display.isSingleTaskInstance()) {
- return false;
- }
+ break;
+ case WINDOWING_MODE_MULTI_WINDOW:
+ // Ignore tasks that are always on top
+ if (task.isAlwaysOnTop()) {
+ return false;
+ }
+ break;
}
// If we're in lock task mode, ignore the root task
diff --git a/services/core/java/com/android/server/wm/RecentsAnimation.java b/services/core/java/com/android/server/wm/RecentsAnimation.java
index 9089240fe9d1..057592c0c2fc 100644
--- a/services/core/java/com/android/server/wm/RecentsAnimation.java
+++ b/services/core/java/com/android/server/wm/RecentsAnimation.java
@@ -400,6 +400,12 @@ class RecentsAnimation implements RecentsAnimationCallbacks,
throw e;
} finally {
mService.continueWindowLayout();
+ // Make sure the surfaces are updated with the latest state. Sometimes the
+ // surface placement may be skipped if display configuration is changed (i.e.
+ // {@link DisplayContent#mWaitingForConfig} is true).
+ if (mWindowManager.mRoot.isLayoutNeeded()) {
+ mWindowManager.mRoot.performSurfacePlacement();
+ }
Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);
}
});
diff --git a/services/core/java/com/android/server/wm/RootWindowContainer.java b/services/core/java/com/android/server/wm/RootWindowContainer.java
index 6e56bf4dafd7..76c16d40bf2c 100644
--- a/services/core/java/com/android/server/wm/RootWindowContainer.java
+++ b/services/core/java/com/android/server/wm/RootWindowContainer.java
@@ -36,7 +36,6 @@ import static android.view.Display.DEFAULT_DISPLAY;
import static android.view.Display.INVALID_DISPLAY;
import static android.view.WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON;
import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_SUSTAINED_PERFORMANCE_MODE;
-import static android.view.WindowManager.LayoutParams.TYPE_DREAM;
import static android.view.WindowManager.LayoutParams.TYPE_KEYGUARD_DIALOG;
import static android.view.WindowManager.TRANSIT_CRASHING_ACTIVITY_CLOSE;
import static android.view.WindowManager.TRANSIT_SHOW_SINGLE_TASK_DISPLAY;
@@ -796,10 +795,10 @@ class RootWindowContainer extends WindowContainer<DisplayContent>
return leakedSurface || killedApps;
}
- void performSurfacePlacement(boolean recoveringMemory) {
+ void performSurfacePlacement() {
Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "performSurfacePlacement");
try {
- performSurfacePlacementNoTrace(recoveringMemory);
+ performSurfacePlacementNoTrace();
} finally {
Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);
}
@@ -807,7 +806,7 @@ class RootWindowContainer extends WindowContainer<DisplayContent>
// "Something has changed! Let's make it correct now."
// TODO: Super crazy long method that should be broken down...
- void performSurfacePlacementNoTrace(boolean recoveringMemory) {
+ void performSurfacePlacementNoTrace() {
if (DEBUG_WINDOW_TRACE) Slog.v(TAG, "performSurfacePlacementInner: entry. Called by "
+ Debug.getCallers(3));
@@ -842,7 +841,7 @@ class RootWindowContainer extends WindowContainer<DisplayContent>
Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "applySurfaceChanges");
mWmService.openSurfaceTransaction();
try {
- applySurfaceChangesTransaction(recoveringMemory);
+ applySurfaceChangesTransaction();
} catch (RuntimeException e) {
Slog.wtf(TAG, "Unhandled exception in Window Manager", e);
} finally {
@@ -1042,7 +1041,7 @@ class RootWindowContainer extends WindowContainer<DisplayContent>
}
}
- private void applySurfaceChangesTransaction(boolean recoveringMemory) {
+ private void applySurfaceChangesTransaction() {
mHoldScreenWindow = null;
mObscuringWindow = null;
@@ -1065,7 +1064,7 @@ class RootWindowContainer extends WindowContainer<DisplayContent>
final int count = mChildren.size();
for (int j = 0; j < count; ++j) {
final DisplayContent dc = mChildren.get(j);
- dc.applySurfaceChangesTransaction(recoveringMemory);
+ dc.applySurfaceChangesTransaction();
}
// Give the display manager a chance to adjust properties like display rotation if it needs
@@ -1138,7 +1137,7 @@ class RootWindowContainer extends WindowContainer<DisplayContent>
// While a dream or keyguard is showing, obscure ordinary application content on
// secondary displays (by forcibly enabling mirroring unless there is other content
// we want to show) but still allow opaque keyguard dialogs to be shown.
- if (type == TYPE_DREAM || mWmService.mPolicy.isKeyguardShowing()) {
+ if (w.isDreamWindow() || mWmService.mPolicy.isKeyguardShowing()) {
mObscureApplicationContentOnSecondaryDisplays = true;
}
displayHasContent = true;
@@ -2289,6 +2288,9 @@ class RootWindowContainer extends WindowContainer<DisplayContent>
TRANSIT_SHOW_SINGLE_TASK_DISPLAY, false);
}
stack.awakeFromSleepingLocked();
+ if (display.isSingleTaskInstance()) {
+ display.executeAppTransition();
+ }
if (stack.isFocusedStackOnDisplay()
&& !mStackSupervisor.getKeyguardController()
.isKeyguardOrAodShowing(display.mDisplayId)) {
@@ -3393,11 +3395,10 @@ class RootWindowContainer extends WindowContainer<DisplayContent>
@VisibleForTesting
void getRunningTasks(int maxNum, List<ActivityManager.RunningTaskInfo> list,
- @WindowConfiguration.ActivityType int ignoreActivityType,
- @WindowConfiguration.WindowingMode int ignoreWindowingMode, int callingUid,
- boolean allowed, boolean crossUser, ArraySet<Integer> profileIds) {
- mStackSupervisor.getRunningTasks().getTasks(maxNum, list, ignoreActivityType,
- ignoreWindowingMode, this, callingUid, allowed, crossUser, profileIds);
+ boolean filterOnlyVisibleRecents, int callingUid, boolean allowed, boolean crossUser,
+ ArraySet<Integer> profileIds) {
+ mStackSupervisor.getRunningTasks().getTasks(maxNum, list, filterOnlyVisibleRecents, this,
+ callingUid, allowed, crossUser, profileIds);
}
void sendPowerHintForLaunchStartIfNeeded(boolean forceSend, ActivityRecord targetActivity) {
diff --git a/services/core/java/com/android/server/wm/RunningTasks.java b/services/core/java/com/android/server/wm/RunningTasks.java
index 02077fbf453e..3509ba72d058 100644
--- a/services/core/java/com/android/server/wm/RunningTasks.java
+++ b/services/core/java/com/android/server/wm/RunningTasks.java
@@ -16,12 +16,10 @@
package com.android.server.wm;
-import static android.app.WindowConfiguration.ACTIVITY_TYPE_UNDEFINED;
-import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED;
+import static android.app.WindowConfiguration.ACTIVITY_TYPE_HOME;
+import static android.app.WindowConfiguration.ACTIVITY_TYPE_RECENTS;
import android.app.ActivityManager.RunningTaskInfo;
-import android.app.WindowConfiguration.ActivityType;
-import android.app.WindowConfiguration.WindowingMode;
import android.os.UserHandle;
import android.util.ArraySet;
@@ -49,13 +47,13 @@ class RunningTasks {
private boolean mCrossUser;
private ArraySet<Integer> mProfileIds;
private boolean mAllowed;
- private int mIgnoreActivityType;
- private int mIgnoreWindowingMode;
+ private boolean mFilterOnlyVisibleRecents;
private ActivityStack mTopDisplayFocusStack;
+ private RecentTasks mRecentTasks;
- void getTasks(int maxNum, List<RunningTaskInfo> list, @ActivityType int ignoreActivityType,
- @WindowingMode int ignoreWindowingMode, RootWindowContainer root,
- int callingUid, boolean allowed, boolean crossUser, ArraySet<Integer> profileIds) {
+ void getTasks(int maxNum, List<RunningTaskInfo> list, boolean filterOnlyVisibleRecents,
+ RootWindowContainer root, int callingUid, boolean allowed, boolean crossUser,
+ ArraySet<Integer> profileIds) {
// Return early if there are no tasks to fetch
if (maxNum <= 0) {
return;
@@ -68,9 +66,9 @@ class RunningTasks {
mCrossUser = crossUser;
mProfileIds = profileIds;
mAllowed = allowed;
- mIgnoreActivityType = ignoreActivityType;
- mIgnoreWindowingMode = ignoreWindowingMode;
+ mFilterOnlyVisibleRecents = filterOnlyVisibleRecents;
mTopDisplayFocusStack = root.getTopDisplayFocusedStack();
+ mRecentTasks = root.mService.getRecentTasks();
final PooledConsumer c = PooledLambda.obtainConsumer(RunningTasks::processTask, this,
PooledLambda.__(Task.class));
@@ -107,14 +105,12 @@ class RunningTasks {
return;
}
}
- if (mIgnoreActivityType != ACTIVITY_TYPE_UNDEFINED
- && task.getActivityType() == mIgnoreActivityType) {
- // Skip ignored activity type
- return;
- }
- if (mIgnoreWindowingMode != WINDOWING_MODE_UNDEFINED
- && task.getWindowingMode() == mIgnoreWindowingMode) {
- // Skip ignored windowing mode
+ if (mFilterOnlyVisibleRecents
+ && task.getActivityType() != ACTIVITY_TYPE_HOME
+ && task.getActivityType() != ACTIVITY_TYPE_RECENTS
+ && !mRecentTasks.isVisibleRecentTask(task)) {
+ // Skip if this task wouldn't be visibile (ever) from recents, with an exception for the
+ // home & recent tasks
return;
}
diff --git a/services/core/java/com/android/server/wm/Task.java b/services/core/java/com/android/server/wm/Task.java
index 7a41ea57610d..91b4ec95f8fd 100644
--- a/services/core/java/com/android/server/wm/Task.java
+++ b/services/core/java/com/android/server/wm/Task.java
@@ -258,7 +258,7 @@ class Task extends WindowContainer<WindowContainer> {
boolean autoRemoveRecents; // If true, we should automatically remove the task from
// recents when activity finishes
boolean askedCompatMode;// Have asked the user about compat mode for this task.
- boolean hasBeenVisible; // Set if any activities in the task have been visible to the user.
+ private boolean mHasBeenVisible; // Set if any activities in the task have been visible
String stringName; // caching of toString() result.
boolean mUserSetupComplete; // The user set-up is complete as of the last time the task activity
@@ -483,6 +483,10 @@ class Task extends WindowContainer<WindowContainer> {
*/
ITaskOrganizer mTaskOrganizer;
private int mLastTaskOrganizerWindowingMode = -1;
+ /**
+ * Prevent duplicate calls to onTaskAppeared.
+ */
+ boolean mTaskAppearedSent;
/**
* Last Picture-in-Picture params applicable to the task. Updated when the app
@@ -1517,7 +1521,7 @@ class Task extends WindowContainer<WindowContainer> {
// We will automatically remove the task either if it has explicitly asked for
// this, or it is empty and has never contained an activity that got shown to
// the user.
- return autoRemoveRecents || (!hasChild() && !hasBeenVisible);
+ return autoRemoveRecents || (!hasChild() && !getHasBeenVisible());
}
/**
@@ -2030,7 +2034,7 @@ class Task extends WindowContainer<WindowContainer> {
}
private void saveLaunchingStateIfNeeded(DisplayContent display) {
- if (!hasBeenVisible) {
+ if (!getHasBeenVisible()) {
// Not ever visible to user.
return;
}
@@ -3558,7 +3562,7 @@ class Task extends WindowContainer<WindowContainer> {
pw.print(prefix); pw.print("mRootProcess="); pw.println(mRootProcess);
}
pw.print(prefix); pw.print("taskId=" + mTaskId); pw.println(" stackId=" + getRootTaskId());
- pw.print(prefix + "hasBeenVisible=" + hasBeenVisible);
+ pw.print(prefix + "mHasBeenVisible=" + getHasBeenVisible());
pw.print(" mResizeMode=" + ActivityInfo.resizeModeToString(mResizeMode));
pw.print(" mSupportsPictureInPicture=" + mSupportsPictureInPicture);
pw.print(" isResizeable=" + isResizeable());
@@ -4087,14 +4091,42 @@ class Task extends WindowContainer<WindowContainer> {
super.reparentSurfaceControl(t, newParent);
}
+ void setHasBeenVisible(boolean hasBeenVisible) {
+ mHasBeenVisible = hasBeenVisible;
+ if (hasBeenVisible) {
+ sendTaskAppeared();
+ if (!isRootTask()) {
+ getRootTask().setHasBeenVisible(true);
+ }
+ }
+ }
+
+ boolean getHasBeenVisible() {
+ return mHasBeenVisible;
+ }
+
+ /** In the case that these three conditions are true, we want to send the Task to
+ * the organizer:
+ * 1. We have a SurfaceControl
+ * 2. An organizer has been set
+ * 3. We have finished drawing
+ * Any time any of these conditions are updated, the updating code should call
+ * sendTaskAppeared.
+ */
+ private boolean taskAppearedReady() {
+ return mSurfaceControl != null && mTaskOrganizer != null && getHasBeenVisible();
+ }
+
private void sendTaskAppeared() {
- if (mSurfaceControl != null && mTaskOrganizer != null) {
+ if (taskAppearedReady() && !mTaskAppearedSent) {
+ mTaskAppearedSent = true;
mAtmService.mTaskOrganizerController.onTaskAppeared(mTaskOrganizer, this);
}
}
private void sendTaskVanished() {
- if (mTaskOrganizer != null) {
+ if (mTaskOrganizer != null && mTaskAppearedSent) {
+ mTaskAppearedSent = false;
mAtmService.mTaskOrganizerController.onTaskVanished(mTaskOrganizer, this);
}
}
@@ -4113,6 +4145,7 @@ class Task extends WindowContainer<WindowContainer> {
void taskOrganizerUnregistered() {
mTaskOrganizer = null;
+ mTaskAppearedSent = false;
mLastTaskOrganizerWindowingMode = -1;
onTaskOrganizerChanged();
if (mCreatedByOrganizer) {
diff --git a/services/core/java/com/android/server/wm/TaskOrganizerController.java b/services/core/java/com/android/server/wm/TaskOrganizerController.java
index 4382e9d578ad..8a896f52eea7 100644
--- a/services/core/java/com/android/server/wm/TaskOrganizerController.java
+++ b/services/core/java/com/android/server/wm/TaskOrganizerController.java
@@ -20,14 +20,13 @@ import static android.Manifest.permission.MANAGE_ACTIVITY_STACKS;
import static android.app.WindowConfiguration.ACTIVITY_TYPE_UNDEFINED;
import static android.app.WindowConfiguration.WINDOWING_MODE_MULTI_WINDOW;
import static android.app.WindowConfiguration.WINDOWING_MODE_PINNED;
-import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_PRIMARY;
-import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_SECONDARY;
import static com.android.server.wm.WindowOrganizerController.CONTROLLABLE_CONFIGS;
import static com.android.server.wm.WindowOrganizerController.CONTROLLABLE_WINDOW_CONFIGS;
import android.annotation.Nullable;
import android.app.ActivityManager.RunningTaskInfo;
+import android.app.WindowConfiguration;
import android.content.Intent;
import android.content.pm.ActivityInfo;
import android.os.Binder;
@@ -53,7 +52,7 @@ import java.util.WeakHashMap;
*/
class TaskOrganizerController extends ITaskOrganizerController.Stub {
private static final String TAG = "TaskOrganizerController";
- private static final LinkedList<TaskOrganizerState> EMPTY_LIST = new LinkedList<>();
+ private static final LinkedList<IBinder> EMPTY_LIST = new LinkedList<>();
/**
* Masks specifying which configurations are important to report back to an organizer when
@@ -65,12 +64,10 @@ class TaskOrganizerController extends ITaskOrganizerController.Stub {
private final WindowManagerGlobalLock mGlobalLock;
private class DeathRecipient implements IBinder.DeathRecipient {
- int mWindowingMode;
ITaskOrganizer mTaskOrganizer;
- DeathRecipient(ITaskOrganizer organizer, int windowingMode) {
+ DeathRecipient(ITaskOrganizer organizer) {
mTaskOrganizer = organizer;
- mWindowingMode = windowingMode;
}
@Override
@@ -86,18 +83,16 @@ class TaskOrganizerController extends ITaskOrganizerController.Stub {
private class TaskOrganizerState {
private final ITaskOrganizer mOrganizer;
private final DeathRecipient mDeathRecipient;
- private final int mWindowingMode;
private final ArrayList<Task> mOrganizedTasks = new ArrayList<>();
- TaskOrganizerState(ITaskOrganizer organizer, int windowingMode) {
+ TaskOrganizerState(ITaskOrganizer organizer) {
mOrganizer = organizer;
- mDeathRecipient = new DeathRecipient(organizer, windowingMode);
+ mDeathRecipient = new DeathRecipient(organizer);
try {
organizer.asBinder().linkToDeath(mDeathRecipient, 0);
} catch (RemoteException e) {
Slog.e(TAG, "TaskOrganizer failed to register death recipient");
}
- mWindowingMode = windowingMode;
}
void addTask(Task t) {
@@ -120,7 +115,9 @@ class TaskOrganizerController extends ITaskOrganizerController.Stub {
void dispose() {
releaseTasks();
- mTaskOrganizersForWindowingMode.get(mWindowingMode).remove(this);
+ for (int i = mTaskOrganizersForWindowingMode.size() - 1; i >= 0; --i) {
+ mTaskOrganizersForWindowingMode.valueAt(i).remove(mOrganizer.asBinder());
+ }
}
private void releaseTasks() {
@@ -136,7 +133,7 @@ class TaskOrganizerController extends ITaskOrganizerController.Stub {
}
}
- private final SparseArray<LinkedList<TaskOrganizerState>> mTaskOrganizersForWindowingMode =
+ private final SparseArray<LinkedList<IBinder>> mTaskOrganizersForWindowingMode =
new SparseArray<>();
private final HashMap<IBinder, TaskOrganizerState> mTaskOrganizerStates = new HashMap<>();
private final WeakHashMap<Task, RunningTaskInfo> mLastSentTaskInfos = new WeakHashMap<>();
@@ -162,10 +159,22 @@ class TaskOrganizerController extends ITaskOrganizerController.Stub {
*/
@Override
public void registerTaskOrganizer(ITaskOrganizer organizer, int windowingMode) {
- if (windowingMode != WINDOWING_MODE_PINNED
- && windowingMode != WINDOWING_MODE_SPLIT_SCREEN_PRIMARY
- && windowingMode != WINDOWING_MODE_SPLIT_SCREEN_SECONDARY
- && windowingMode != WINDOWING_MODE_MULTI_WINDOW) {
+ if (windowingMode == WINDOWING_MODE_PINNED) {
+ if (!mService.mSupportsPictureInPicture) {
+ throw new UnsupportedOperationException("Picture in picture is not supported on "
+ + "this device");
+ }
+ } else if (WindowConfiguration.isSplitScreenWindowingMode(windowingMode)) {
+ if (!mService.mSupportsSplitScreenMultiWindow) {
+ throw new UnsupportedOperationException("Split-screen is not supported on this "
+ + "device");
+ }
+ } else if (windowingMode == WINDOWING_MODE_MULTI_WINDOW) {
+ if (!mService.mSupportsMultiWindow) {
+ throw new UnsupportedOperationException("Multi-window is not supported on this "
+ + "device");
+ }
+ } else {
throw new UnsupportedOperationException("As of now only Pinned/Split/Multiwindow"
+ " windowing modes are supported for registerTaskOrganizer");
}
@@ -178,19 +187,18 @@ class TaskOrganizerController extends ITaskOrganizerController.Stub {
+ windowingMode);
}
- LinkedList<TaskOrganizerState> states;
- if (mTaskOrganizersForWindowingMode.contains(windowingMode)) {
- states = mTaskOrganizersForWindowingMode.get(windowingMode);
- } else {
- states = new LinkedList<>();
- mTaskOrganizersForWindowingMode.put(windowingMode, states);
+ LinkedList<IBinder> orgs = mTaskOrganizersForWindowingMode.get(windowingMode);
+ if (orgs == null) {
+ orgs = new LinkedList<>();
+ mTaskOrganizersForWindowingMode.put(windowingMode, orgs);
+ }
+ orgs.add(organizer.asBinder());
+ if (!mTaskOrganizerStates.containsKey(organizer.asBinder())) {
+ mTaskOrganizerStates.put(organizer.asBinder(),
+ new TaskOrganizerState(organizer));
}
- final TaskOrganizerState previousState = states.peekLast();
- final TaskOrganizerState state = new TaskOrganizerState(organizer, windowingMode);
- states.add(state);
- mTaskOrganizerStates.put(organizer.asBinder(), state);
- if (previousState == null) {
+ if (orgs.size() == 1) {
// Only in the case where this is the root task organizer for the given
// windowing mode, we add report all existing tasks in that mode to the new
// task organizer.
@@ -214,8 +222,12 @@ class TaskOrganizerController extends ITaskOrganizerController.Stub {
}
ITaskOrganizer getTaskOrganizer(int windowingMode) {
- final TaskOrganizerState state = mTaskOrganizersForWindowingMode.get(windowingMode,
- EMPTY_LIST).peekLast();
+ final IBinder organizer =
+ mTaskOrganizersForWindowingMode.get(windowingMode, EMPTY_LIST).peekLast();
+ if (organizer == null) {
+ return null;
+ }
+ final TaskOrganizerState state = mTaskOrganizerStates.get(organizer);
if (state == null) {
return null;
}
diff --git a/services/core/java/com/android/server/wm/TaskPositioner.java b/services/core/java/com/android/server/wm/TaskPositioner.java
index be0d6f8a0b9f..f046e8adc478 100644
--- a/services/core/java/com/android/server/wm/TaskPositioner.java
+++ b/services/core/java/com/android/server/wm/TaskPositioner.java
@@ -268,9 +268,8 @@ class TaskPositioner implements IBinder.DeathRecipient {
mDisplayContent.getDisplayRotation().pause();
// Notify InputMonitor to take mDragWindowHandle.
- final SurfaceControl.Transaction t = mService.mTransactionFactory.get();
- mDisplayContent.getInputMonitor().updateInputWindowsImmediately(t);
- t.syncInputWindows().apply();
+ mDisplayContent.getInputMonitor().updateInputWindowsImmediately();
+ new SurfaceControl.Transaction().syncInputWindows().apply(true);
final DisplayMetrics displayMetrics = displayContent.getDisplayMetrics();
mMinVisibleWidth = dipToPixel(MINIMUM_VISIBLE_WIDTH_IN_DP, displayMetrics);
diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java
index 075772566d56..b1f22f8623d6 100644
--- a/services/core/java/com/android/server/wm/WindowManagerService.java
+++ b/services/core/java/com/android/server/wm/WindowManagerService.java
@@ -58,7 +58,6 @@ import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_IS_ROUNDED_CO
import static android.view.WindowManager.LayoutParams.SYSTEM_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS;
import static android.view.WindowManager.LayoutParams.TYPE_ACCESSIBILITY_OVERLAY;
import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_STARTING;
-import static android.view.WindowManager.LayoutParams.TYPE_DREAM;
import static android.view.WindowManager.LayoutParams.TYPE_INPUT_METHOD;
import static android.view.WindowManager.LayoutParams.TYPE_INPUT_METHOD_DIALOG;
import static android.view.WindowManager.LayoutParams.TYPE_NAVIGATION_BAR;
@@ -1482,12 +1481,6 @@ public class WindowManagerService extends IWindowManager.Stub
+ "%s. Aborting.", attrs.token);
return WindowManagerGlobal.ADD_BAD_APP_TOKEN;
}
- } else if (rootType == TYPE_DREAM) {
- if (token.windowType != TYPE_DREAM) {
- ProtoLog.w(WM_ERROR, "Attempted to add Dream window with bad token "
- + "%s. Aborting.", attrs.token);
- return WindowManagerGlobal.ADD_BAD_APP_TOKEN;
- }
} else if (rootType == TYPE_ACCESSIBILITY_OVERLAY) {
if (token.windowType != TYPE_ACCESSIBILITY_OVERLAY) {
ProtoLog.w(WM_ERROR,
@@ -1723,11 +1716,6 @@ public class WindowManagerService extends IWindowManager.Stub
+ "%s. Aborting.", tokenForLog);
return false;
}
- if (rootType == TYPE_DREAM) {
- ProtoLog.w(WM_ERROR, "Attempted to add Dream window with unknown token "
- + "%s. Aborting.", tokenForLog);
- return false;
- }
if (rootType == TYPE_QS_DIALOG) {
ProtoLog.w(WM_ERROR, "Attempted to add QS dialog window with unknown token "
+ "%s. Aborting.", tokenForLog);
@@ -7746,23 +7734,19 @@ public class WindowManagerService extends IWindowManager.Stub
public void syncInputTransactions() {
waitForAnimationsToComplete();
- // Collect all input transactions from all displays to make sure we could sync all input
- // windows at same time.
- final SurfaceControl.Transaction t = mTransactionFactory.get();
synchronized (mGlobalLock) {
mWindowPlacerLocked.performSurfacePlacementIfScheduled();
mRoot.forAllDisplays(displayContent ->
- displayContent.getInputMonitor().updateInputWindowsImmediately(t));
+ displayContent.getInputMonitor().updateInputWindowsImmediately());
}
- t.syncInputWindows().apply();
+ mTransactionFactory.get().syncInputWindows().apply(true);
}
private void waitForAnimationsToComplete() {
synchronized (mGlobalLock) {
long timeoutRemaining = ANIMATION_COMPLETED_TIMEOUT_MS;
- while ((mAnimator.isAnimationScheduled()
- || mRoot.isAnimating(TRANSITION | CHILDREN)) && timeoutRemaining > 0) {
+ while (mRoot.isAnimating(TRANSITION | CHILDREN) && timeoutRemaining > 0) {
long startTime = System.currentTimeMillis();
try {
mGlobalLock.wait(timeoutRemaining);
diff --git a/services/core/java/com/android/server/wm/WindowState.java b/services/core/java/com/android/server/wm/WindowState.java
index c4d700c9aca3..b4487409c74e 100644
--- a/services/core/java/com/android/server/wm/WindowState.java
+++ b/services/core/java/com/android/server/wm/WindowState.java
@@ -20,6 +20,7 @@ import static android.app.ActivityTaskManager.INVALID_TASK_ID;
import static android.app.AppOpsManager.MODE_ALLOWED;
import static android.app.AppOpsManager.MODE_DEFAULT;
import static android.app.AppOpsManager.OP_NONE;
+import static android.app.WindowConfiguration.ACTIVITY_TYPE_DREAM;
import static android.app.WindowConfiguration.isSplitScreenWindowingMode;
import static android.content.res.Configuration.ORIENTATION_LANDSCAPE;
import static android.os.PowerManager.DRAW_WAKE_LOCK;
@@ -1694,6 +1695,11 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP
return !isParentWindowHidden() || isAnimating(TRANSITION | PARENTS);
}
+ boolean isDreamWindow() {
+ return mActivityRecord != null
+ && mActivityRecord.getActivityType() == ACTIVITY_TYPE_DREAM;
+ }
+
/**
* Whether this window's drawn state might affect the drawn states of the app token.
*
diff --git a/services/core/java/com/android/server/wm/WindowSurfacePlacer.java b/services/core/java/com/android/server/wm/WindowSurfacePlacer.java
index 0cfdebc6792d..6b9fbcbf459f 100644
--- a/services/core/java/com/android/server/wm/WindowSurfacePlacer.java
+++ b/services/core/java/com/android/server/wm/WindowSurfacePlacer.java
@@ -157,9 +157,7 @@ class WindowSurfacePlacer {
mInLayout = true;
- boolean recoveringMemory = false;
if (!mService.mForceRemoves.isEmpty()) {
- recoveringMemory = true;
// Wait a little bit for things to settle down, and off we go.
while (!mService.mForceRemoves.isEmpty()) {
final WindowState ws = mService.mForceRemoves.remove(0);
@@ -177,7 +175,7 @@ class WindowSurfacePlacer {
}
try {
- mService.mRoot.performSurfacePlacement(recoveringMemory);
+ mService.mRoot.performSurfacePlacement();
mInLayout = false;
diff --git a/services/core/jni/com_android_server_input_InputManagerService.cpp b/services/core/jni/com_android_server_input_InputManagerService.cpp
index 9bc5d34c11af..e3f9ae8969b3 100644
--- a/services/core/jni/com_android_server_input_InputManagerService.cpp
+++ b/services/core/jni/com_android_server_input_InputManagerService.cpp
@@ -206,7 +206,7 @@ public:
status_t unregisterInputChannel(JNIEnv* env, const sp<InputChannel>& inputChannel);
status_t pilferPointers(const sp<IBinder>& token);
- void displayRemoved(JNIEnv* env, int32_t displayId);
+ void setInputWindows(JNIEnv* env, jobjectArray windowHandleObjArray, int32_t displayId);
void setFocusedApplication(JNIEnv* env, int32_t displayId, jobject applicationHandleObj);
void setFocusedDisplay(JNIEnv* env, int32_t displayId);
void setInputDispatchMode(bool enabled, bool frozen);
@@ -771,10 +771,55 @@ void NativeInputManager::getDispatcherConfiguration(InputDispatcherConfiguration
}
}
-void NativeInputManager::displayRemoved(JNIEnv* env, int32_t displayId) {
- // Set an empty list to remove all handles from the specific display.
- std::vector<sp<InputWindowHandle>> windowHandles;
- mInputManager->getDispatcher()->setInputWindows({{displayId, windowHandles}});
+void NativeInputManager::setInputWindows(JNIEnv* env, jobjectArray windowHandleObjArray,
+ int32_t displayId) {
+ std::vector<sp<InputWindowHandle> > windowHandles;
+
+ if (windowHandleObjArray) {
+ jsize length = env->GetArrayLength(windowHandleObjArray);
+ for (jsize i = 0; i < length; i++) {
+ jobject windowHandleObj = env->GetObjectArrayElement(windowHandleObjArray, i);
+ if (! windowHandleObj) {
+ break; // found null element indicating end of used portion of the array
+ }
+
+ sp<InputWindowHandle> windowHandle =
+ android_view_InputWindowHandle_getHandle(env, windowHandleObj);
+ if (windowHandle != nullptr) {
+ windowHandles.push_back(windowHandle);
+ }
+ env->DeleteLocalRef(windowHandleObj);
+ }
+ }
+
+ mInputManager->getDispatcher()->setInputWindows(windowHandles, displayId);
+
+ // Do this after the dispatcher has updated the window handle state.
+ bool newPointerGesturesEnabled = true;
+ size_t numWindows = windowHandles.size();
+ for (size_t i = 0; i < numWindows; i++) {
+ const sp<InputWindowHandle>& windowHandle = windowHandles[i];
+ const InputWindowInfo* windowInfo = windowHandle->getInfo();
+ if (windowInfo && windowInfo->hasFocus && (windowInfo->inputFeatures
+ & InputWindowInfo::INPUT_FEATURE_DISABLE_TOUCH_PAD_GESTURES)) {
+ newPointerGesturesEnabled = false;
+ }
+ }
+
+ bool pointerGesturesEnabledChanged = false;
+ { // acquire lock
+ AutoMutex _l(mLock);
+
+ if (mLocked.pointerGesturesEnabled != newPointerGesturesEnabled) {
+ mLocked.pointerGesturesEnabled = newPointerGesturesEnabled;
+ pointerGesturesEnabledChanged = true;
+ }
+ } // release lock
+
+ if (pointerGesturesEnabledChanged) {
+ mInputManager->getReader()->requestRefreshConfiguration(
+ InputReaderConfiguration::CHANGE_POINTER_GESTURE_ENABLEMENT);
+ }
}
void NativeInputManager::setFocusedApplication(JNIEnv* env, int32_t displayId,
@@ -1522,10 +1567,11 @@ static void nativeToggleCapsLock(JNIEnv* env, jclass /* clazz */,
im->getInputManager()->getReader()->toggleCapsLockState(deviceId);
}
-static void nativeDisplayRemoved(JNIEnv* env, jclass /* clazz */, jlong ptr, jint displayId) {
+static void nativeSetInputWindows(JNIEnv* env, jclass /* clazz */,
+ jlong ptr, jobjectArray windowHandleObjArray, jint displayId) {
NativeInputManager* im = reinterpret_cast<NativeInputManager*>(ptr);
- im->displayRemoved(env, displayId);
+ im->setInputWindows(env, windowHandleObjArray, displayId);
}
static void nativeSetFocusedApplication(JNIEnv* env, jclass /* clazz */,
@@ -1769,7 +1815,8 @@ static const JNINativeMethod gInputManagerMethods[] = {
{"nativeVerifyInputEvent", "(JLandroid/view/InputEvent;)Landroid/view/VerifiedInputEvent;",
(void*)nativeVerifyInputEvent},
{"nativeToggleCapsLock", "(JI)V", (void*)nativeToggleCapsLock},
- {"nativeDisplayRemoved", "(JI)V", (void*)nativeDisplayRemoved},
+ {"nativeSetInputWindows", "(J[Landroid/view/InputWindowHandle;I)V",
+ (void*)nativeSetInputWindows},
{"nativeSetFocusedApplication", "(JILandroid/view/InputApplicationHandle;)V",
(void*)nativeSetFocusedApplication},
{"nativeSetFocusedDisplay", "(JI)V", (void*)nativeSetFocusedDisplay},
diff --git a/services/core/jni/com_android_server_location_GnssLocationProvider.cpp b/services/core/jni/com_android_server_location_GnssLocationProvider.cpp
index 822f3835cc07..e4061b4fc34c 100644
--- a/services/core/jni/com_android_server_location_GnssLocationProvider.cpp
+++ b/services/core/jni/com_android_server_location_GnssLocationProvider.cpp
@@ -2068,8 +2068,8 @@ static void android_location_GnssLocationProvider_class_init_native(JNIEnv* env,
class_gnssClock = (jclass) env->NewGlobalRef(gnssClockClass);
method_gnssClockCtor = env->GetMethodID(class_gnssClock, "<init>", "()V");
- jclass gnssConfiguration_halInterfaceVersionClass =
- env->FindClass("com/android/server/location/GnssConfiguration$HalInterfaceVersion");
+ jclass gnssConfiguration_halInterfaceVersionClass = env->FindClass(
+ "com/android/server/location/gnss/GnssConfiguration$HalInterfaceVersion");
class_gnssConfiguration_halInterfaceVersion =
(jclass) env->NewGlobalRef(gnssConfiguration_halInterfaceVersionClass);
method_halInterfaceVersionCtor =
@@ -3738,39 +3738,29 @@ static const JNINativeMethod sNetworkConnectivityMethods[] = {
};
static const JNINativeMethod sConfigurationMethods[] = {
- /* name, signature, funcPtr */
- {"native_get_gnss_configuration_version",
- "()Lcom/android/server/location/GnssConfiguration$HalInterfaceVersion;",
- reinterpret_cast<void *>(
- android_location_GnssConfiguration_get_gnss_configuration_version)},
- {"native_set_supl_es",
- "(I)Z",
- reinterpret_cast<void *>(android_location_GnssConfiguration_set_supl_es)},
- {"native_set_supl_version",
- "(I)Z",
- reinterpret_cast<void *>(android_location_GnssConfiguration_set_supl_version)},
- {"native_set_supl_mode",
- "(I)Z",
- reinterpret_cast<void *>(android_location_GnssConfiguration_set_supl_mode)},
- {"native_set_lpp_profile",
- "(I)Z",
- reinterpret_cast<void *>(android_location_GnssConfiguration_set_lpp_profile)},
- {"native_set_gnss_pos_protocol_select",
- "(I)Z",
- reinterpret_cast<void *>(
- android_location_GnssConfiguration_set_gnss_pos_protocol_select)},
- {"native_set_gps_lock",
- "(I)Z",
- reinterpret_cast<void *>(android_location_GnssConfiguration_set_gps_lock)},
- {"native_set_emergency_supl_pdn",
- "(I)Z",
- reinterpret_cast<void *>(android_location_GnssConfiguration_set_emergency_supl_pdn)},
- {"native_set_satellite_blacklist",
- "([I[I)Z",
- reinterpret_cast<void *>(android_location_GnssConfiguration_set_satellite_blacklist)},
- {"native_set_es_extension_sec",
- "(I)Z",
- reinterpret_cast<void *>(android_location_GnssConfiguration_set_es_extension_sec)},
+ /* name, signature, funcPtr */
+ {"native_get_gnss_configuration_version",
+ "()Lcom/android/server/location/gnss/GnssConfiguration$HalInterfaceVersion;",
+ reinterpret_cast<void*>(
+ android_location_GnssConfiguration_get_gnss_configuration_version)},
+ {"native_set_supl_es", "(I)Z",
+ reinterpret_cast<void*>(android_location_GnssConfiguration_set_supl_es)},
+ {"native_set_supl_version", "(I)Z",
+ reinterpret_cast<void*>(android_location_GnssConfiguration_set_supl_version)},
+ {"native_set_supl_mode", "(I)Z",
+ reinterpret_cast<void*>(android_location_GnssConfiguration_set_supl_mode)},
+ {"native_set_lpp_profile", "(I)Z",
+ reinterpret_cast<void*>(android_location_GnssConfiguration_set_lpp_profile)},
+ {"native_set_gnss_pos_protocol_select", "(I)Z",
+ reinterpret_cast<void*>(android_location_GnssConfiguration_set_gnss_pos_protocol_select)},
+ {"native_set_gps_lock", "(I)Z",
+ reinterpret_cast<void*>(android_location_GnssConfiguration_set_gps_lock)},
+ {"native_set_emergency_supl_pdn", "(I)Z",
+ reinterpret_cast<void*>(android_location_GnssConfiguration_set_emergency_supl_pdn)},
+ {"native_set_satellite_blacklist", "([I[I)Z",
+ reinterpret_cast<void*>(android_location_GnssConfiguration_set_satellite_blacklist)},
+ {"native_set_es_extension_sec", "(I)Z",
+ reinterpret_cast<void*>(android_location_GnssConfiguration_set_es_extension_sec)},
};
static const JNINativeMethod sVisibilityControlMethods[] = {
@@ -3782,53 +3772,27 @@ static const JNINativeMethod sVisibilityControlMethods[] = {
};
int register_android_server_location_GnssLocationProvider(JNIEnv* env) {
- jniRegisterNativeMethods(env, "com/android/server/location/GnssAntennaInfoProvider",
+ jniRegisterNativeMethods(env, "com/android/server/location/gnss/GnssAntennaInfoProvider",
sAntennaInfoMethods, NELEM(sAntennaInfoMethods));
- jniRegisterNativeMethods(
- env,
- "com/android/server/location/GnssBatchingProvider",
- sMethodsBatching,
- NELEM(sMethodsBatching));
- jniRegisterNativeMethods(
- env,
- "com/android/server/location/GnssGeofenceProvider",
- sGeofenceMethods,
- NELEM(sGeofenceMethods));
- jniRegisterNativeMethods(
- env,
- "com/android/server/location/GnssMeasurementsProvider",
- sMeasurementMethods,
- NELEM(sMeasurementMethods));
- jniRegisterNativeMethods(
- env,
- "com/android/server/location/GnssMeasurementCorrectionsProvider",
- sMeasurementCorrectionsMethods,
- NELEM(sMeasurementCorrectionsMethods));
- jniRegisterNativeMethods(
- env,
- "com/android/server/location/GnssNavigationMessageProvider",
- sNavigationMessageMethods,
- NELEM(sNavigationMessageMethods));
- jniRegisterNativeMethods(
- env,
- "com/android/server/location/GnssNetworkConnectivityHandler",
- sNetworkConnectivityMethods,
- NELEM(sNetworkConnectivityMethods));
- jniRegisterNativeMethods(
- env,
- "com/android/server/location/GnssConfiguration",
- sConfigurationMethods,
- NELEM(sConfigurationMethods));
- jniRegisterNativeMethods(
- env,
- "com/android/server/location/GnssVisibilityControl",
- sVisibilityControlMethods,
- NELEM(sVisibilityControlMethods));
- return jniRegisterNativeMethods(
- env,
- "com/android/server/location/GnssLocationProvider",
- sMethods,
- NELEM(sMethods));
+ jniRegisterNativeMethods(env, "com/android/server/location/gnss/GnssBatchingProvider",
+ sMethodsBatching, NELEM(sMethodsBatching));
+ jniRegisterNativeMethods(env, "com/android/server/location/gnss/GnssGeofenceProvider",
+ sGeofenceMethods, NELEM(sGeofenceMethods));
+ jniRegisterNativeMethods(env, "com/android/server/location/gnss/GnssMeasurementsProvider",
+ sMeasurementMethods, NELEM(sMeasurementMethods));
+ jniRegisterNativeMethods(env,
+ "com/android/server/location/gnss/GnssMeasurementCorrectionsProvider",
+ sMeasurementCorrectionsMethods, NELEM(sMeasurementCorrectionsMethods));
+ jniRegisterNativeMethods(env, "com/android/server/location/gnss/GnssNavigationMessageProvider",
+ sNavigationMessageMethods, NELEM(sNavigationMessageMethods));
+ jniRegisterNativeMethods(env, "com/android/server/location/gnss/GnssNetworkConnectivityHandler",
+ sNetworkConnectivityMethods, NELEM(sNetworkConnectivityMethods));
+ jniRegisterNativeMethods(env, "com/android/server/location/gnss/GnssConfiguration",
+ sConfigurationMethods, NELEM(sConfigurationMethods));
+ jniRegisterNativeMethods(env, "com/android/server/location/gnss/GnssVisibilityControl",
+ sVisibilityControlMethods, NELEM(sVisibilityControlMethods));
+ return jniRegisterNativeMethods(env, "com/android/server/location/gnss/GnssLocationProvider",
+ sMethods, NELEM(sMethods));
}
} /* namespace android */
diff --git a/services/core/jni/com_android_server_pm_PackageManagerShellCommandDataLoader.cpp b/services/core/jni/com_android_server_pm_PackageManagerShellCommandDataLoader.cpp
index 725036c9df0f..e9a5e58e49d1 100644
--- a/services/core/jni/com_android_server_pm_PackageManagerShellCommandDataLoader.cpp
+++ b/services/core/jni/com_android_server_pm_PackageManagerShellCommandDataLoader.cpp
@@ -227,56 +227,40 @@ static inline unique_fd convertPfdToFdAndDup(JNIEnv* env, const JniIds& jni, job
return result;
}
+enum MetadataMode : int8_t {
+ STDIN = 0,
+ LOCAL_FILE = 1,
+ DATA_ONLY_STREAMING = 2,
+ STREAMING = 3,
+};
+
struct InputDesc {
unique_fd fd;
IncFsSize size;
IncFsBlockKind kind = INCFS_BLOCK_KIND_DATA;
bool waitOnEof = false;
bool streaming = false;
+ MetadataMode mode = STDIN;
};
using InputDescs = std::vector<InputDesc>;
-static inline InputDescs openInputs(JNIEnv* env, const JniIds& jni, jobject shellCommand,
- IncFsSize size, IncFsSpan metadata) {
+template <class T>
+std::optional<T> read(IncFsSpan& data) {
+ if (data.size < (int32_t)sizeof(T)) {
+ return {};
+ }
+ T res;
+ memcpy(&res, data.data, sizeof(res));
+ data.data += sizeof(res);
+ data.size -= sizeof(res);
+ return res;
+}
+
+static inline InputDescs openLocalFile(JNIEnv* env, const JniIds& jni, jobject shellCommand,
+ IncFsSize size, const std::string& filePath) {
InputDescs result;
result.reserve(2);
- if (metadata.size == 0 || *metadata.data == '-') {
- // stdin
- auto fd = convertPfdToFdAndDup(
- env, jni,
- env->CallStaticObjectMethod(jni.packageManagerShellCommandDataLoader,
- jni.pmscdGetStdInPFD, shellCommand));
- if (fd.ok()) {
- result.push_back(InputDesc{
- .fd = std::move(fd),
- .size = size,
- .waitOnEof = true,
- });
- }
- return result;
- }
- if (*metadata.data == '+') {
- // verity tree from stdin, rest is streaming
- auto fd = convertPfdToFdAndDup(
- env, jni,
- env->CallStaticObjectMethod(jni.packageManagerShellCommandDataLoader,
- jni.pmscdGetStdInPFD, shellCommand));
- if (fd.ok()) {
- auto treeSize = verityTreeSizeForFile(size);
- result.push_back(InputDesc{
- .fd = std::move(fd),
- .size = treeSize,
- .kind = INCFS_BLOCK_KIND_HASH,
- .waitOnEof = true,
- .streaming = true,
- });
- }
- return result;
- }
-
- // local file and possibly signature
- const std::string filePath(metadata.data, metadata.size);
const std::string idsigPath = filePath + ".idsig";
auto idsigFd = convertPfdToFdAndDup(
@@ -314,6 +298,59 @@ static inline InputDescs openInputs(JNIEnv* env, const JniIds& jni, jobject shel
return result;
}
+static inline InputDescs openInputs(JNIEnv* env, const JniIds& jni, jobject shellCommand,
+ IncFsSize size, IncFsSpan metadata) {
+ auto mode = read<int8_t>(metadata).value_or(STDIN);
+ if (mode == LOCAL_FILE) {
+ // local file and possibly signature
+ return openLocalFile(env, jni, shellCommand, size,
+ std::string(metadata.data, metadata.size));
+ }
+
+ auto fd = convertPfdToFdAndDup(
+ env, jni,
+ env->CallStaticObjectMethod(jni.packageManagerShellCommandDataLoader,
+ jni.pmscdGetStdInPFD, shellCommand));
+ if (!fd.ok()) {
+ return {};
+ }
+
+ InputDescs result;
+ switch (mode) {
+ case STDIN: {
+ result.push_back(InputDesc{
+ .fd = std::move(fd),
+ .size = size,
+ .waitOnEof = true,
+ });
+ break;
+ }
+ case DATA_ONLY_STREAMING: {
+ // verity tree from stdin, rest is streaming
+ auto treeSize = verityTreeSizeForFile(size);
+ result.push_back(InputDesc{
+ .fd = std::move(fd),
+ .size = treeSize,
+ .kind = INCFS_BLOCK_KIND_HASH,
+ .waitOnEof = true,
+ .streaming = true,
+ .mode = DATA_ONLY_STREAMING,
+ });
+ break;
+ }
+ case STREAMING: {
+ result.push_back(InputDesc{
+ .fd = std::move(fd),
+ .size = 0,
+ .streaming = true,
+ .mode = STREAMING,
+ });
+ break;
+ }
+ }
+ return result;
+}
+
static inline JNIEnv* GetJNIEnvironment(JavaVM* vm) {
JNIEnv* env;
if (vm->GetEnv(reinterpret_cast<void**>(&env), JNI_VERSION_1_6) != JNI_OK) {
@@ -390,6 +427,7 @@ private:
blocks.reserve(BLOCKS_COUNT);
unique_fd streamingFd;
+ MetadataMode streamingMode;
for (auto&& file : addedFiles) {
auto inputs = openInputs(env, jni, shellCommand, file.size, file.metadata);
if (inputs.empty()) {
@@ -411,6 +449,7 @@ private:
for (auto&& input : inputs) {
if (input.streaming && !streamingFd.ok()) {
streamingFd.reset(dup(input.fd));
+ streamingMode = input.mode;
}
if (!copyToIncFs(incfsFd, input.size, input.kind, input.fd, input.waitOnEof,
&buffer, &blocks)) {
@@ -425,7 +464,7 @@ private:
if (streamingFd.ok()) {
ALOGE("onPrepareImage: done, proceeding to streaming.");
- return initStreaming(std::move(streamingFd));
+ return initStreaming(std::move(streamingFd), streamingMode);
}
ALOGE("onPrepareImage: done.");
@@ -564,7 +603,7 @@ private:
}
// Streaming.
- bool initStreaming(unique_fd inout) {
+ bool initStreaming(unique_fd inout, MetadataMode mode) {
mEventFd.reset(eventfd(0, EFD_CLOEXEC));
if (mEventFd < 0) {
ALOGE("Failed to create eventfd.");
@@ -591,8 +630,8 @@ private:
}
}
- mReceiverThread =
- std::thread([this, io = std::move(inout)]() mutable { receiver(std::move(io)); });
+ mReceiverThread = std::thread(
+ [this, io = std::move(inout), mode]() mutable { receiver(std::move(io), mode); });
ALOGI("Started streaming...");
return true;
}
@@ -624,7 +663,7 @@ private:
}
}
- void receiver(unique_fd inout) {
+ void receiver(unique_fd inout, MetadataMode mode) {
std::vector<uint8_t> data;
std::vector<IncFsDataBlock> instructions;
std::unordered_map<FileIdx, unique_fd> writeFds;
@@ -667,7 +706,7 @@ private:
break;
}
const FileIdx fileIdx = header.fileIdx;
- const android::dataloader::FileId fileId = convertFileIndexToFileId(fileIdx);
+ const android::dataloader::FileId fileId = convertFileIndexToFileId(mode, fileIdx);
if (!android::incfs::isValidFileId(fileId)) {
ALOGE("Unknown data destination for file ID %d. "
"Ignore.",
@@ -679,7 +718,7 @@ private:
if (writeFd < 0) {
writeFd.reset(this->mIfs->openWrite(fileId));
if (writeFd < 0) {
- ALOGE("Failed to open file %d for writing (%d). Aboring.", header.fileIdx,
+ ALOGE("Failed to open file %d for writing (%d). Aborting.", header.fileIdx,
-writeFd);
break;
}
@@ -716,9 +755,11 @@ private:
}
FileIdx convertFileIdToFileIndex(android::dataloader::FileId fileId) {
- // FileId is a string in format '+FileIdx\0'.
+ // FileId has format '\2FileIdx'.
const char* meta = (const char*)&fileId;
- if (*meta != '+') {
+
+ int8_t mode = *meta;
+ if (mode != DATA_ONLY_STREAMING && mode != STREAMING) {
return -1;
}
@@ -732,10 +773,10 @@ private:
return FileIdx(fileIdx);
}
- android::dataloader::FileId convertFileIndexToFileId(FileIdx fileIdx) {
+ android::dataloader::FileId convertFileIndexToFileId(MetadataMode mode, FileIdx fileIdx) {
IncFsFileId fileId = {};
char* meta = (char*)&fileId;
- *meta = '+';
+ *meta = mode;
if (auto [p, ec] = std::to_chars(meta + 1, meta + sizeof(fileId), fileIdx);
ec != std::errc()) {
return {};
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
index e304bca4553c..1544ff127121 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
@@ -2079,7 +2079,8 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
Owners newOwners() {
return new Owners(getUserManager(), getUserManagerInternal(),
- getPackageManagerInternal(), getActivityTaskManagerInternal());
+ getPackageManagerInternal(), getActivityTaskManagerInternal(),
+ getActivityManagerInternal());
}
UserManager getUserManager() {
@@ -9184,8 +9185,6 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
return true;
}
- Log.w(LOG_TAG, String.format("Package %s (uid=%d, pid=%d) cannot access Device IDs",
- packageName, uid, pid));
return false;
}
@@ -15742,9 +15741,11 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
}
}
+ final int suspendedState = suspended
+ ? PERSONAL_APPS_SUSPENDED_EXPLICITLY
+ : PERSONAL_APPS_NOT_SUSPENDED;
mInjector.binderWithCleanCallingIdentity(
- () -> applyPersonalAppsSuspension(
- callingUserId, PERSONAL_APPS_SUSPENDED_EXPLICITLY));
+ () -> applyPersonalAppsSuspension(callingUserId, suspendedState));
DevicePolicyEventLogger
.createEvent(DevicePolicyEnums.SET_PERSONAL_APPS_SUSPENDED)
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/Owners.java b/services/devicepolicy/java/com/android/server/devicepolicy/Owners.java
index f70fe909b459..3cdd482ffa37 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/Owners.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/Owners.java
@@ -17,6 +17,7 @@
package com.android.server.devicepolicy;
import android.annotation.Nullable;
+import android.app.ActivityManagerInternal;
import android.app.AppOpsManagerInternal;
import android.app.admin.SystemUpdateInfo;
import android.app.admin.SystemUpdatePolicy;
@@ -112,6 +113,7 @@ class Owners {
private final UserManagerInternal mUserManagerInternal;
private final PackageManagerInternal mPackageManagerInternal;
private final ActivityTaskManagerInternal mActivityTaskManagerInternal;
+ private final ActivityManagerInternal mActivityManagerInternal;
private boolean mSystemReady;
@@ -138,9 +140,10 @@ class Owners {
public Owners(UserManager userManager,
UserManagerInternal userManagerInternal,
PackageManagerInternal packageManagerInternal,
- ActivityTaskManagerInternal activityTaskManagerInternal) {
+ ActivityTaskManagerInternal activityTaskManagerInternal,
+ ActivityManagerInternal activitykManagerInternal) {
this(userManager, userManagerInternal, packageManagerInternal,
- activityTaskManagerInternal, new Injector());
+ activityTaskManagerInternal, activitykManagerInternal, new Injector());
}
@VisibleForTesting
@@ -148,11 +151,13 @@ class Owners {
UserManagerInternal userManagerInternal,
PackageManagerInternal packageManagerInternal,
ActivityTaskManagerInternal activityTaskManagerInternal,
+ ActivityManagerInternal activityManagerInternal,
Injector injector) {
mUserManager = userManager;
mUserManagerInternal = userManagerInternal;
mPackageManagerInternal = packageManagerInternal;
mActivityTaskManagerInternal = activityTaskManagerInternal;
+ mActivityManagerInternal = activityManagerInternal;
mInjector = injector;
}
@@ -220,6 +225,7 @@ class Owners {
PackageManager.MATCH_ALL | PackageManager.MATCH_KNOWN_PACKAGES, mDeviceOwnerUserId)
: Process.INVALID_UID;
mActivityTaskManagerInternal.setDeviceOwnerUid(uid);
+ mActivityManagerInternal.setDeviceOwnerUid(uid);
}
String getDeviceOwnerPackageName() {
diff --git a/services/incremental/IncrementalService.cpp b/services/incremental/IncrementalService.cpp
index ed85b931c08e..ae27c7aabdda 100644
--- a/services/incremental/IncrementalService.cpp
+++ b/services/incremental/IncrementalService.cpp
@@ -286,7 +286,6 @@ void IncrementalService::onDump(int fd) {
dprintf(fd, "\t\t\tpackageName: %s\n", params.packageName.c_str());
dprintf(fd, "\t\t\tclassName: %s\n", params.className.c_str());
dprintf(fd, "\t\t\targuments: %s\n", params.arguments.c_str());
- dprintf(fd, "\t\t\tdynamicArgs: %d\n", int(params.dynamicArgs.size()));
}
dprintf(fd, "\t\tstorages (%d):\n", int(mnt.storages.size()));
for (auto&& [storageId, storage] : mnt.storages) {
diff --git a/services/java/com/android/server/SystemServer.java b/services/java/com/android/server/SystemServer.java
index b019e9dd03ba..d04186940d2a 100644
--- a/services/java/com/android/server/SystemServer.java
+++ b/services/java/com/android/server/SystemServer.java
@@ -144,7 +144,6 @@ import com.android.server.power.ThermalManagerService;
import com.android.server.recoverysystem.RecoverySystemService;
import com.android.server.restrictions.RestrictionsManagerService;
import com.android.server.role.RoleManagerService;
-import com.android.server.rollback.RollbackManagerService;
import com.android.server.security.FileIntegrityService;
import com.android.server.security.KeyAttestationApplicationIdProviderService;
import com.android.server.security.KeyChainSystemService;
@@ -294,6 +293,8 @@ public final class SystemServer {
"com.android.server.DeviceIdleController";
private static final String BLOB_STORE_MANAGER_SERVICE_CLASS =
"com.android.server.blob.BlobStoreManagerService";
+ private static final String ROLLBACK_MANAGER_SERVICE_CLASS =
+ "com.android.server.rollback.RollbackManagerService";
private static final String TETHERING_CONNECTOR_CLASS = "android.net.ITetheringConnector";
@@ -964,7 +965,7 @@ public final class SystemServer {
// Manages apk rollbacks.
t.traceBegin("StartRollbackManagerService");
- mSystemServiceManager.startService(RollbackManagerService.class);
+ mSystemServiceManager.startService(ROLLBACK_MANAGER_SERVICE_CLASS);
t.traceEnd();
// Service to capture bugreports.
@@ -1068,7 +1069,8 @@ public final class SystemServer {
t.traceEnd();
t.traceBegin("StartTelephonyRegistry");
- telephonyRegistry = new TelephonyRegistry(context);
+ telephonyRegistry = new TelephonyRegistry(
+ context, new TelephonyRegistry.ConfigurationProvider());
ServiceManager.addService("telephony.registry", telephonyRegistry);
t.traceEnd();
diff --git a/services/robotests/src/com/android/server/location/GnssAntennaInfoProviderTest.java b/services/robotests/src/com/android/server/location/gnss/GnssAntennaInfoProviderTest.java
index 76f7ad646bb1..d8acd6ea6948 100644
--- a/services/robotests/src/com/android/server/location/GnssAntennaInfoProviderTest.java
+++ b/services/robotests/src/com/android/server/location/gnss/GnssAntennaInfoProviderTest.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package com.android.server.location;
+package com.android.server.location.gnss;
import static com.google.common.truth.Truth.assertThat;
@@ -41,7 +41,8 @@ import org.robolectric.RuntimeEnvironment;
@Presubmit
public class GnssAntennaInfoProviderTest {
@Mock
- private GnssAntennaInfoProvider.GnssAntennaInfoProviderNative mMockNative;
+ private GnssAntennaInfoProvider.GnssAntennaInfoProviderNative
+ mMockNative;
private GnssAntennaInfoProvider mTestProvider;
/** Setup. */
diff --git a/services/robotests/src/com/android/server/location/GnssBatchingProviderTest.java b/services/robotests/src/com/android/server/location/gnss/GnssBatchingProviderTest.java
index d58c3f73b8e8..25d6aa4dae29 100644
--- a/services/robotests/src/com/android/server/location/GnssBatchingProviderTest.java
+++ b/services/robotests/src/com/android/server/location/gnss/GnssBatchingProviderTest.java
@@ -1,4 +1,20 @@
-package com.android.server.location;
+/*
+ * 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.location.gnss;
import static com.google.common.truth.Truth.assertThat;
@@ -11,7 +27,7 @@ import static org.mockito.Mockito.when;
import android.platform.test.annotations.Presubmit;
-import com.android.server.location.GnssBatchingProvider.GnssBatchingProviderNative;
+import com.android.server.location.gnss.GnssBatchingProvider.GnssBatchingProviderNative;
import org.junit.Before;
import org.junit.Test;
diff --git a/services/robotests/src/com/android/server/location/GnssGeofenceProviderTest.java b/services/robotests/src/com/android/server/location/gnss/GnssGeofenceProviderTest.java
index 30c73368da15..4a533aac01db 100644
--- a/services/robotests/src/com/android/server/location/GnssGeofenceProviderTest.java
+++ b/services/robotests/src/com/android/server/location/gnss/GnssGeofenceProviderTest.java
@@ -1,4 +1,20 @@
-package com.android.server.location;
+/*
+ * 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.location.gnss;
import static org.mockito.ArgumentMatchers.anyDouble;
import static org.mockito.ArgumentMatchers.anyInt;
diff --git a/services/robotests/src/com/android/server/location/GnssMeasurementsProviderTest.java b/services/robotests/src/com/android/server/location/gnss/GnssMeasurementsProviderTest.java
index b349b67dab0c..e7d9ef810e51 100644
--- a/services/robotests/src/com/android/server/location/GnssMeasurementsProviderTest.java
+++ b/services/robotests/src/com/android/server/location/gnss/GnssMeasurementsProviderTest.java
@@ -1,4 +1,20 @@
-package com.android.server.location;
+/*
+ * 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.location.gnss;
import static com.google.common.truth.Truth.assertThat;
@@ -26,7 +42,8 @@ import org.robolectric.RuntimeEnvironment;
@Presubmit
public class GnssMeasurementsProviderTest {
@Mock
- private GnssMeasurementsProvider.GnssMeasurementProviderNative mMockNative;
+ private GnssMeasurementsProvider.GnssMeasurementProviderNative
+ mMockNative;
private GnssMeasurementsProvider mTestProvider;
@Before
diff --git a/services/robotests/src/com/android/server/location/GnssNavigationMessageProviderTest.java b/services/robotests/src/com/android/server/location/gnss/GnssNavigationMessageProviderTest.java
index aa2a96e6fad4..c21db73fb56c 100644
--- a/services/robotests/src/com/android/server/location/GnssNavigationMessageProviderTest.java
+++ b/services/robotests/src/com/android/server/location/gnss/GnssNavigationMessageProviderTest.java
@@ -1,4 +1,20 @@
-package com.android.server.location;
+/*
+ * 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.location.gnss;
import static com.google.common.truth.Truth.assertThat;
@@ -25,7 +41,8 @@ import org.robolectric.RuntimeEnvironment;
@Presubmit
public class GnssNavigationMessageProviderTest {
@Mock
- private GnssNavigationMessageProvider.GnssNavigationMessageProviderNative mMockNative;
+ private GnssNavigationMessageProvider.GnssNavigationMessageProviderNative
+ mMockNative;
private GnssNavigationMessageProvider mTestProvider;
@Before
diff --git a/services/robotests/src/com/android/server/location/GnssPositionModeTest.java b/services/robotests/src/com/android/server/location/gnss/GnssPositionModeTest.java
index f37f50e76ae5..7117ff95b401 100644
--- a/services/robotests/src/com/android/server/location/GnssPositionModeTest.java
+++ b/services/robotests/src/com/android/server/location/gnss/GnssPositionModeTest.java
@@ -1,4 +1,20 @@
-package com.android.server.location;
+/*
+ * 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.location.gnss;
import static com.google.common.truth.Truth.assertThat;
diff --git a/services/robotests/src/com/android/server/location/GnssSatelliteBlacklistHelperTest.java b/services/robotests/src/com/android/server/location/gnss/GnssSatelliteBlacklistHelperTest.java
index ba4a753e4813..7c73a2f92f71 100644
--- a/services/robotests/src/com/android/server/location/GnssSatelliteBlacklistHelperTest.java
+++ b/services/robotests/src/com/android/server/location/gnss/GnssSatelliteBlacklistHelperTest.java
@@ -1,4 +1,20 @@
-package com.android.server.location;
+/*
+ * 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.location.gnss;
import static com.google.common.truth.Truth.assertThat;
@@ -35,7 +51,8 @@ public class GnssSatelliteBlacklistHelperTest {
private ContentResolver mContentResolver;
@Mock
- private GnssSatelliteBlacklistHelper.GnssSatelliteBlacklistCallback mCallback;
+ private GnssSatelliteBlacklistHelper.GnssSatelliteBlacklistCallback
+ mCallback;
@Before
public void setUp() {
diff --git a/services/robotests/src/com/android/server/location/NtpTimeHelperTest.java b/services/robotests/src/com/android/server/location/gnss/NtpTimeHelperTest.java
index 9c5d4ad6ceeb..9b59aaddc4d4 100644
--- a/services/robotests/src/com/android/server/location/NtpTimeHelperTest.java
+++ b/services/robotests/src/com/android/server/location/gnss/NtpTimeHelperTest.java
@@ -1,4 +1,20 @@
-package com.android.server.location;
+/*
+ * 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.location.gnss;
import static com.google.common.truth.Truth.assertThat;
@@ -10,7 +26,7 @@ import android.os.SystemClock;
import android.platform.test.annotations.Presubmit;
import android.util.NtpTrustedTime;
-import com.android.server.location.NtpTimeHelper.InjectNtpTimeCallback;
+import com.android.server.location.gnss.NtpTimeHelper.InjectNtpTimeCallback;
import org.junit.Before;
import org.junit.Test;
diff --git a/services/tests/servicestests/Android.bp b/services/tests/servicestests/Android.bp
index 449e75cd11a0..e58e91179931 100644
--- a/services/tests/servicestests/Android.bp
+++ b/services/tests/servicestests/Android.bp
@@ -91,7 +91,15 @@ android_test {
enabled: false,
},
- data: [":JobTestApp"],
+ data: [
+ ":JobTestApp",
+ ],
+
+ java_resources: [
+ ":PackageParserTestApp1",
+ ":PackageParserTestApp2",
+ ":PackageParserTestApp3",
+ ],
resource_zips: [":FrameworksServicesTests_apks_as_resources"],
}
diff --git a/services/tests/servicestests/src/com/android/server/MountServiceTests.java b/services/tests/servicestests/src/com/android/server/MountServiceTests.java
deleted file mode 100644
index b1b31744c88b..000000000000
--- a/services/tests/servicestests/src/com/android/server/MountServiceTests.java
+++ /dev/null
@@ -1,279 +0,0 @@
-/*
- * Copyright (C) 2010 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.server;
-
-import android.content.Context;
-import android.content.res.Resources;
-import android.content.res.Resources.NotFoundException;
-import android.os.FileUtils;
-import android.os.storage.OnObbStateChangeListener;
-import android.os.storage.StorageManager;
-import android.test.AndroidTestCase;
-import android.test.ComparisonFailure;
-import android.test.suitebuilder.annotation.LargeTest;
-import android.util.Log;
-
-import com.android.frameworks.servicestests.R;
-
-import java.io.File;
-import java.io.InputStream;
-
-public class MountServiceTests extends AndroidTestCase {
- private static final String TAG = "MountServiceTests";
-
- private static final long MAX_WAIT_TIME = 25*1000;
- private static final long WAIT_TIME_INCR = 5*1000;
-
- private static final String OBB_MOUNT_PREFIX = "/mnt/obb/";
-
- private static void assertStartsWith(String message, String prefix, String actual) {
- if (!actual.startsWith(prefix)) {
- throw new ComparisonFailure(message, prefix, actual);
- }
- }
-
- private static class ObbObserver extends OnObbStateChangeListener {
- private String path;
-
- public int state = -1;
- boolean done = false;
-
- @Override
- public void onObbStateChange(String path, int state) {
- Log.d(TAG, "Received message. path=" + path + ", state=" + state);
- synchronized (this) {
- this.path = path;
- this.state = state;
- done = true;
- notifyAll();
- }
- }
-
- public String getPath() {
- assertTrue("Expected ObbObserver to have received a state change.", done);
- return path;
- }
-
- public int getState() {
- assertTrue("Expected ObbObserver to have received a state change.", done);
- return state;
- }
-
- public void reset() {
- this.path = null;
- this.state = -1;
- done = false;
- }
-
- public boolean isDone() {
- return done;
- }
-
- public boolean waitForCompletion() {
- long waitTime = 0;
- synchronized (this) {
- while (!isDone() && waitTime < MAX_WAIT_TIME) {
- try {
- wait(WAIT_TIME_INCR);
- waitTime += WAIT_TIME_INCR;
- } catch (InterruptedException e) {
- Log.i(TAG, "Interrupted during sleep", e);
- }
- }
- }
-
- return isDone();
- }
- }
-
- private File getFilePath(String name) {
- final File filesDir = mContext.getFilesDir();
- final File outFile = new File(filesDir, name);
- return outFile;
- }
-
- private void copyRawToFile(int rawResId, File outFile) {
- Resources res = mContext.getResources();
- InputStream is = null;
- try {
- is = res.openRawResource(rawResId);
- } catch (NotFoundException e) {
- fail("Failed to load resource with id: " + rawResId);
- }
- FileUtils.setPermissions(outFile.getPath(), FileUtils.S_IRWXU | FileUtils.S_IRWXG
- | FileUtils.S_IRWXO, -1, -1);
- assertTrue(FileUtils.copyToFile(is, outFile));
- FileUtils.setPermissions(outFile.getPath(), FileUtils.S_IRWXU | FileUtils.S_IRWXG
- | FileUtils.S_IRWXO, -1, -1);
- }
-
- private StorageManager getStorageManager() {
- return (StorageManager) getContext().getSystemService(Context.STORAGE_SERVICE);
- }
-
- private void mountObb(StorageManager sm, final int resource, final File file,
- int expectedState) {
- copyRawToFile(resource, file);
-
- final ObbObserver observer = new ObbObserver();
- assertTrue("mountObb call on " + file.getPath() + " should succeed",
- sm.mountObb(file.getPath(), null, observer));
-
- assertTrue("Mount should have completed",
- observer.waitForCompletion());
-
- if (expectedState == OnObbStateChangeListener.MOUNTED) {
- assertTrue("OBB should be mounted", sm.isObbMounted(file.getPath()));
- }
-
- assertEquals("Actual file and resolved file should be the same",
- file.getPath(), observer.getPath());
-
- assertEquals(expectedState, observer.getState());
- }
-
- private ObbObserver mountObbWithoutWait(final StorageManager sm, final int resource,
- final File file) {
- copyRawToFile(resource, file);
-
- final ObbObserver observer = new ObbObserver();
- assertTrue("mountObb call on " + file.getPath() + " should succeed", sm.mountObb(file
- .getPath(), null, observer));
-
- return observer;
- }
-
- private void waitForObbActionCompletion(final StorageManager sm, final File file,
- final ObbObserver observer, int expectedState, boolean checkPath) {
- assertTrue("Mount should have completed", observer.waitForCompletion());
-
- assertTrue("OBB should be mounted", sm.isObbMounted(file.getPath()));
-
- if (checkPath) {
- assertEquals("Actual file and resolved file should be the same", file.getPath(),
- observer.getPath());
- }
-
- assertEquals(expectedState, observer.getState());
- }
-
- private String checkMountedPath(final StorageManager sm, final File file) {
- final String mountPath = sm.getMountedObbPath(file.getPath());
- assertStartsWith("Path should be in " + OBB_MOUNT_PREFIX,
- OBB_MOUNT_PREFIX,
- mountPath);
- return mountPath;
- }
-
- private void unmountObb(final StorageManager sm, final File file, int expectedState) {
- final ObbObserver observer = new ObbObserver();
-
- assertTrue("unmountObb call on test1.obb should succeed",
- sm.unmountObb(file.getPath(), false, observer));
-
- assertTrue("Unmount should have completed",
- observer.waitForCompletion());
-
- assertEquals(expectedState, observer.getState());
-
- if (expectedState == OnObbStateChangeListener.UNMOUNTED) {
- assertFalse("OBB should not be mounted", sm.isObbMounted(file.getPath()));
- }
- }
-
- @LargeTest
- public void testMountAndUnmountObbNormal() {
- StorageManager sm = getStorageManager();
-
- final File outFile = getFilePath("test1.obb");
-
- mountObb(sm, R.raw.test1, outFile, OnObbStateChangeListener.MOUNTED);
-
- mountObb(sm, R.raw.test1, outFile, OnObbStateChangeListener.ERROR_ALREADY_MOUNTED);
-
- final String mountPath = checkMountedPath(sm, outFile);
- final File mountDir = new File(mountPath);
-
- assertTrue("OBB mounted path should be a directory",
- mountDir.isDirectory());
-
- unmountObb(sm, outFile, OnObbStateChangeListener.UNMOUNTED);
- }
-
- @LargeTest
- public void testAttemptMountNonObb() {
- StorageManager sm = getStorageManager();
-
- final File outFile = getFilePath("test1_nosig.obb");
-
- try {
- mountObb(sm, R.raw.test1_nosig, outFile, OnObbStateChangeListener.ERROR_INTERNAL);
- fail("mountObb should've failed with an exception");
- } catch (IllegalArgumentException e) {
- // Expected
- }
-
- assertFalse("OBB should not be mounted",
- sm.isObbMounted(outFile.getPath()));
-
- assertNull("OBB's mounted path should be null",
- sm.getMountedObbPath(outFile.getPath()));
- }
-
- @LargeTest
- public void testAttemptMountObbWrongPackage() {
- StorageManager sm = getStorageManager();
-
- final File outFile = getFilePath("test1_wrongpackage.obb");
-
- mountObb(sm, R.raw.test1_wrongpackage, outFile,
- OnObbStateChangeListener.ERROR_PERMISSION_DENIED);
-
- assertFalse("OBB should not be mounted",
- sm.isObbMounted(outFile.getPath()));
-
- assertNull("OBB's mounted path should be null",
- sm.getMountedObbPath(outFile.getPath()));
- }
-
- @LargeTest
- public void testMountAndUnmountTwoObbs() {
- StorageManager sm = getStorageManager();
-
- final File file1 = getFilePath("test1.obb");
- final File file2 = getFilePath("test2.obb");
-
- ObbObserver oo1 = mountObbWithoutWait(sm, R.raw.test1, file1);
- ObbObserver oo2 = mountObbWithoutWait(sm, R.raw.test1, file2);
-
- Log.d(TAG, "Waiting for OBB #1 to complete mount");
- waitForObbActionCompletion(sm, file1, oo1, OnObbStateChangeListener.MOUNTED, false);
- Log.d(TAG, "Waiting for OBB #2 to complete mount");
- waitForObbActionCompletion(sm, file2, oo2, OnObbStateChangeListener.MOUNTED, false);
-
- final String mountPath1 = checkMountedPath(sm, file1);
- final File mountDir1 = new File(mountPath1);
- assertTrue("OBB mounted path should be a directory", mountDir1.isDirectory());
-
- final String mountPath2 = checkMountedPath(sm, file2);
- final File mountDir2 = new File(mountPath2);
- assertTrue("OBB mounted path should be a directory", mountDir2.isDirectory());
-
- unmountObb(sm, file1, OnObbStateChangeListener.UNMOUNTED);
- unmountObb(sm, file2, OnObbStateChangeListener.UNMOUNTED);
- }
-}
diff --git a/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerServiceTestable.java b/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerServiceTestable.java
index c1bcf1fb75a6..3e5c21c67bb3 100644
--- a/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerServiceTestable.java
+++ b/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerServiceTestable.java
@@ -68,7 +68,7 @@ public class DevicePolicyManagerServiceTestable extends DevicePolicyManagerServi
public OwnersTestable(MockSystemServices services) {
super(services.userManager, services.userManagerInternal,
services.packageManagerInternal, services.activityTaskManagerInternal,
- new MockInjector(services));
+ services.activityManagerInternal, new MockInjector(services));
}
static class MockInjector extends Injector {
diff --git a/services/tests/servicestests/src/com/android/server/location/gnss/GnssManagerServiceTest.java b/services/tests/servicestests/src/com/android/server/location/gnss/GnssManagerServiceTest.java
index a99c982753c5..be2a5c529181 100644
--- a/services/tests/servicestests/src/com/android/server/location/gnss/GnssManagerServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/location/gnss/GnssManagerServiceTest.java
@@ -61,17 +61,9 @@ import android.os.RemoteException;
import com.android.server.LocalServices;
import com.android.server.location.AppForegroundHelper;
-import com.android.server.location.GnssAntennaInfoProvider;
-import com.android.server.location.GnssAntennaInfoProvider.GnssAntennaInfoProviderNative;
-import com.android.server.location.GnssBatchingProvider;
-import com.android.server.location.GnssCapabilitiesProvider;
-import com.android.server.location.GnssLocationProvider;
-import com.android.server.location.GnssMeasurementCorrectionsProvider;
-import com.android.server.location.GnssMeasurementsProvider;
-import com.android.server.location.GnssMeasurementsProvider.GnssMeasurementProviderNative;
-import com.android.server.location.GnssNavigationMessageProvider;
-import com.android.server.location.GnssNavigationMessageProvider.GnssNavigationMessageProviderNative;
-import com.android.server.location.GnssStatusListenerHelper;
+import com.android.server.location.gnss.GnssAntennaInfoProvider.GnssAntennaInfoProviderNative;
+import com.android.server.location.gnss.GnssMeasurementsProvider.GnssMeasurementProviderNative;
+import com.android.server.location.gnss.GnssNavigationMessageProvider.GnssNavigationMessageProviderNative;
import com.android.server.location.LocationUsageLogger;
import com.android.server.location.SettingsHelper;
diff --git a/services/tests/servicestests/src/com/android/server/pm/PackageParserTest.java b/services/tests/servicestests/src/com/android/server/pm/PackageParserTest.java
index a19d91976307..d760629552b8 100644
--- a/services/tests/servicestests/src/com/android/server/pm/PackageParserTest.java
+++ b/services/tests/servicestests/src/com/android/server/pm/PackageParserTest.java
@@ -17,11 +17,15 @@ package com.android.server.pm;
import static org.junit.Assert.assertArrayEquals;
import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertSame;
import static org.junit.Assert.assertTrue;
+import static java.nio.file.StandardCopyOption.REPLACE_EXISTING;
+
import android.annotation.NonNull;
+import android.content.Context;
import android.content.pm.ActivityInfo;
import android.content.pm.ApplicationInfo;
import android.content.pm.ConfigurationInfo;
@@ -30,7 +34,6 @@ import android.content.pm.FeatureInfo;
import android.content.pm.PackageInfo;
import android.content.pm.PackageParser;
import android.content.pm.PackageUserState;
-import android.content.pm.ProviderInfo;
import android.content.pm.ServiceInfo;
import android.content.pm.Signature;
import android.content.pm.parsing.ParsingPackage;
@@ -49,6 +52,7 @@ import android.util.ArraySet;
import android.util.DisplayMetrics;
import androidx.annotation.Nullable;
+import androidx.test.InstrumentationRegistry;
import androidx.test.filters.MediumTest;
import androidx.test.filters.SmallTest;
import androidx.test.runner.AndroidJUnit4;
@@ -69,9 +73,11 @@ import org.junit.runner.RunWith;
import java.io.File;
import java.io.IOException;
+import java.io.InputStream;
import java.lang.reflect.Array;
import java.lang.reflect.Field;
import java.nio.charset.StandardCharsets;
+import java.nio.file.Files;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashSet;
@@ -90,6 +96,9 @@ public class PackageParserTest {
private File mTmpDir;
private static final File FRAMEWORK = new File("/system/framework/framework-res.apk");
+ private static final String TEST_APP1_APK = "PackageParserTestApp1.apk";
+ private static final String TEST_APP2_APK = "PackageParserTestApp2.apk";
+ private static final String TEST_APP3_APK = "PackageParserTestApp3.apk";
@Before
public void setUp() throws IOException {
@@ -209,6 +218,61 @@ public class PackageParserTest {
assertSame(deserialized.getSharedUserId(), deserialized2.getSharedUserId());
}
+ private static PackageParser2 makeParser() {
+ return new PackageParser2(null, false, null, null, null);
+ }
+
+ private File extractFile(String filename) throws Exception {
+ final Context context = InstrumentationRegistry.getTargetContext();
+ final File tmpFile = File.createTempFile(filename, ".apk");
+ try (InputStream inputStream = context.getAssets().openNonAsset(filename)) {
+ Files.copy(inputStream, tmpFile.toPath(), REPLACE_EXISTING);
+ }
+ return tmpFile;
+ }
+
+ /**
+ * Tests AndroidManifest.xml with no android:isolatedSplits attribute.
+ */
+ @Test
+ public void testParseIsolatedSplitsDefault() throws Exception {
+ final File testFile = extractFile(TEST_APP1_APK);
+ try {
+ final ParsedPackage pkg = makeParser().parsePackage(testFile, 0, false);
+ assertFalse("isolatedSplits", pkg.isIsolatedSplitLoading());
+ } finally {
+ testFile.delete();
+ }
+ }
+
+ /**
+ * Tests AndroidManifest.xml with an android:isolatedSplits attribute set to a constant.
+ */
+ @Test
+ public void testParseIsolatedSplitsConstant() throws Exception {
+ final File testFile = extractFile(TEST_APP2_APK);
+ try {
+ final ParsedPackage pkg = makeParser().parsePackage(testFile, 0, false);
+ assertTrue("isolatedSplits", pkg.isIsolatedSplitLoading());
+ } finally {
+ testFile.delete();
+ }
+ }
+
+ /**
+ * Tests AndroidManifest.xml with an android:isolatedSplits attribute set to a resource.
+ */
+ @Test
+ public void testParseIsolatedSplitsResource() throws Exception {
+ final File testFile = extractFile(TEST_APP3_APK);
+ try {
+ final ParsedPackage pkg = makeParser().parsePackage(testFile, 0, false);
+ assertTrue("isolatedSplits", pkg.isIsolatedSplitLoading());
+ } finally {
+ testFile.delete();
+ }
+ }
+
/**
* A trivial subclass of package parser that only caches the package name, and throws away
* all other information.
diff --git a/services/tests/servicestests/test-apps/PackageParserApp/Android.bp b/services/tests/servicestests/test-apps/PackageParserApp/Android.bp
new file mode 100644
index 000000000000..c409438e94ae
--- /dev/null
+++ b/services/tests/servicestests/test-apps/PackageParserApp/Android.bp
@@ -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.
+
+android_test_helper_app {
+ name: "PackageParserTestApp1",
+ sdk_version: "current",
+ srcs: ["**/*.java"],
+ dex_preopt: {
+ enabled: false,
+ },
+ optimize: {
+ enabled: false,
+ },
+ manifest: "AndroidManifestApp1.xml",
+}
+
+android_test_helper_app {
+ name: "PackageParserTestApp2",
+ sdk_version: "current",
+ srcs: ["**/*.java"],
+ dex_preopt: {
+ enabled: false,
+ },
+ optimize: {
+ enabled: false,
+ },
+ manifest: "AndroidManifestApp2.xml",
+}
+
+android_test_helper_app {
+ name: "PackageParserTestApp3",
+ sdk_version: "current",
+ srcs: ["**/*.java"],
+ dex_preopt: {
+ enabled: false,
+ },
+ optimize: {
+ enabled: false,
+ },
+ resource_dirs: ["res"],
+ manifest: "AndroidManifestApp3.xml",
+}
diff --git a/services/tests/servicestests/test-apps/PackageParserApp/AndroidManifestApp1.xml b/services/tests/servicestests/test-apps/PackageParserApp/AndroidManifestApp1.xml
new file mode 100644
index 000000000000..01d335d2cbbd
--- /dev/null
+++ b/services/tests/servicestests/test-apps/PackageParserApp/AndroidManifestApp1.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.
+-->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="com.android.servicestests.apps.packageparserapp" >
+
+ <application>
+ <activity android:name=".TestActivity"
+ android:exported="true" />
+ </application>
+
+</manifest> \ No newline at end of file
diff --git a/services/tests/servicestests/test-apps/PackageParserApp/AndroidManifestApp2.xml b/services/tests/servicestests/test-apps/PackageParserApp/AndroidManifestApp2.xml
new file mode 100644
index 000000000000..567946cc70d7
--- /dev/null
+++ b/services/tests/servicestests/test-apps/PackageParserApp/AndroidManifestApp2.xml
@@ -0,0 +1,26 @@
+<?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="com.android.servicestests.apps.packageparserapp"
+ android:isolatedSplits="true" >
+
+ <application>
+ <activity android:name=".TestActivity"
+ android:exported="true" />
+ </application>
+
+</manifest> \ No newline at end of file
diff --git a/services/tests/servicestests/test-apps/PackageParserApp/AndroidManifestApp3.xml b/services/tests/servicestests/test-apps/PackageParserApp/AndroidManifestApp3.xml
new file mode 100644
index 000000000000..77285a805950
--- /dev/null
+++ b/services/tests/servicestests/test-apps/PackageParserApp/AndroidManifestApp3.xml
@@ -0,0 +1,26 @@
+<?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="com.android.servicestests.apps.packageparserapp"
+ android:isolatedSplits="@bool/config_isIsolated" >
+
+ <application>
+ <activity android:name=".TestActivity"
+ android:exported="true" />
+ </application>
+
+</manifest> \ No newline at end of file
diff --git a/services/tests/servicestests/test-apps/PackageParserApp/res/values/values.xml b/services/tests/servicestests/test-apps/PackageParserApp/res/values/values.xml
new file mode 100644
index 000000000000..6a4cc653494f
--- /dev/null
+++ b/services/tests/servicestests/test-apps/PackageParserApp/res/values/values.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:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <bool name="config_isIsolated">true</bool>
+</resources> \ No newline at end of file
diff --git a/core/java/android/content/pm/NamedParcelFileDescriptor.aidl b/services/tests/servicestests/test-apps/PackageParserApp/src/com/android/servicestests/apps/packageparserapp/TestActivity.java
index 68dd5f54654b..2eacb96fb2aa 100644
--- a/core/java/android/content/pm/NamedParcelFileDescriptor.aidl
+++ b/services/tests/servicestests/test-apps/PackageParserApp/src/com/android/servicestests/apps/packageparserapp/TestActivity.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,15 +14,15 @@
* limitations under the License.
*/
-package android.content.pm;
+package com.android.servicestests.apps.packageparserapp;
-import android.os.ParcelFileDescriptor;
+import android.app.Activity;
+import android.os.Bundle;
-/**
- * A named ParcelFileDescriptor.
- * @hide
- */
-parcelable NamedParcelFileDescriptor {
- @utf8InCpp String name;
- ParcelFileDescriptor fd;
+public class TestActivity extends Activity {
+ @Override
+ public void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ finish();
+ }
}
diff --git a/services/tests/uiservicestests/src/com/android/server/notification/BubbleExtractorTest.java b/services/tests/uiservicestests/src/com/android/server/notification/BubbleExtractorTest.java
index c7cef05ce442..0dbbbaa9cdd6 100644
--- a/services/tests/uiservicestests/src/com/android/server/notification/BubbleExtractorTest.java
+++ b/services/tests/uiservicestests/src/com/android/server/notification/BubbleExtractorTest.java
@@ -47,6 +47,7 @@ import org.mockito.MockitoAnnotations;
public class BubbleExtractorTest extends UiServiceTestCase {
@Mock RankingConfig mConfig;
+ @Mock BubbleExtractor.BubbleChecker mBubbleChecker;
BubbleExtractor mBubbleExtractor;
private String mPkg = "com.android.server.notification";
@@ -141,4 +142,33 @@ public class BubbleExtractorTest extends UiServiceTestCase {
assertFalse(r.canBubble());
}
+
+ @Test
+ public void testFlagBubble_true() {
+ when(mConfig.bubblesEnabled()).thenReturn(true);
+ when(mConfig.areBubblesAllowed(mPkg, mUid)).thenReturn(true);
+ NotificationRecord r = getNotificationRecord(true, IMPORTANCE_UNSPECIFIED);
+
+ mBubbleExtractor.setBubbleChecker(mBubbleChecker);
+ when(mBubbleChecker.isNotificationAppropriateToBubble(r)).thenReturn(true);
+ mBubbleExtractor.process(r);
+
+ assertTrue(r.canBubble());
+ assertTrue(r.getNotification().isBubbleNotification());
+ }
+
+ @Test
+ public void testFlagBubble_noFlag_previouslyRemoved() {
+ when(mConfig.bubblesEnabled()).thenReturn(true);
+ when(mConfig.areBubblesAllowed(mPkg, mUid)).thenReturn(true);
+ NotificationRecord r = getNotificationRecord(true, IMPORTANCE_UNSPECIFIED);
+ r.setFlagBubbleRemoved(true);
+
+ mBubbleExtractor.setBubbleChecker(mBubbleChecker);
+ when(mBubbleChecker.isNotificationAppropriateToBubble(r)).thenReturn(true);
+ mBubbleExtractor.process(r);
+
+ assertTrue(r.canBubble());
+ assertFalse(r.getNotification().isBubbleNotification());
+ }
}
diff --git a/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java b/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java
index d2417f9d10c5..f083f0e707bd 100755
--- a/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java
+++ b/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java
@@ -78,6 +78,7 @@ import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import android.app.ActivityManager;
+import android.app.ActivityManagerInternal;
import android.app.AppOpsManager;
import android.app.AutomaticZenRule;
import android.app.IActivityManager;
@@ -131,6 +132,7 @@ import android.service.notification.NotificationListenerService;
import android.service.notification.NotificationStats;
import android.service.notification.StatusBarNotification;
import android.service.notification.ZenPolicy;
+import android.telephony.TelephonyManager;
import android.test.suitebuilder.annotation.SmallTest;
import android.testing.AndroidTestingRunner;
import android.testing.TestableContext;
@@ -154,6 +156,7 @@ import com.android.internal.logging.InstanceIdSequence;
import com.android.internal.logging.InstanceIdSequenceFake;
import com.android.internal.statusbar.NotificationVisibility;
import com.android.internal.util.FastXmlSerializer;
+import com.android.server.DeviceIdleInternal;
import com.android.server.LocalServices;
import com.android.server.SystemService;
import com.android.server.UiServiceTestCase;
@@ -380,12 +383,20 @@ public class NotificationManagerServiceTest extends UiServiceTestCase {
MockitoAnnotations.initMocks(this);
+ DeviceIdleInternal deviceIdleInternal = mock(DeviceIdleInternal.class);
+ when(deviceIdleInternal.getNotificationWhitelistDuration()).thenReturn(3000L);
+ ActivityManagerInternal activityManagerInternal = mock(ActivityManagerInternal.class);
+
LocalServices.removeServiceForTest(UriGrantsManagerInternal.class);
LocalServices.addService(UriGrantsManagerInternal.class, mUgmInternal);
LocalServices.removeServiceForTest(WindowManagerInternal.class);
LocalServices.addService(WindowManagerInternal.class, mWindowManagerInternal);
LocalServices.removeServiceForTest(StatusBarManagerInternal.class);
LocalServices.addService(StatusBarManagerInternal.class, mStatusBar);
+ LocalServices.removeServiceForTest(DeviceIdleInternal.class);
+ LocalServices.addService(DeviceIdleInternal.class, deviceIdleInternal);
+ LocalServices.removeServiceForTest(ActivityManagerInternal.class);
+ LocalServices.addService(ActivityManagerInternal.class, activityManagerInternal);
doNothing().when(mContext).sendBroadcastAsUser(any(), any(), any());
@@ -457,7 +468,8 @@ public class NotificationManagerServiceTest extends UiServiceTestCase {
mCompanionMgr, mSnoozeHelper, mUsageStats, mPolicyFile, mActivityManager,
mGroupHelper, mAm, mAtm, mAppUsageStats,
mock(DevicePolicyManagerInternal.class), mUgm, mUgmInternal,
- mAppOpsManager, mUm, mHistoryManager, mStatsManager);
+ mAppOpsManager, mUm, mHistoryManager, mStatsManager,
+ mock(TelephonyManager.class));
mService.onBootPhase(SystemService.PHASE_SYSTEM_SERVICES_READY);
mService.setAudioManager(mAudioManager);
@@ -5592,6 +5604,67 @@ public class NotificationManagerServiceTest extends UiServiceTestCase {
}
@Test
+ public void testNotificationBubbleIsFlagRemoved_resetOnUpdate() throws Exception {
+ // Bubbles are allowed!
+ setUpPrefsForBubbles(PKG, mUid, true /* global */, true /* app */, true /* channel */);
+ // Notif with bubble metadata
+ NotificationRecord nr = generateMessageBubbleNotifRecord(mTestNotificationChannel,
+ "testNotificationBubbleIsFlagRemoved_resetOnUpdate");
+
+ mBinderService.enqueueNotificationWithTag(PKG, PKG, nr.getSbn().getTag(),
+ nr.getSbn().getId(), nr.getSbn().getNotification(), nr.getSbn().getUserId());
+ waitForIdle();
+ // Flag shouldn't be modified
+ NotificationRecord recordToCheck = mService.getNotificationRecord(nr.getSbn().getKey());
+ assertFalse(recordToCheck.isFlagBubbleRemoved());
+
+ // Notify we're not a bubble
+ mService.mNotificationDelegate.onNotificationBubbleChanged(nr.getKey(), false);
+ waitForIdle();
+ // Flag should be modified
+ recordToCheck = mService.getNotificationRecord(nr.getSbn().getKey());
+ assertTrue(recordToCheck.isFlagBubbleRemoved());
+
+
+ // Update the notif
+ mBinderService.enqueueNotificationWithTag(PKG, PKG, nr.getSbn().getTag(),
+ nr.getSbn().getId(), nr.getSbn().getNotification(), nr.getSbn().getUserId());
+ waitForIdle();
+ // And the flag is reset
+ recordToCheck = mService.getNotificationRecord(nr.getSbn().getKey());
+ assertFalse(recordToCheck.isFlagBubbleRemoved());
+ }
+
+ @Test
+ public void testNotificationBubbleIsFlagRemoved_resetOnBubbleChangedTrue() throws Exception {
+ // Bubbles are allowed!
+ setUpPrefsForBubbles(PKG, mUid, true /* global */, true /* app */, true /* channel */);
+ // Notif with bubble metadata
+ NotificationRecord nr = generateMessageBubbleNotifRecord(mTestNotificationChannel,
+ "testNotificationBubbleIsFlagRemoved_trueOnBubbleChangedTrue");
+
+ mBinderService.enqueueNotificationWithTag(PKG, PKG, nr.getSbn().getTag(),
+ nr.getSbn().getId(), nr.getSbn().getNotification(), nr.getSbn().getUserId());
+ waitForIdle();
+ // Flag shouldn't be modified
+ NotificationRecord recordToCheck = mService.getNotificationRecord(nr.getSbn().getKey());
+ assertFalse(recordToCheck.isFlagBubbleRemoved());
+
+ // Notify we're not a bubble
+ mService.mNotificationDelegate.onNotificationBubbleChanged(nr.getKey(), false);
+ waitForIdle();
+ // Flag should be modified
+ recordToCheck = mService.getNotificationRecord(nr.getSbn().getKey());
+ assertTrue(recordToCheck.isFlagBubbleRemoved());
+
+ // Notify we are a bubble
+ mService.mNotificationDelegate.onNotificationBubbleChanged(nr.getKey(), true);
+ waitForIdle();
+ // And the flag is reset
+ assertFalse(recordToCheck.isFlagBubbleRemoved());
+ }
+
+ @Test
public void testOnBubbleNotificationSuppressionChanged() throws Exception {
// Bubbles are allowed!
setUpPrefsForBubbles(PKG, mUid, true /* global */, true /* app */, true /* channel */);
diff --git a/services/tests/uiservicestests/src/com/android/server/notification/RoleObserverTest.java b/services/tests/uiservicestests/src/com/android/server/notification/RoleObserverTest.java
index 19ff683a46a1..3281c3f4cfb9 100644
--- a/services/tests/uiservicestests/src/com/android/server/notification/RoleObserverTest.java
+++ b/services/tests/uiservicestests/src/com/android/server/notification/RoleObserverTest.java
@@ -47,6 +47,7 @@ import android.content.pm.UserInfo;
import android.os.Looper;
import android.os.UserHandle;
import android.os.UserManager;
+import android.telephony.TelephonyManager;
import android.test.suitebuilder.annotation.SmallTest;
import android.testing.AndroidTestingRunner;
import android.testing.TestableContext;
@@ -153,7 +154,7 @@ public class RoleObserverTest extends UiServiceTestCase {
mock(DevicePolicyManagerInternal.class), mock(IUriGrantsManager.class),
mock(UriGrantsManagerInternal.class),
mock(AppOpsManager.class), mUm, mock(NotificationHistoryManager.class),
- mock(StatsManager.class));
+ mock(StatsManager.class), mock(TelephonyManager.class));
} catch (SecurityException e) {
if (!e.getMessage().contains("Permission Denial: not allowed to send broadcast")) {
throw e;
diff --git a/services/tests/wmtests/src/com/android/server/wm/AppTransitionTests.java b/services/tests/wmtests/src/com/android/server/wm/AppTransitionTests.java
index c71d8194f889..08e492a7b0ff 100644
--- a/services/tests/wmtests/src/com/android/server/wm/AppTransitionTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/AppTransitionTests.java
@@ -28,7 +28,6 @@ import static android.view.WindowManager.TRANSIT_KEYGUARD_UNOCCLUDE;
import static androidx.test.platform.app.InstrumentationRegistry.getInstrumentation;
-import static com.android.dx.mockito.inline.extended.ExtendedMockito.anyBoolean;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.doNothing;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.doReturn;
@@ -38,7 +37,6 @@ import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
import static org.mockito.ArgumentMatchers.any;
-import android.graphics.Rect;
import android.os.IBinder;
import android.os.RemoteException;
import android.platform.test.annotations.Presubmit;
@@ -70,7 +68,7 @@ public class AppTransitionTests extends WindowTestsBase {
@Before
public void setUp() throws Exception {
- doNothing().when(mWm.mRoot).performSurfacePlacement(anyBoolean());
+ doNothing().when(mWm.mRoot).performSurfacePlacement();
mDc = mWm.getDefaultDisplayContentLocked();
}
diff --git a/services/tests/wmtests/src/com/android/server/wm/AppWindowTokenTests.java b/services/tests/wmtests/src/com/android/server/wm/AppWindowTokenTests.java
index 6cc57f4dbf8c..cf3cfecbf65e 100644
--- a/services/tests/wmtests/src/com/android/server/wm/AppWindowTokenTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/AppWindowTokenTests.java
@@ -174,7 +174,7 @@ public class AppWindowTokenTests extends WindowTestsBase {
null /* freezeThisOneIfNeeded */, false /* forceUpdate */);
// In this test, DC will not get config update. Set the waiting flag to false.
mDisplayContent.mWaitingForConfig = false;
- mWm.mRoot.performSurfacePlacement(false /* recoveringMemory */);
+ mWm.mRoot.performSurfacePlacement();
assertEquals(SCREEN_ORIENTATION_REVERSE_LANDSCAPE, mDisplayContent.getLastOrientation());
assertTrue(appWindow.mResizeReported);
appWindow.removeImmediately();
diff --git a/services/tests/wmtests/src/com/android/server/wm/LaunchParamsPersisterTests.java b/services/tests/wmtests/src/com/android/server/wm/LaunchParamsPersisterTests.java
index 8f3ff52b8018..ae467c0c811d 100644
--- a/services/tests/wmtests/src/com/android/server/wm/LaunchParamsPersisterTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/LaunchParamsPersisterTests.java
@@ -120,7 +120,7 @@ public class LaunchParamsPersisterTests extends ActivityTestsBase {
.build();
mTestTask.mUserId = TEST_USER_ID;
mTestTask.mLastNonFullscreenBounds = TEST_BOUNDS;
- mTestTask.hasBeenVisible = true;
+ mTestTask.setHasBeenVisible(true);
mTaskWithDifferentComponent = new TaskBuilder(mSupervisor)
.setComponent(ALTERNATIVE_COMPONENT).build();
@@ -346,7 +346,7 @@ public class LaunchParamsPersisterTests extends ActivityTestsBase {
.build();
anotherTaskOfTheSameUser.setWindowingMode(WINDOWING_MODE_FREEFORM);
anotherTaskOfTheSameUser.setBounds(200, 300, 400, 500);
- anotherTaskOfTheSameUser.hasBeenVisible = true;
+ anotherTaskOfTheSameUser.setHasBeenVisible(true);
mTarget.saveTask(anotherTaskOfTheSameUser);
stack = mTestDisplay.createStack(TEST_WINDOWING_MODE,
@@ -358,7 +358,7 @@ public class LaunchParamsPersisterTests extends ActivityTestsBase {
.build();
anotherTaskOfDifferentUser.setWindowingMode(WINDOWING_MODE_FREEFORM);
anotherTaskOfDifferentUser.setBounds(300, 400, 500, 600);
- anotherTaskOfDifferentUser.hasBeenVisible = true;
+ anotherTaskOfDifferentUser.setHasBeenVisible(true);
mTarget.saveTask(anotherTaskOfDifferentUser);
mTarget.onCleanupUser(TEST_USER_ID);
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 66566bc5dff5..8846fb8e0962 100644
--- a/services/tests/wmtests/src/com/android/server/wm/RecentTasksTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/RecentTasksTest.java
@@ -21,6 +21,7 @@ import static android.app.WindowConfiguration.ACTIVITY_TYPE_HOME;
import static android.app.WindowConfiguration.ACTIVITY_TYPE_STANDARD;
import static android.app.WindowConfiguration.ACTIVITY_TYPE_UNDEFINED;
import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
+import static android.app.WindowConfiguration.WINDOWING_MODE_MULTI_WINDOW;
import static android.app.WindowConfiguration.WINDOWING_MODE_PINNED;
import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED;
import static android.content.Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS;
@@ -28,6 +29,7 @@ import static android.content.Intent.FLAG_ACTIVITY_MULTIPLE_TASK;
import static android.content.Intent.FLAG_ACTIVITY_NEW_DOCUMENT;
import static android.content.Intent.FLAG_ACTIVITY_NEW_TASK;
import static android.view.Display.DEFAULT_DISPLAY;
+import static android.view.Display.TYPE_VIRTUAL;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.doNothing;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.doReturn;
@@ -54,6 +56,7 @@ import static java.lang.Integer.MAX_VALUE;
import android.app.ActivityManager.RecentTaskInfo;
import android.app.ActivityManager.RunningTaskInfo;
+import android.app.ActivityOptions;
import android.app.ActivityTaskManager;
import android.app.WindowConfiguration;
import android.content.ComponentName;
@@ -681,24 +684,19 @@ public class RecentTasksTest extends ActivityTestsBase {
* Tests that tasks on singleTaskDisplay are not visible and not trimmed/removed.
*/
@Test
- public void testVisibleTasks_singleTaskDisplay() {
+ public void testVisibleTasks_alwaysOnTop() {
mRecentTasks.setOnlyTestVisibleRange();
mRecentTasks.setParameters(-1 /* min */, 3 /* max */, -1 /* ms */);
- final DisplayContent singleTaskDisplay =
- addNewDisplayContentAt(DisplayContent.POSITION_TOP);
- singleTaskDisplay.setDisplayToSingleTaskInstance();
- ActivityStack singleTaskStack = singleTaskDisplay.createStack(
- WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD, true /* onTop */);
+ final DisplayContent display = mRootWindowContainer.getDefaultDisplay();
+ final Task alwaysOnTopTask = display.createStack(WINDOWING_MODE_MULTI_WINDOW,
+ ACTIVITY_TYPE_STANDARD, true /* onTop */);
+ alwaysOnTopTask.setAlwaysOnTop(true);
- Task excludedTask1 = createTaskBuilder(".ExcludedTask1")
- .setStack(singleTaskStack)
- .build();
+ assertFalse("Always on top tasks should not be visible recents",
+ mRecentTasks.isVisibleRecentTask(alwaysOnTopTask));
- assertFalse("Tasks on singleTaskDisplay should not be visible recents",
- mRecentTasks.isVisibleRecentTask(excludedTask1));
-
- mRecentTasks.add(excludedTask1);
+ mRecentTasks.add(alwaysOnTopTask);
// Add N+1 visible tasks.
mRecentTasks.add(mTasks.get(0));
@@ -1115,7 +1113,6 @@ public class RecentTasksTest extends ActivityTestsBase {
() -> mService.moveTaskToStack(0, INVALID_STACK_ID, true));
assertSecurityException(expectCallable,
() -> mService.setTaskWindowingModeSplitScreenPrimary(0, true));
- assertSecurityException(expectCallable, () -> mService.dismissPip(true, 0));
assertSecurityException(expectCallable,
() -> mService.moveTopActivityToPinnedStack(INVALID_STACK_ID, new Rect()));
assertSecurityException(expectCallable, () -> mService.getAllStackInfos());
@@ -1366,12 +1363,12 @@ public class RecentTasksTest extends ActivityTestsBase {
public boolean mLastAllowed;
@Override
- void getTasks(int maxNum, List<RunningTaskInfo> list, int ignoreActivityType,
- int ignoreWindowingMode, RootWindowContainer root,
- int callingUid, boolean allowed, boolean crossUser, ArraySet<Integer> profileIds) {
+ void getTasks(int maxNum, List<RunningTaskInfo> list, boolean filterOnlyVisibleRecents,
+ RootWindowContainer root, int callingUid, boolean allowed, boolean crossUser,
+ ArraySet<Integer> profileIds) {
mLastAllowed = allowed;
- super.getTasks(maxNum, list, ignoreActivityType, ignoreWindowingMode, root,
- callingUid, allowed, crossUser, profileIds);
+ super.getTasks(maxNum, list, filterOnlyVisibleRecents, root, callingUid, allowed,
+ crossUser, profileIds);
}
}
}
diff --git a/services/tests/wmtests/src/com/android/server/wm/RecentsAnimationControllerTest.java b/services/tests/wmtests/src/com/android/server/wm/RecentsAnimationControllerTest.java
index f242989ab885..da07baca3ce1 100644
--- a/services/tests/wmtests/src/com/android/server/wm/RecentsAnimationControllerTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/RecentsAnimationControllerTest.java
@@ -100,7 +100,7 @@ public class RecentsAnimationControllerTest extends WindowTestsBase {
@Before
public void setUp() throws Exception {
MockitoAnnotations.initMocks(this);
- doNothing().when(mWm.mRoot).performSurfacePlacement(anyBoolean());
+ doNothing().when(mWm.mRoot).performSurfacePlacement();
when(mMockRunner.asBinder()).thenReturn(new Binder());
mDefaultDisplay = mWm.mRoot.getDefaultDisplay();
mController = spy(new RecentsAnimationController(mWm, mMockRunner, mAnimationCallbacks,
diff --git a/services/tests/wmtests/src/com/android/server/wm/RunningTasksTest.java b/services/tests/wmtests/src/com/android/server/wm/RunningTasksTest.java
index 0d5565428bf2..d6a67abc9e76 100644
--- a/services/tests/wmtests/src/com/android/server/wm/RunningTasksTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/RunningTasksTest.java
@@ -16,9 +16,6 @@
package com.android.server.wm;
-import static android.app.WindowConfiguration.ACTIVITY_TYPE_UNDEFINED;
-import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED;
-
import static com.google.common.truth.Truth.assertThat;
import static org.junit.Assert.assertEquals;
@@ -82,9 +79,8 @@ public class RunningTasksTest extends ActivityTestsBase {
// collected from all tasks across all the stacks
final int numFetchTasks = 5;
ArrayList<RunningTaskInfo> tasks = new ArrayList<>();
- mRunningTasks.getTasks(5, tasks, ACTIVITY_TYPE_UNDEFINED, WINDOWING_MODE_UNDEFINED,
- mRootWindowContainer, -1 /* callingUid */, true /* allowed */,
- true /*crossUser */, PROFILE_IDS);
+ mRunningTasks.getTasks(5, tasks, false /* filterOnlyVisibleRecents */, mRootWindowContainer,
+ -1 /* callingUid */, true /* allowed */, true /*crossUser */, PROFILE_IDS);
assertThat(tasks).hasSize(numFetchTasks);
for (int i = 0; i < numFetchTasks; i++) {
assertEquals(numTasks - i - 1, tasks.get(i).id);
@@ -93,9 +89,9 @@ public class RunningTasksTest extends ActivityTestsBase {
// Ensure that requesting more than the total number of tasks only returns the subset
// and does not crash
tasks.clear();
- mRunningTasks.getTasks(100, tasks, ACTIVITY_TYPE_UNDEFINED, WINDOWING_MODE_UNDEFINED,
- mRootWindowContainer, -1 /* callingUid */, true /* allowed */,
- true /* crossUser */, PROFILE_IDS);
+ mRunningTasks.getTasks(100, tasks, false /* filterOnlyVisibleRecents */,
+ mRootWindowContainer, -1 /* callingUid */, true /* allowed */, true /* crossUser */,
+ PROFILE_IDS);
assertThat(tasks).hasSize(numTasks);
for (int i = 0; i < numTasks; i++) {
assertEquals(numTasks - i - 1, tasks.get(i).id);
@@ -119,9 +115,9 @@ public class RunningTasksTest extends ActivityTestsBase {
final int numFetchTasks = 5;
final ArrayList<RunningTaskInfo> tasks = new ArrayList<>();
- mRunningTasks.getTasks(numFetchTasks, tasks, ACTIVITY_TYPE_UNDEFINED,
- WINDOWING_MODE_UNDEFINED, mRootWindowContainer, -1 /* callingUid */,
- true /* allowed */, true /*crossUser */, PROFILE_IDS);
+ mRunningTasks.getTasks(numFetchTasks, tasks, false /* filterOnlyVisibleRecents */,
+ mRootWindowContainer, -1 /* callingUid */, true /* allowed */, true /*crossUser */,
+ PROFILE_IDS);
assertThat(tasks).hasSize(numFetchTasks);
for (int i = 0; i < tasks.size(); i++) {
final Bundle extras = tasks.get(i).baseIntent.getExtras();
diff --git a/services/tests/wmtests/src/com/android/server/wm/SizeCompatTests.java b/services/tests/wmtests/src/com/android/server/wm/SizeCompatTests.java
index edf81ea32ad3..893a14541c48 100644
--- a/services/tests/wmtests/src/com/android/server/wm/SizeCompatTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/SizeCompatTests.java
@@ -481,7 +481,7 @@ public class SizeCompatTests extends ActivityTestsBase {
// The letterbox needs a main window to layout.
addWindowToActivity(mActivity);
// Compute the frames of the window and invoke {@link ActivityRecord#layoutLetterbox}.
- mActivity.mRootWindowContainer.performSurfacePlacement(false /* recoveringMemory */);
+ mActivity.mRootWindowContainer.performSurfacePlacement();
// The letterbox insets should be [350, 0 - 350, 0].
assertEquals(new Rect(mActivity.getBounds().left, 0, dh - mActivity.getBounds().right, 0),
mActivity.getLetterboxInsets());
diff --git a/services/tests/wmtests/src/com/android/server/wm/TaskOrganizerTests.java b/services/tests/wmtests/src/com/android/server/wm/TaskOrganizerTests.java
index ed635ce3f69e..4cc84a65fb29 100644
--- a/services/tests/wmtests/src/com/android/server/wm/TaskOrganizerTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/TaskOrganizerTests.java
@@ -96,10 +96,28 @@ public class TaskOrganizerTests extends WindowTestsBase {
return registerMockOrganizer(WINDOWING_MODE_MULTI_WINDOW);
}
+ Task createTask(ActivityStack stack, boolean fakeDraw) {
+ final Task task = createTaskInStack(stack, 0);
+
+ if (fakeDraw) {
+ task.setHasBeenVisible(true);
+ }
+ return task;
+ }
+
+ Task createTask(ActivityStack stack) {
+ // Fake draw notifications for most of our tests.
+ return createTask(stack, true);
+ }
+
+ ActivityStack createStack() {
+ return createTaskStackOnDisplay(mDisplayContent);
+ }
+
@Test
public void testAppearVanish() throws RemoteException {
- final ActivityStack stack = createTaskStackOnDisplay(mDisplayContent);
- final Task task = createTaskInStack(stack, 0 /* userId */);
+ final ActivityStack stack = createStack();
+ final Task task = createTask(stack);
final ITaskOrganizer organizer = registerMockOrganizer();
task.setTaskOrganizer(organizer);
@@ -110,9 +128,42 @@ public class TaskOrganizerTests extends WindowTestsBase {
}
@Test
+ public void testAppearWaitsForVisibility() throws RemoteException {
+ final ActivityStack stack = createStack();
+ final Task task = createTask(stack, false);
+ final ITaskOrganizer organizer = registerMockOrganizer();
+
+ task.setTaskOrganizer(organizer);
+
+ verify(organizer, never()).onTaskAppeared(any());
+ task.setHasBeenVisible(true);
+ assertTrue(stack.getHasBeenVisible());
+
+ verify(organizer).onTaskAppeared(any());
+
+ task.removeImmediately();
+ verify(organizer).onTaskVanished(any());
+ }
+
+ @Test
+ public void testNoVanishedIfNoAppear() throws RemoteException {
+ final ActivityStack stack = createStack();
+ final Task task = createTask(stack, false /* hasBeenVisible */);
+ final ITaskOrganizer organizer = registerMockOrganizer();
+
+ // In this test we skip making the Task visible, and verify
+ // that even though a TaskOrganizer is set remove doesn't emit
+ // a vanish callback, because we never emitted appear.
+ task.setTaskOrganizer(organizer);
+ verify(organizer, never()).onTaskAppeared(any());
+ task.removeImmediately();
+ verify(organizer, never()).onTaskVanished(any());
+ }
+
+ @Test
public void testSwapOrganizer() throws RemoteException {
- final ActivityStack stack = createTaskStackOnDisplay(mDisplayContent);
- final Task task = createTaskInStack(stack, 0 /* userId */);
+ final ActivityStack stack = createStack();
+ final Task task = createTask(stack);
final ITaskOrganizer organizer = registerMockOrganizer(WINDOWING_MODE_MULTI_WINDOW);
final ITaskOrganizer organizer2 = registerMockOrganizer(WINDOWING_MODE_PINNED);
@@ -125,8 +176,8 @@ public class TaskOrganizerTests extends WindowTestsBase {
@Test
public void testSwapWindowingModes() throws RemoteException {
- final ActivityStack stack = createTaskStackOnDisplay(mDisplayContent);
- final Task task = createTaskInStack(stack, 0 /* userId */);
+ final ActivityStack stack = createStack();
+ final Task task = createTask(stack);
final ITaskOrganizer organizer = registerMockOrganizer(WINDOWING_MODE_MULTI_WINDOW);
final ITaskOrganizer organizer2 = registerMockOrganizer(WINDOWING_MODE_PINNED);
@@ -139,8 +190,8 @@ public class TaskOrganizerTests extends WindowTestsBase {
@Test
public void testClearOrganizer() throws RemoteException {
- final ActivityStack stack = createTaskStackOnDisplay(mDisplayContent);
- final Task task = createTaskInStack(stack, 0 /* userId */);
+ final ActivityStack stack = createStack();
+ final Task task = createTask(stack);
final ITaskOrganizer organizer = registerMockOrganizer();
stack.setTaskOrganizer(organizer);
@@ -154,8 +205,8 @@ public class TaskOrganizerTests extends WindowTestsBase {
@Test
public void testUnregisterOrganizer() throws RemoteException {
- final ActivityStack stack = createTaskStackOnDisplay(mDisplayContent);
- final Task task = createTaskInStack(stack, 0 /* userId */);
+ final ActivityStack stack = createStack();
+ final Task task = createTask(stack);
final ITaskOrganizer organizer = registerMockOrganizer();
stack.setWindowingMode(WINDOWING_MODE_MULTI_WINDOW);
@@ -169,12 +220,12 @@ public class TaskOrganizerTests extends WindowTestsBase {
@Test
public void testUnregisterOrganizerReturnsRegistrationToPrevious() throws RemoteException {
- final ActivityStack stack = createTaskStackOnDisplay(mDisplayContent);
- final Task task = createTaskInStack(stack, 0 /* userId */);
- final ActivityStack stack2 = createTaskStackOnDisplay(mDisplayContent);
- final Task task2 = createTaskInStack(stack2, 0 /* userId */);
- final ActivityStack stack3 = createTaskStackOnDisplay(mDisplayContent);
- final Task task3 = createTaskInStack(stack3, 0 /* userId */);
+ final ActivityStack stack = createStack();
+ final Task task = createTask(stack);
+ final ActivityStack stack2 = createStack();
+ final Task task2 = createTask(stack2);
+ final ActivityStack stack3 = createStack();
+ final Task task3 = createTask(stack3);
final ITaskOrganizer organizer = registerMockOrganizer(WINDOWING_MODE_MULTI_WINDOW);
// First organizer is registered, verify a task appears when changing windowing mode
@@ -202,9 +253,9 @@ public class TaskOrganizerTests extends WindowTestsBase {
public void testRegisterTaskOrganizerStackWindowingModeChanges() throws RemoteException {
final ITaskOrganizer organizer = registerMockOrganizer(WINDOWING_MODE_PINNED);
- final ActivityStack stack = createTaskStackOnDisplay(mDisplayContent);
- final Task task = createTaskInStack(stack, 0 /* userId */);
- final Task task2 = createTaskInStack(stack, 0 /* userId */);
+ final ActivityStack stack = createStack();
+ final Task task = createTask(stack);
+ final Task task2 = createTask(stack);
stack.setWindowingMode(WINDOWING_MODE_PINNED);
verify(organizer, times(1)).onTaskAppeared(any());
@@ -214,8 +265,8 @@ public class TaskOrganizerTests extends WindowTestsBase {
@Test
public void testRegisterTaskOrganizerWithExistingTasks() throws RemoteException {
- final ActivityStack stack = createTaskStackOnDisplay(mDisplayContent);
- final Task task = createTaskInStack(stack, 0 /* userId */);
+ final ActivityStack stack = createStack();
+ final Task task = createTask(stack);
stack.setWindowingMode(WINDOWING_MODE_PINNED);
final ITaskOrganizer organizer = registerMockOrganizer(WINDOWING_MODE_PINNED);
@@ -560,8 +611,8 @@ public class TaskOrganizerTests extends WindowTestsBase {
@Test
public void testTrivialBLASTCallback() throws RemoteException {
- final ActivityStack stackController1 = createTaskStackOnDisplay(mDisplayContent);
- final Task task = createTaskInStack(stackController1, 0 /* userId */);
+ final ActivityStack stackController1 = createStack();
+ final Task task = createTask(stackController1);
final ITaskOrganizer organizer = registerMockOrganizer();
spyOn(task);
@@ -582,8 +633,8 @@ public class TaskOrganizerTests extends WindowTestsBase {
@Test
public void testOverlappingBLASTCallback() throws RemoteException {
- final ActivityStack stackController1 = createTaskStackOnDisplay(mDisplayContent);
- final Task task = createTaskInStack(stackController1, 0 /* userId */);
+ final ActivityStack stackController1 = createStack();
+ final Task task = createTask(stackController1);
final ITaskOrganizer organizer = registerMockOrganizer();
spyOn(task);
@@ -611,8 +662,8 @@ public class TaskOrganizerTests extends WindowTestsBase {
@Test
public void testBLASTCallbackWithWindow() {
- final ActivityStack stackController1 = createTaskStackOnDisplay(mDisplayContent);
- final Task task = createTaskInStack(stackController1, 0 /* userId */);
+ final ActivityStack stackController1 = createStack();
+ final Task task = createTask(stackController1);
final ITaskOrganizer organizer = registerMockOrganizer();
final WindowState w = createAppWindow(task, TYPE_APPLICATION, "Enlightened Window");
makeWindowVisible(w);
@@ -635,8 +686,8 @@ public class TaskOrganizerTests extends WindowTestsBase {
@Test
public void testBLASTCallbackWithInvisibleWindow() {
- final ActivityStack stackController1 = createTaskStackOnDisplay(mDisplayContent);
- final Task task = createTaskInStack(stackController1, 0 /* userId */);
+ final ActivityStack stackController1 = createStack();
+ final Task task = createTask(stackController1);
final ITaskOrganizer organizer = registerMockOrganizer();
final WindowState w = createAppWindow(task, TYPE_APPLICATION, "Enlightened Window");
@@ -657,8 +708,8 @@ public class TaskOrganizerTests extends WindowTestsBase {
@Test
public void testBLASTCallbackWithChildWindow() {
- final ActivityStack stackController1 = createTaskStackOnDisplay(mDisplayContent);
- final Task task = createTaskInStack(stackController1, 0 /* userId */);
+ final ActivityStack 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");
@@ -708,6 +759,8 @@ public class TaskOrganizerTests extends WindowTestsBase {
record.info.flags |= ActivityInfo.FLAG_SUPPORTS_PICTURE_IN_PICTURE;
spyOn(record);
doReturn(true).when(record).checkEnterPictureInPictureState(any(), anyBoolean());
+
+ record.getRootTask().setHasBeenVisible(true);
return record;
}
@@ -755,4 +808,23 @@ public class TaskOrganizerTests extends WindowTestsBase {
assertEquals(3, ratio.getNumerator());
assertEquals(4, ratio.getDenominator());
}
+
+ @Test
+ public void testPreventDuplicateAppear() throws RemoteException {
+ final ActivityStack stack = createStack();
+ final Task task = createTask(stack);
+ final ITaskOrganizer organizer = registerMockOrganizer();
+
+ task.setTaskOrganizer(organizer);
+ // setHasBeenVisible was already called once by the set-up code.
+ task.setHasBeenVisible(true);
+ verify(organizer, times(1)).onTaskAppeared(any());
+
+ task.taskOrganizerUnregistered();
+ task.setTaskOrganizer(organizer);
+ verify(organizer, times(2)).onTaskAppeared(any());
+
+ task.removeImmediately();
+ verify(organizer).onTaskVanished(any());
+ }
}
diff --git a/services/tests/wmtests/src/com/android/server/wm/TaskRecordTests.java b/services/tests/wmtests/src/com/android/server/wm/TaskRecordTests.java
index 56c19a47b68a..1ad4079c5193 100644
--- a/services/tests/wmtests/src/com/android/server/wm/TaskRecordTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/TaskRecordTests.java
@@ -874,11 +874,11 @@ public class TaskRecordTests extends ActivityTestsBase {
spyOn(persister);
final Task task = getTestTask();
- task.hasBeenVisible = false;
+ task.setHasBeenVisible(false);
task.getDisplayContent().setDisplayWindowingMode(WINDOWING_MODE_FREEFORM);
task.getStack().setWindowingMode(WINDOWING_MODE_FULLSCREEN);
- task.hasBeenVisible = true;
+ task.setHasBeenVisible(true);
task.onConfigurationChanged(task.getParent().getConfiguration());
verify(persister).saveTask(task, task.getDisplayContent());
@@ -890,7 +890,7 @@ public class TaskRecordTests extends ActivityTestsBase {
spyOn(persister);
final Task task = getTestTask();
- task.hasBeenVisible = false;
+ task.setHasBeenVisible(false);
task.getDisplayContent().setWindowingMode(WindowConfiguration.WINDOWING_MODE_FREEFORM);
task.getStack().setWindowingMode(WINDOWING_MODE_FULLSCREEN);
final DisplayContent oldDisplay = task.getDisplayContent();
@@ -900,7 +900,7 @@ public class TaskRecordTests extends ActivityTestsBase {
persister.getLaunchParams(task, null, params);
assertEquals(WINDOWING_MODE_UNDEFINED, params.mWindowingMode);
- task.hasBeenVisible = true;
+ task.setHasBeenVisible(true);
task.removeImmediately();
verify(persister).saveTask(task, oldDisplay);
@@ -915,10 +915,10 @@ public class TaskRecordTests extends ActivityTestsBase {
spyOn(persister);
final Task task = getTestTask();
- task.hasBeenVisible = false;
+ task.setHasBeenVisible(false);
task.getStack().setWindowingMode(WINDOWING_MODE_FULLSCREEN);
- task.hasBeenVisible = true;
+ task.setHasBeenVisible(true);
task.onConfigurationChanged(task.getParent().getConfiguration());
verify(persister, never()).saveTask(same(task), any());
@@ -930,11 +930,11 @@ public class TaskRecordTests extends ActivityTestsBase {
spyOn(persister);
final Task task = getTestTask();
- task.hasBeenVisible = false;
+ task.setHasBeenVisible(false);
task.getDisplayContent().setDisplayWindowingMode(WINDOWING_MODE_FREEFORM);
task.getStack().setWindowingMode(WINDOWING_MODE_PINNED);
- task.hasBeenVisible = true;
+ task.setHasBeenVisible(true);
task.onConfigurationChanged(task.getParent().getConfiguration());
verify(persister, never()).saveTask(same(task), any());
diff --git a/services/voiceinteraction/java/com/android/server/soundtrigger/SoundTriggerDbHelper.java b/services/voiceinteraction/java/com/android/server/soundtrigger/SoundTriggerDbHelper.java
index 99065854445a..71da8dd267db 100644
--- a/services/voiceinteraction/java/com/android/server/soundtrigger/SoundTriggerDbHelper.java
+++ b/services/voiceinteraction/java/com/android/server/soundtrigger/SoundTriggerDbHelper.java
@@ -86,10 +86,11 @@ public class SoundTriggerDbHelper extends SQLiteOpenHelper {
synchronized(this) {
SQLiteDatabase db = getWritableDatabase();
ContentValues values = new ContentValues();
- values.put(GenericSoundModelContract.KEY_MODEL_UUID, soundModel.uuid.toString());
- values.put(GenericSoundModelContract.KEY_VENDOR_UUID, soundModel.vendorUuid.toString());
- values.put(GenericSoundModelContract.KEY_DATA, soundModel.data);
- values.put(GenericSoundModelContract.KEY_MODEL_VERSION, soundModel.version);
+ values.put(GenericSoundModelContract.KEY_MODEL_UUID, soundModel.getUuid().toString());
+ values.put(GenericSoundModelContract.KEY_VENDOR_UUID,
+ soundModel.getVendorUuid().toString());
+ values.put(GenericSoundModelContract.KEY_DATA, soundModel.getData());
+ values.put(GenericSoundModelContract.KEY_MODEL_VERSION, soundModel.getVersion());
try {
return db.insertWithOnConflict(GenericSoundModelContract.TABLE, null, values,
@@ -140,7 +141,7 @@ public class SoundTriggerDbHelper extends SQLiteOpenHelper {
// Delete all sound models for the given keyphrase and specified user.
SQLiteDatabase db = getWritableDatabase();
String soundModelClause = GenericSoundModelContract.KEY_MODEL_UUID
- + "='" + soundModel.uuid.toString() + "'";
+ + "='" + soundModel.getUuid().toString() + "'";
try {
return db.delete(GenericSoundModelContract.TABLE, soundModelClause, null) != 0;
} finally {
diff --git a/services/voiceinteraction/java/com/android/server/soundtrigger/SoundTriggerHelper.java b/services/voiceinteraction/java/com/android/server/soundtrigger/SoundTriggerHelper.java
index 7099c0935ee9..6c0f2b0cd278 100644
--- a/services/voiceinteraction/java/com/android/server/soundtrigger/SoundTriggerHelper.java
+++ b/services/voiceinteraction/java/com/android/server/soundtrigger/SoundTriggerHelper.java
@@ -195,7 +195,7 @@ public class SoundTriggerHelper implements SoundTrigger.StatusListener {
}
// Process existing model first.
- if (model != null && !model.getModelId().equals(soundModel.uuid)) {
+ if (model != null && !model.getModelId().equals(soundModel.getUuid())) {
// The existing model has a different UUID, should be replaced.
int status = cleanUpExistingKeyphraseModelLocked(model);
if (status != STATUS_OK) {
@@ -208,7 +208,7 @@ public class SoundTriggerHelper implements SoundTrigger.StatusListener {
// We need to create a new one: either no previous models existed for given keyphrase id
// or the existing model had a different UUID and was cleaned up.
if (model == null) {
- model = createKeyphraseModelDataLocked(soundModel.uuid, keyphraseId);
+ model = createKeyphraseModelDataLocked(soundModel.getUuid(), keyphraseId);
}
return startRecognition(soundModel, model, callback, recognitionConfig,
@@ -249,7 +249,7 @@ public class SoundTriggerHelper implements SoundTrigger.StatusListener {
return STATUS_ERROR;
}
if (mModule == null) {
- mModule = SoundTrigger.attachModule(mModuleProperties.id, this, null);
+ mModule = SoundTrigger.attachModule(mModuleProperties.getId(), this, null);
if (mModule == null) {
Slog.w(TAG, "startRecognition cannot attach to sound trigger module");
return STATUS_ERROR;
diff --git a/services/voiceinteraction/java/com/android/server/soundtrigger/SoundTriggerService.java b/services/voiceinteraction/java/com/android/server/soundtrigger/SoundTriggerService.java
index 00cb6dc7400d..170bee841e74 100644
--- a/services/voiceinteraction/java/com/android/server/soundtrigger/SoundTriggerService.java
+++ b/services/voiceinteraction/java/com/android/server/soundtrigger/SoundTriggerService.java
@@ -358,7 +358,7 @@ public class SoundTriggerService extends SystemService {
public int loadGenericSoundModel(GenericSoundModel soundModel) {
enforceCallingPermission(Manifest.permission.MANAGE_SOUND_TRIGGER);
if (!isInitialized()) return STATUS_ERROR;
- if (soundModel == null || soundModel.uuid == null) {
+ if (soundModel == null || soundModel.getUuid() == null) {
Slog.e(TAG, "Invalid sound model");
sEventLogger.log(new SoundTriggerLogger.StringEvent(
@@ -367,24 +367,24 @@ public class SoundTriggerService extends SystemService {
return STATUS_ERROR;
}
if (DEBUG) {
- Slog.i(TAG, "loadGenericSoundModel(): id = " + soundModel.uuid);
+ Slog.i(TAG, "loadGenericSoundModel(): id = " + soundModel.getUuid());
}
sEventLogger.log(new SoundTriggerLogger.StringEvent("loadGenericSoundModel(): id = "
- + soundModel.uuid));
+ + soundModel.getUuid()));
synchronized (mLock) {
- SoundModel oldModel = mLoadedModels.get(soundModel.uuid);
+ SoundModel oldModel = mLoadedModels.get(soundModel.getUuid());
// If the model we're loading is actually different than what we had loaded, we
// should unload that other model now. We don't care about return codes since we
// don't know if the other model is loaded.
if (oldModel != null && !oldModel.equals(soundModel)) {
- mSoundTriggerHelper.unloadGenericSoundModel(soundModel.uuid);
+ mSoundTriggerHelper.unloadGenericSoundModel(soundModel.getUuid());
synchronized (mCallbacksLock) {
- mCallbacks.remove(soundModel.uuid);
+ mCallbacks.remove(soundModel.getUuid());
}
}
- mLoadedModels.put(soundModel.uuid, soundModel);
+ mLoadedModels.put(soundModel.getUuid(), soundModel);
}
return STATUS_OK;
}
@@ -393,7 +393,7 @@ public class SoundTriggerService extends SystemService {
public int loadKeyphraseSoundModel(KeyphraseSoundModel soundModel) {
enforceCallingPermission(Manifest.permission.MANAGE_SOUND_TRIGGER);
if (!isInitialized()) return STATUS_ERROR;
- if (soundModel == null || soundModel.uuid == null) {
+ if (soundModel == null || soundModel.getUuid() == null) {
Slog.e(TAG, "Invalid sound model");
sEventLogger.log(new SoundTriggerLogger.StringEvent(
@@ -401,7 +401,7 @@ public class SoundTriggerService extends SystemService {
return STATUS_ERROR;
}
- if (soundModel.keyphrases == null || soundModel.keyphrases.length != 1) {
+ if (soundModel.getKeyphrases() == null || soundModel.getKeyphrases().length != 1) {
Slog.e(TAG, "Only one keyphrase per model is currently supported.");
sEventLogger.log(new SoundTriggerLogger.StringEvent(
@@ -411,24 +411,25 @@ public class SoundTriggerService extends SystemService {
return STATUS_ERROR;
}
if (DEBUG) {
- Slog.i(TAG, "loadKeyphraseSoundModel(): id = " + soundModel.uuid);
+ Slog.i(TAG, "loadKeyphraseSoundModel(): id = " + soundModel.getUuid());
}
sEventLogger.log(new SoundTriggerLogger.StringEvent("loadKeyphraseSoundModel(): id = "
- + soundModel.uuid));
+ + soundModel.getUuid()));
synchronized (mLock) {
- SoundModel oldModel = mLoadedModels.get(soundModel.uuid);
+ SoundModel oldModel = mLoadedModels.get(soundModel.getUuid());
// If the model we're loading is actually different than what we had loaded, we
// should unload that other model now. We don't care about return codes since we
// don't know if the other model is loaded.
if (oldModel != null && !oldModel.equals(soundModel)) {
- mSoundTriggerHelper.unloadKeyphraseSoundModel(soundModel.keyphrases[0].id);
+ mSoundTriggerHelper.unloadKeyphraseSoundModel(
+ soundModel.getKeyphrases()[0].getId());
synchronized (mCallbacksLock) {
- mCallbacks.remove(soundModel.uuid);
+ mCallbacks.remove(soundModel.getUuid());
}
}
- mLoadedModels.put(soundModel.uuid, soundModel);
+ mLoadedModels.put(soundModel.getUuid(), soundModel);
}
return STATUS_OK;
}
@@ -478,9 +479,9 @@ public class SoundTriggerService extends SystemService {
return STATUS_ERROR;
}
int ret;
- switch (soundModel.type) {
+ switch (soundModel.getType()) {
case SoundModel.TYPE_GENERIC_SOUND:
- ret = mSoundTriggerHelper.startGenericRecognition(soundModel.uuid,
+ ret = mSoundTriggerHelper.startGenericRecognition(soundModel.getUuid(),
(GenericSoundModel) soundModel, callback, config);
break;
default:
@@ -545,9 +546,10 @@ public class SoundTriggerService extends SystemService {
return STATUS_ERROR;
}
int ret;
- switch (soundModel.type) {
+ switch (soundModel.getType()) {
case SoundModel.TYPE_GENERIC_SOUND:
- ret = mSoundTriggerHelper.stopGenericRecognition(soundModel.uuid, callback);
+ ret = mSoundTriggerHelper.stopGenericRecognition(
+ soundModel.getUuid(), callback);
break;
default:
Slog.e(TAG, "Unknown model type");
@@ -597,13 +599,13 @@ public class SoundTriggerService extends SystemService {
return STATUS_ERROR;
}
int ret;
- switch (soundModel.type) {
+ switch (soundModel.getType()) {
case SoundModel.TYPE_KEYPHRASE:
ret = mSoundTriggerHelper.unloadKeyphraseSoundModel(
- ((KeyphraseSoundModel)soundModel).keyphrases[0].id);
+ ((KeyphraseSoundModel) soundModel).getKeyphrases()[0].getId());
break;
case SoundModel.TYPE_GENERIC_SOUND:
- ret = mSoundTriggerHelper.unloadGenericSoundModel(soundModel.uuid);
+ ret = mSoundTriggerHelper.unloadGenericSoundModel(soundModel.getUuid());
break;
default:
Slog.e(TAG, "Unknown model type");
@@ -661,16 +663,16 @@ public class SoundTriggerService extends SystemService {
return ret;
}
- switch (soundModel.type) {
+ switch (soundModel.getType()) {
case SoundModel.TYPE_GENERIC_SOUND:
- ret = mSoundTriggerHelper.getGenericModelState(soundModel.uuid);
+ ret = mSoundTriggerHelper.getGenericModelState(soundModel.getUuid());
break;
default:
// SoundModel.TYPE_KEYPHRASE is not supported to increase privacy.
- Slog.e(TAG, "Unsupported model type, " + soundModel.type);
+ Slog.e(TAG, "Unsupported model type, " + soundModel.getType());
sEventLogger.log(new SoundTriggerLogger.StringEvent(
"getModelState(): Unsupported model type, "
- + soundModel.type));
+ + soundModel.getType()));
break;
}
@@ -723,7 +725,7 @@ public class SoundTriggerService extends SystemService {
return STATUS_BAD_VALUE;
}
- return mSoundTriggerHelper.setParameter(soundModel.uuid, modelParam, value);
+ return mSoundTriggerHelper.setParameter(soundModel.getUuid(), modelParam, value);
}
}
@@ -755,7 +757,7 @@ public class SoundTriggerService extends SystemService {
throw new IllegalArgumentException("sound model is not loaded");
}
- return mSoundTriggerHelper.getParameter(soundModel.uuid, modelParam);
+ return mSoundTriggerHelper.getParameter(soundModel.getUuid(), modelParam);
}
}
@@ -786,7 +788,7 @@ public class SoundTriggerService extends SystemService {
return null;
}
- return mSoundTriggerHelper.queryParameter(soundModel.uuid, modelParam);
+ return mSoundTriggerHelper.queryParameter(soundModel.getUuid(), modelParam);
}
}
}
diff --git a/services/voiceinteraction/java/com/android/server/voiceinteraction/DatabaseHelper.java b/services/voiceinteraction/java/com/android/server/voiceinteraction/DatabaseHelper.java
index be0987d745ba..aaf7a9eacce6 100644
--- a/services/voiceinteraction/java/com/android/server/voiceinteraction/DatabaseHelper.java
+++ b/services/voiceinteraction/java/com/android/server/voiceinteraction/DatabaseHelper.java
@@ -162,23 +162,26 @@ public class DatabaseHelper extends SQLiteOpenHelper {
synchronized(this) {
SQLiteDatabase db = getWritableDatabase();
ContentValues values = new ContentValues();
- values.put(SoundModelContract.KEY_MODEL_UUID, soundModel.uuid.toString());
- if (soundModel.vendorUuid != null) {
- values.put(SoundModelContract.KEY_VENDOR_UUID, soundModel.vendorUuid.toString());
+ values.put(SoundModelContract.KEY_MODEL_UUID, soundModel.getUuid().toString());
+ if (soundModel.getVendorUuid() != null) {
+ values.put(SoundModelContract.KEY_VENDOR_UUID,
+ soundModel.getVendorUuid().toString());
}
values.put(SoundModelContract.KEY_TYPE, SoundTrigger.SoundModel.TYPE_KEYPHRASE);
- values.put(SoundModelContract.KEY_DATA, soundModel.data);
- values.put(SoundModelContract.KEY_MODEL_VERSION, soundModel.version);
+ values.put(SoundModelContract.KEY_DATA, soundModel.getData());
+ values.put(SoundModelContract.KEY_MODEL_VERSION, soundModel.getVersion());
- if (soundModel.keyphrases != null && soundModel.keyphrases.length == 1) {
- values.put(SoundModelContract.KEY_KEYPHRASE_ID, soundModel.keyphrases[0].id);
+ if (soundModel.getKeyphrases() != null && soundModel.getKeyphrases().length == 1) {
+ values.put(SoundModelContract.KEY_KEYPHRASE_ID,
+ soundModel.getKeyphrases()[0].getId());
values.put(SoundModelContract.KEY_RECOGNITION_MODES,
- soundModel.keyphrases[0].recognitionModes);
+ soundModel.getKeyphrases()[0].getRecognitionModes());
values.put(SoundModelContract.KEY_USERS,
- getCommaSeparatedString(soundModel.keyphrases[0].users));
+ getCommaSeparatedString(soundModel.getKeyphrases()[0].getUsers()));
values.put(SoundModelContract.KEY_LOCALE,
- soundModel.keyphrases[0].locale.toLanguageTag());
- values.put(SoundModelContract.KEY_HINT_TEXT, soundModel.keyphrases[0].text);
+ soundModel.getKeyphrases()[0].getLocale().toLanguageTag());
+ values.put(SoundModelContract.KEY_HINT_TEXT,
+ soundModel.getKeyphrases()[0].getText());
try {
return db.insertWithOnConflict(SoundModelContract.TABLE, null, values,
SQLiteDatabase.CONFLICT_REPLACE) != -1;
@@ -206,7 +209,7 @@ public class DatabaseHelper extends SQLiteOpenHelper {
// Delete all sound models for the given keyphrase and specified user.
SQLiteDatabase db = getWritableDatabase();
String soundModelClause = SoundModelContract.KEY_MODEL_UUID
- + "='" + soundModel.uuid.toString() + "'";
+ + "='" + soundModel.getUuid().toString() + "'";
try {
return db.delete(SoundModelContract.TABLE, soundModelClause, null) != 0;
} finally {
diff --git a/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerService.java b/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerService.java
index 18d581964f2a..ef282ba110c5 100644
--- a/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerService.java
+++ b/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerService.java
@@ -1045,12 +1045,12 @@ public class VoiceInteractionManagerService extends SystemService {
return null;
}
- for (SoundTrigger.Keyphrase phrase : model.keyphrases) {
- if (keyphrase.equals(phrase.text)) {
+ for (SoundTrigger.Keyphrase phrase : model.getKeyphrases()) {
+ if (keyphrase.equals(phrase.getText())) {
ArraySet<Locale> locales = new ArraySet<>();
- locales.add(phrase.locale);
- return new KeyphraseMetadata(phrase.id, phrase.text, locales,
- phrase.recognitionModes);
+ locales.add(phrase.getLocale());
+ return new KeyphraseMetadata(phrase.getId(), phrase.getText(), locales,
+ phrase.getRecognitionModes());
}
}
} finally {
@@ -1093,8 +1093,8 @@ public class VoiceInteractionManagerService extends SystemService {
KeyphraseSoundModel soundModel =
mDbHelper.getKeyphraseSoundModel(keyphraseId, callingUid, bcp47Locale);
if (soundModel == null
- || soundModel.uuid == null
- || soundModel.keyphrases == null) {
+ || soundModel.getUuid() == null
+ || soundModel.getKeyphrases() == null) {
Slog.w(TAG, "No matching sound model found in startRecognition");
return SoundTriggerInternal.STATUS_ERROR;
} else {
diff --git a/startop/iorap/src/com/google/android/startop/iorap/IorapForwardingService.java b/startop/iorap/src/com/google/android/startop/iorap/IorapForwardingService.java
index badff7bc2f8c..d5851d85345f 100644
--- a/startop/iorap/src/com/google/android/startop/iorap/IorapForwardingService.java
+++ b/startop/iorap/src/com/google/android/startop/iorap/IorapForwardingService.java
@@ -279,6 +279,8 @@ public class IorapForwardingService extends SystemService {
(IIorap remote) -> remote.setTaskListener(new RemoteTaskListener()) );
registerInProcessListenersLocked();
+ Log.i(TAG, "Connected to iorapd native service.");
+
return true;
}
diff --git a/telecomm/java/android/telecom/TelecomManager.java b/telecomm/java/android/telecom/TelecomManager.java
index e3baa0a3cb3d..c993cfad1d05 100644
--- a/telecomm/java/android/telecom/TelecomManager.java
+++ b/telecomm/java/android/telecom/TelecomManager.java
@@ -193,13 +193,13 @@ public class TelecomManager {
/**
* Broadcast intent action indicating that the current default call screening app has changed.
- *
- * The string extra {@link #EXTRA_DEFAULT_CALL_SCREENING_APP_COMPONENT_NAME} will contain the
- * name of the Component of the previous or the new call screening app.
- *
- * The boolean extra {@link #EXTRA_IS_DEFAULT_CALL_SCREENING_APP} will indicate the component
- * name in the String extra {@link #EXTRA_DEFAULT_CALL_SCREENING_APP_COMPONENT_NAME} is default
- * call screening app or not.
+ * <p>
+ * Note: This intent is NEVER actually broadcast and will be deprecated in the future.
+ * <p>
+ * An app that want to know if it holds the
+ * {@link android.app.role.RoleManager#ROLE_CALL_SCREENING} role can use
+ * {@link android.app.role.RoleManager#isRoleHeld(String)} to confirm if it holds the role or
+ * not.
*/
public static final String ACTION_DEFAULT_CALL_SCREENING_APP_CHANGED =
"android.telecom.action.DEFAULT_CALL_SCREENING_APP_CHANGED";
@@ -207,6 +207,8 @@ public class TelecomManager {
/**
* Extra value used with {@link #ACTION_DEFAULT_CALL_SCREENING_APP_CHANGED} broadcast to
* indicate the ComponentName of the call screening app which has changed.
+ * <p>
+ * Note: This extra is NOT used and will be deprecated in the future.
*/
public static final String EXTRA_DEFAULT_CALL_SCREENING_APP_COMPONENT_NAME =
"android.telecom.extra.DEFAULT_CALL_SCREENING_APP_COMPONENT_NAME";
@@ -214,6 +216,8 @@ public class TelecomManager {
/**
* Extra value used with {@link #ACTION_DEFAULT_CALL_SCREENING_APP_CHANGED} broadcast to
* indicate whether an app is the default call screening app.
+ * <p>
+ * Note: This extra is NOT used and will be deprecated in the future.
*/
public static final String EXTRA_IS_DEFAULT_CALL_SCREENING_APP =
"android.telecom.extra.IS_DEFAULT_CALL_SCREENING_APP";
diff --git a/telephony/api/system-current.txt b/telephony/api/system-current.txt
index afb75bb22bee..6273b487b68f 100644
--- a/telephony/api/system-current.txt
+++ b/telephony/api/system-current.txt
@@ -816,9 +816,9 @@ package android.telephony {
method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setVoiceActivationState(int);
method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void shutdownAllRadios();
method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public boolean supplyPin(String);
- method @Deprecated @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public int[] supplyPinReportResult(String);
+ method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public int[] supplyPinReportResult(String);
method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public boolean supplyPuk(String, String);
- method @Deprecated @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public int[] supplyPukReportResult(String, String);
+ method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public int[] supplyPukReportResult(String, String);
method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public boolean switchSlots(int[]);
method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void toggleRadioOnOff();
method @RequiresPermission(android.Manifest.permission.READ_ACTIVE_EMERGENCY_SESSION) public void updateOtaEmergencyNumberDbFilePath(@NonNull android.os.ParcelFileDescriptor);
diff --git a/telephony/common/com/android/internal/telephony/TelephonyPermissions.java b/telephony/common/com/android/internal/telephony/TelephonyPermissions.java
index 7e02966779a2..1a38a42873b7 100644
--- a/telephony/common/com/android/internal/telephony/TelephonyPermissions.java
+++ b/telephony/common/com/android/internal/telephony/TelephonyPermissions.java
@@ -361,7 +361,8 @@ public final class TelephonyPermissions {
TelephonyCommonStatsLog.write(TelephonyCommonStatsLog.DEVICE_IDENTIFIER_ACCESS_DENIED,
callingPackage, message, /* isPreinstalled= */ false, false);
}
- Log.w(LOG_TAG, "reportAccessDeniedToReadIdentifiers:" + callingPackage + ":" + message);
+ Log.w(LOG_TAG, "reportAccessDeniedToReadIdentifiers:" + callingPackage + ":" + message + ":"
+ + subId);
// if the target SDK is pre-Q then check if the calling package would have previously
// had access to device identifiers.
if (callingPackageInfo != null && (
diff --git a/telephony/java/android/telephony/SignalStrength.java b/telephony/java/android/telephony/SignalStrength.java
index 283e666f7ab2..2bb4eb1538bd 100644
--- a/telephony/java/android/telephony/SignalStrength.java
+++ b/telephony/java/android/telephony/SignalStrength.java
@@ -188,12 +188,12 @@ public class SignalStrength implements Parcelable {
private CellSignalStrength getPrimary() {
// This behavior is intended to replicate the legacy behavior of getLevel() by prioritizing
// newer faster RATs for default/for display purposes.
+ if (mNr.isValid()) return mNr;
if (mLte.isValid()) return mLte;
if (mCdma.isValid()) return mCdma;
if (mTdscdma.isValid()) return mTdscdma;
if (mWcdma.isValid()) return mWcdma;
if (mGsm.isValid()) return mGsm;
- if (mNr.isValid()) return mNr;
return mLte;
}
diff --git a/telephony/java/android/telephony/TelephonyManager.java b/telephony/java/android/telephony/TelephonyManager.java
index 5a7b852eeb76..4e5be5c453b7 100644
--- a/telephony/java/android/telephony/TelephonyManager.java
+++ b/telephony/java/android/telephony/TelephonyManager.java
@@ -5577,6 +5577,10 @@ public class TelephonyManager {
* call {@link android.os.Binder#clearCallingIdentity()} before calling this method. A
* {@link SecurityException} will be thrown otherwise.
*
+ * This API should be used sparingly -- large numbers of listeners will cause system
+ * instability. If a process has registered too many listeners without unregistering them, it
+ * may encounter an {@link IllegalStateException} when trying to register more listeners.
+ *
* @param listener The {@link PhoneStateListener} object to register
* (or unregister)
* @param events The telephony state(s) of interest to the listener,
@@ -8679,13 +8683,9 @@ public class TelephonyManager {
return false;
}
- /**
- * @deprecated use {@link #supplyPinReportPinResult(String pin)} instead.
- *
- * @hide */
+ /** @hide */
@SystemApi
@RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE)
- @Deprecated
public int[] supplyPinReportResult(String pin) {
try {
ITelephony telephony = getITelephony();
@@ -8697,13 +8697,9 @@ public class TelephonyManager {
return new int[0];
}
- /**
- * @deprecated use {@link #supplyPukReportPinResult(String puk, String pin)} instead.
- *
- * @hide */
+ /** @hide */
@SystemApi
@RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE)
- @Deprecated
public int[] supplyPukReportResult(String puk, String pin) {
try {
ITelephony telephony = getITelephony();
@@ -12268,6 +12264,17 @@ public class TelephonyManager {
"android.telephony.extra.NETWORK_COUNTRY";
/**
+ * The extra used with an {@link #ACTION_NETWORK_COUNTRY_CHANGED} to specify the
+ * last known the country code in ISO-3166-1 alpha-2 format.
+ * <p class="note">
+ * Retrieve with {@link android.content.Intent#getStringExtra(String)}.
+ *
+ * @hide
+ */
+ public static final String EXTRA_LAST_KNOWN_NETWORK_COUNTRY =
+ "android.telephony.extra.LAST_KNOWN_NETWORK_COUNTRY";
+
+ /**
* Indicate if the user is allowed to use multiple SIM cards at the same time to register
* on the network (e.g. Dual Standby or Dual Active) when the device supports it, or if the
* usage is restricted. This API is used to prevent usage of multiple SIM card, based on
diff --git a/telephony/java/com/android/internal/telephony/DctConstants.java b/telephony/java/com/android/internal/telephony/DctConstants.java
index 3e1d72c7eeb8..2b1d9e58c4d5 100644
--- a/telephony/java/com/android/internal/telephony/DctConstants.java
+++ b/telephony/java/com/android/internal/telephony/DctConstants.java
@@ -74,7 +74,6 @@ public class DctConstants {
public static final int BASE = Protocol.BASE_DATA_CONNECTION_TRACKER;
public static final int EVENT_DATA_SETUP_COMPLETE = BASE + 0;
public static final int EVENT_RADIO_AVAILABLE = BASE + 1;
- public static final int EVENT_RECORDS_LOADED = BASE + 2;
public static final int EVENT_TRY_SETUP_DATA = BASE + 3;
public static final int EVENT_RADIO_OFF_OR_NOT_AVAILABLE = BASE + 6;
public static final int EVENT_VOICE_CALL_STARTED = BASE + 7;
@@ -94,7 +93,6 @@ public class DctConstants {
public static final int EVENT_CLEAN_UP_CONNECTION = BASE + 24;
public static final int EVENT_RESTART_RADIO = BASE + 26;
public static final int EVENT_CLEAN_UP_ALL_CONNECTIONS = BASE + 29;
- public static final int EVENT_ICC_CHANGED = BASE + 33;
public static final int EVENT_DATA_SETUP_COMPLETE_ERROR = BASE + 35;
public static final int CMD_SET_ENABLE_FAIL_FAST_MOBILE_DATA = BASE + 36;
public static final int CMD_ENABLE_MOBILE_PROVISIONING = BASE + 37;
@@ -114,7 +112,7 @@ public class DctConstants {
public static final int EVENT_SERVICE_STATE_CHANGED = BASE + 52;
public static final int EVENT_5G_TIMER_HYSTERESIS = BASE + 53;
public static final int EVENT_5G_TIMER_WATCHDOG = BASE + 54;
- public static final int EVENT_UPDATE_CARRIER_CONFIGS = BASE + 55;
+ public static final int EVENT_CARRIER_CONFIG_CHANGED = BASE + 55;
/***** Constants *****/
diff --git a/test-mock/src/android/test/mock/MockContext.java b/test-mock/src/android/test/mock/MockContext.java
index 784ee85fea34..cf3b03cae72e 100644
--- a/test-mock/src/android/test/mock/MockContext.java
+++ b/test-mock/src/android/test/mock/MockContext.java
@@ -928,4 +928,10 @@ public class MockContext extends Context {
public Handler getMainThreadHandler() {
throw new UnsupportedOperationException();
}
+
+ /** {@hide} */
+ @Override
+ public boolean isUiContext() {
+ throw new UnsupportedOperationException();
+ }
}
diff --git a/tests/AppLaunch/src/com/android/tests/applaunch/AppLaunch.java b/tests/AppLaunch/src/com/android/tests/applaunch/AppLaunch.java
index 0ad30391d1a8..42cee7cc5f1e 100644
--- a/tests/AppLaunch/src/com/android/tests/applaunch/AppLaunch.java
+++ b/tests/AppLaunch/src/com/android/tests/applaunch/AppLaunch.java
@@ -41,10 +41,14 @@ import java.io.BufferedWriter;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
+import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
+import java.time.format.DateTimeFormatter;
+import java.time.ZonedDateTime;
+import java.time.ZoneOffset;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
@@ -738,6 +742,41 @@ public class AppLaunch extends InstrumentationTestCase {
return total.contains("root");
}
+ private void stopIorapd() {
+ getInstrumentation().getUiAutomation()
+ .executeShellCommand("stop iorapd");
+ sleep(100); // give it extra time to fully stop.
+ }
+
+ private void startIorapd() {
+ String logcatTimeNow = getTimeNowForLogcat();
+ Log.v(TAG, "startIorapd, logcat time: " + logcatTimeNow);
+
+ getInstrumentation().getUiAutomation()
+ .executeShellCommand("start iorapd");
+
+ int maxAttempts = 100;
+ int attempt = 0;
+ do {
+ // Ensure that IorapForwardingService fully reconnects to iorapd before proceeding.
+ String needle = "Connected to iorapd native service";
+ String logcatLines = getLogcatSinceTime(logcatTimeNow);
+
+ if (logcatLines.contains(needle)) {
+ break;
+ }
+
+ sleep(1000);
+ attempt++;
+ } while (attempt < maxAttempts);
+
+ if (attempt == maxAttempts) {
+ Log.e(TAG, "Timed out after waiting for iorapd to start");
+ }
+ // Wait a little bit longer for iorapd to settle.
+ sleep(1000);
+ }
+
// Delete all db rows and files associated with a package in iorapd.
// Effectively deletes any raw or compiled trace files, unoptimizing the package in iorap.
private void purgeIorapPackage(String packageName) {
@@ -749,15 +788,65 @@ public class AppLaunch extends InstrumentationTestCase {
throw new AssertionError(e);
}
- getInstrumentation().getUiAutomation()
- .executeShellCommand("stop iorapd");
- sleep(100); // give iorapd enough time to stop.
+ Log.v(TAG, "Purge iorap package: " + packageName);
+ stopIorapd();
getInstrumentation().getUiAutomation()
.executeShellCommand(String.format(IORAP_MAINTENANCE_CMD, packageName));
Log.v(TAG, "Executed: " + String.format(IORAP_MAINTENANCE_CMD, packageName));
- getInstrumentation().getUiAutomation()
- .executeShellCommand("start iorapd");
- sleep(2000); // give iorapd enough time to start up.
+ startIorapd();
+ }
+
+ String executeShellCommandWithTempFile(String cmd) {
+ Log.v(TAG, "executeShellCommandWithTempFile, cmd: " + cmd);
+ try {
+ //File outputDir =
+ // InstrumentationRegistry.getInstrumentation().getContext().getCacheDir();
+ File outputFile = File.createTempFile("exec_shell_command", ".sh");
+
+ try {
+ outputFile.setWritable(true);
+ outputFile.setExecutable(true, /*ownersOnly*/false);
+
+ String scriptPath = outputFile.toString();
+
+ // If this works correctly, the next log-line will print 'Success'.
+ try (BufferedWriter writer = new BufferedWriter(new FileWriter(scriptPath))) {
+ writer.write(cmd);
+ }
+
+ String resultString = "";
+ try (ParcelFileDescriptor result = getInstrumentation().getUiAutomation().
+ executeShellCommand(scriptPath);
+ BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(
+ new FileInputStream(result.getFileDescriptor())))) {
+ String line;
+ while ((line = bufferedReader.readLine()) != null) {
+ resultString += line + "\n";
+ }
+ }
+
+ return resultString;
+ } finally {
+ outputFile.delete();
+ }
+ } catch (IOException e) {
+ throw new AssertionError("Failed to execute shell command: " + cmd, e);
+ }
+ }
+
+ // Get the 'now' timestamp usable with $(adb logcat -v utc -T "time string")
+ String getTimeNowForLogcat() {
+ ZonedDateTime utc = ZonedDateTime.now(ZoneOffset.UTC);
+
+ // YYYY-MM-DD hh:mm:ss.mmm
+ return utc.format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss.SSS"));
+ }
+
+ String getLogcatSinceTime(String logcatTime) {
+ // The time has spaces in it but must be passed as a single arg.
+ // Therefore use a temp script file.
+ return executeShellCommandWithTempFile(
+ String.format("logcat -d -v threadtime -v utc -T '%s'", logcatTime));
}
/**
@@ -784,15 +873,12 @@ public class AppLaunch extends InstrumentationTestCase {
throw new AssertionError(e);
}
- getInstrumentation().getUiAutomation()
- .executeShellCommand("stop iorapd");
+ stopIorapd();
getInstrumentation().getUiAutomation()
.executeShellCommand(String.format("setprop iorapd.perfetto.enable %b", enable));
getInstrumentation().getUiAutomation()
.executeShellCommand(String.format("setprop iorapd.readahead.enable %b", enable));
- getInstrumentation().getUiAutomation()
- .executeShellCommand("start iorapd");
- sleep(3000); // give enough time for iorapd to start back up.
+ startIorapd();
if (enable) {
mIorapStatus = IorapStatus.ENABLED;
diff --git a/tests/PackageWatchdog/src/com/android/server/PackageWatchdogTest.java b/tests/PackageWatchdog/src/com/android/server/PackageWatchdogTest.java
index 2957192ecf0f..d011dbbbe5db 100644
--- a/tests/PackageWatchdog/src/com/android/server/PackageWatchdogTest.java
+++ b/tests/PackageWatchdog/src/com/android/server/PackageWatchdogTest.java
@@ -1123,6 +1123,28 @@ public class PackageWatchdogTest {
assertThat(testController.getSyncRequests()).isEqualTo(expectedSyncRequests);
}
+ /**
+ * Ensure that the failure history of a package is preserved when making duplicate calls to
+ * observe the package.
+ */
+ @Test
+ public void testFailureHistoryIsPreserved() {
+ PackageWatchdog watchdog = createWatchdog();
+ TestObserver observer = new TestObserver(OBSERVER_NAME_1);
+ watchdog.startObservingHealth(observer, List.of(APP_A), SHORT_DURATION);
+ for (int i = 0; i < PackageWatchdog.DEFAULT_TRIGGER_FAILURE_COUNT - 1; i++) {
+ watchdog.onPackageFailure(List.of(new VersionedPackage(APP_A, VERSION_CODE)),
+ PackageWatchdog.FAILURE_REASON_UNKNOWN);
+ }
+ mTestLooper.dispatchAll();
+ assertThat(observer.mMitigatedPackages).isEmpty();
+ watchdog.startObservingHealth(observer, List.of(APP_A), LONG_DURATION);
+ watchdog.onPackageFailure(List.of(new VersionedPackage(APP_A, VERSION_CODE)),
+ PackageWatchdog.FAILURE_REASON_UNKNOWN);
+ mTestLooper.dispatchAll();
+ assertThat(observer.mMitigatedPackages).isEqualTo(List.of(APP_A));
+ }
+
private void adoptShellPermissions(String... permissions) {
InstrumentationRegistry
.getInstrumentation()
diff --git a/tests/SoundTriggerTestApp/src/com/android/test/soundtrigger/SoundTriggerTestService.java b/tests/SoundTriggerTestApp/src/com/android/test/soundtrigger/SoundTriggerTestService.java
index b185a26bb972..9324ba0b8b72 100644
--- a/tests/SoundTriggerTestApp/src/com/android/test/soundtrigger/SoundTriggerTestService.java
+++ b/tests/SoundTriggerTestApp/src/com/android/test/soundtrigger/SoundTriggerTestService.java
@@ -250,10 +250,12 @@ public class SoundTriggerTestService extends Service {
boolean status = mSoundTriggerUtil.addOrUpdateSoundModel(soundModel);
if (status) {
- postToast("Successfully loaded " + modelInfo.name + ", UUID=" + soundModel.uuid);
+ postToast("Successfully loaded " + modelInfo.name + ", UUID="
+ + soundModel.getUuid());
setModelState(modelInfo, "Loaded");
} else {
- postErrorToast("Failed to load " + modelInfo.name + ", UUID=" + soundModel.uuid + "!");
+ postErrorToast("Failed to load " + modelInfo.name + ", UUID="
+ + soundModel.getUuid() + "!");
setModelState(modelInfo, "Failed to load");
}
}
@@ -275,11 +277,12 @@ public class SoundTriggerTestService extends Service {
modelInfo.detector = null;
boolean status = mSoundTriggerUtil.deleteSoundModel(modelUuid);
if (status) {
- postToast("Successfully unloaded " + modelInfo.name + ", UUID=" + soundModel.uuid);
+ postToast("Successfully unloaded " + modelInfo.name + ", UUID="
+ + soundModel.getUuid());
setModelState(modelInfo, "Unloaded");
} else {
postErrorToast("Failed to unload " +
- modelInfo.name + ", UUID=" + soundModel.uuid + "!");
+ modelInfo.name + ", UUID=" + soundModel.getUuid() + "!");
setModelState(modelInfo, "Failed to unload");
}
}
@@ -299,7 +302,8 @@ public class SoundTriggerTestService extends Service {
GenericSoundModel updated = createNewSoundModel(modelInfo);
boolean status = mSoundTriggerUtil.addOrUpdateSoundModel(updated);
if (status) {
- postToast("Successfully reloaded " + modelInfo.name + ", UUID=" + modelInfo.modelUuid);
+ postToast("Successfully reloaded " + modelInfo.name + ", UUID="
+ + modelInfo.modelUuid);
setModelState(modelInfo, "Reloaded");
} else {
postErrorToast("Failed to reload "
@@ -321,7 +325,8 @@ public class SoundTriggerTestService extends Service {
modelUuid, new DetectorCallback(modelInfo));
}
- postMessage("Starting recognition for " + modelInfo.name + ", UUID=" + modelInfo.modelUuid);
+ postMessage("Starting recognition for " + modelInfo.name + ", UUID="
+ + modelInfo.modelUuid);
if (modelInfo.detector.startRecognition(modelInfo.captureAudio ?
SoundTriggerDetector.RECOGNITION_FLAG_CAPTURE_TRIGGER_AUDIO :
SoundTriggerDetector.RECOGNITION_FLAG_ALLOW_MULTIPLE_TRIGGERS)) {
@@ -495,7 +500,8 @@ public class SoundTriggerTestService extends Service {
if (properties.containsKey("dataFile")) {
File modelDataFile = new File(
- getFilesDir().getPath() + "/" + properties.getProperty("dataFile"));
+ getFilesDir().getPath() + "/"
+ + properties.getProperty("dataFile"));
modelInfo.modelData = new byte[(int) modelDataFile.length()];
FileInputStream input = new FileInputStream(modelDataFile);
input.read(modelInfo.modelData, 0, modelInfo.modelData.length);
@@ -602,12 +608,14 @@ public class SoundTriggerTestService extends Service {
FileOutputStream fos = null;
try {
fos = new FileOutputStream( new File(
- getFilesDir() + File.separator + mModelInfo.name.replace(' ', '_') +
- "_capture_" + format.getChannelCount() + "ch_" +
- format.getSampleRate() + "hz_" + encoding + ".pcm"));
+ getFilesDir() + File.separator
+ + mModelInfo.name.replace(' ', '_')
+ + "_capture_" + format.getChannelCount() + "ch_"
+ + format.getSampleRate() + "hz_" + encoding + ".pcm"));
} catch (IOException e) {
Log.e(TAG, "Failed to open output for saving PCM data", e);
- postErrorToast("Failed to open output for saving PCM data: " + e.getMessage());
+ postErrorToast("Failed to open output for saving PCM data: "
+ + e.getMessage());
}
// Inform the user we're recording.
@@ -690,7 +698,8 @@ public class SoundTriggerTestService extends Service {
AudioFormat format = event.getCaptureAudioFormat();
result = result + "AudioFormat: " + ((format == null) ? "null" : format.toString());
byte[] triggerAudio = event.getTriggerAudio();
- result = result + ", TriggerAudio: " + (triggerAudio == null ? "null" : triggerAudio.length);
+ result = result + ", TriggerAudio: "
+ + (triggerAudio == null ? "null" : triggerAudio.length);
byte[] data = event.getData();
result = result + ", Data: " + (data == null ? "null" : data.length);
if (data != null) {
diff --git a/tests/SoundTriggerTests/src/android/hardware/soundtrigger/SoundTriggerTest.java b/tests/SoundTriggerTests/src/android/hardware/soundtrigger/SoundTriggerTest.java
index c900eaedbdae..e36f398c53ea 100644
--- a/tests/SoundTriggerTests/src/android/hardware/soundtrigger/SoundTriggerTest.java
+++ b/tests/SoundTriggerTests/src/android/hardware/soundtrigger/SoundTriggerTest.java
@@ -16,7 +16,6 @@
package android.hardware.soundtrigger;
-import android.hardware.soundtrigger.SoundTrigger;
import android.hardware.soundtrigger.SoundTrigger.ConfidenceLevel;
import android.hardware.soundtrigger.SoundTrigger.Keyphrase;
import android.hardware.soundtrigger.SoundTrigger.KeyphraseRecognitionEvent;
@@ -51,10 +50,10 @@ public class SoundTriggerTest extends InstrumentationTestCase {
Keyphrase unparceled = Keyphrase.CREATOR.createFromParcel(parcel);
// Verify that they are the same
- assertEquals(keyphrase.id, unparceled.id);
- assertNull(unparceled.users);
- assertEquals(keyphrase.locale, unparceled.locale);
- assertEquals(keyphrase.text, unparceled.text);
+ assertEquals(keyphrase.getId(), unparceled.getId());
+ assertNull(unparceled.getUsers());
+ assertEquals(keyphrase.getLocale(), unparceled.getLocale());
+ assertEquals(keyphrase.getText(), unparceled.getText());
}
@SmallTest
@@ -71,10 +70,10 @@ public class SoundTriggerTest extends InstrumentationTestCase {
Keyphrase unparceled = Keyphrase.CREATOR.createFromParcel(parcel);
// Verify that they are the same
- assertEquals(keyphrase.id, unparceled.id);
- assertTrue(Arrays.equals(keyphrase.users, unparceled.users));
- assertEquals(keyphrase.locale, unparceled.locale);
- assertEquals(keyphrase.text, unparceled.text);
+ assertEquals(keyphrase.getId(), unparceled.getId());
+ assertTrue(Arrays.equals(keyphrase.getUsers(), unparceled.getUsers()));
+ assertEquals(keyphrase.getLocale(), unparceled.getLocale());
+ assertEquals(keyphrase.getText(), unparceled.getText());
}
@SmallTest
@@ -91,10 +90,10 @@ public class SoundTriggerTest extends InstrumentationTestCase {
Keyphrase unparceled = Keyphrase.CREATOR.createFromParcel(parcel);
// Verify that they are the same
- assertEquals(keyphrase.id, unparceled.id);
- assertTrue(Arrays.equals(keyphrase.users, unparceled.users));
- assertEquals(keyphrase.locale, unparceled.locale);
- assertEquals(keyphrase.text, unparceled.text);
+ assertEquals(keyphrase.getId(), unparceled.getId());
+ assertTrue(Arrays.equals(keyphrase.getUsers(), unparceled.getUsers()));
+ assertEquals(keyphrase.getLocale(), unparceled.getLocale());
+ assertEquals(keyphrase.getText(), unparceled.getText());
}
@SmallTest
@@ -116,10 +115,10 @@ public class SoundTriggerTest extends InstrumentationTestCase {
KeyphraseSoundModel unparceled = KeyphraseSoundModel.CREATOR.createFromParcel(parcel);
// Verify that they are the same
- assertEquals(ksm.uuid, unparceled.uuid);
- assertNull(unparceled.data);
- assertEquals(ksm.type, unparceled.type);
- assertTrue(Arrays.equals(keyphrases, unparceled.keyphrases));
+ assertEquals(ksm.getUuid(), unparceled.getUuid());
+ assertNull(unparceled.getData());
+ assertEquals(ksm.getType(), unparceled.getType());
+ assertTrue(Arrays.equals(keyphrases, unparceled.getKeyphrases()));
}
@SmallTest
@@ -141,10 +140,10 @@ public class SoundTriggerTest extends InstrumentationTestCase {
KeyphraseSoundModel unparceled = KeyphraseSoundModel.CREATOR.createFromParcel(parcel);
// Verify that they are the same
- assertEquals(ksm.uuid, unparceled.uuid);
- assertEquals(ksm.type, unparceled.type);
- assertTrue(Arrays.equals(ksm.keyphrases, unparceled.keyphrases));
- assertTrue(Arrays.equals(ksm.data, unparceled.data));
+ assertEquals(ksm.getUuid(), unparceled.getUuid());
+ assertEquals(ksm.getType(), unparceled.getType());
+ assertTrue(Arrays.equals(ksm.getKeyphrases(), unparceled.getKeyphrases()));
+ assertTrue(Arrays.equals(ksm.getData(), unparceled.getData()));
}
@SmallTest
@@ -163,10 +162,10 @@ public class SoundTriggerTest extends InstrumentationTestCase {
KeyphraseSoundModel unparceled = KeyphraseSoundModel.CREATOR.createFromParcel(parcel);
// Verify that they are the same
- assertEquals(ksm.uuid, unparceled.uuid);
- assertEquals(ksm.type, unparceled.type);
- assertNull(unparceled.keyphrases);
- assertTrue(Arrays.equals(ksm.data, unparceled.data));
+ assertEquals(ksm.getUuid(), unparceled.getUuid());
+ assertEquals(ksm.getType(), unparceled.getType());
+ assertNull(unparceled.getKeyphrases());
+ assertTrue(Arrays.equals(ksm.getData(), unparceled.getData()));
}
@SmallTest
@@ -185,10 +184,10 @@ public class SoundTriggerTest extends InstrumentationTestCase {
KeyphraseSoundModel unparceled = KeyphraseSoundModel.CREATOR.createFromParcel(parcel);
// Verify that they are the same
- assertEquals(ksm.uuid, unparceled.uuid);
- assertEquals(ksm.type, unparceled.type);
- assertTrue(Arrays.equals(ksm.keyphrases, unparceled.keyphrases));
- assertTrue(Arrays.equals(ksm.data, unparceled.data));
+ assertEquals(ksm.getUuid(), unparceled.getUuid());
+ assertEquals(ksm.getType(), unparceled.getType());
+ assertTrue(Arrays.equals(ksm.getKeyphrases(), unparceled.getKeyphrases()));
+ assertTrue(Arrays.equals(ksm.getData(), unparceled.getData()));
}
@LargeTest
@@ -212,10 +211,10 @@ public class SoundTriggerTest extends InstrumentationTestCase {
KeyphraseSoundModel unparceled = KeyphraseSoundModel.CREATOR.createFromParcel(parcel);
// Verify that they are the same
- assertEquals(ksm.uuid, unparceled.uuid);
- assertEquals(ksm.type, unparceled.type);
- assertTrue(Arrays.equals(ksm.data, unparceled.data));
- assertTrue(Arrays.equals(ksm.keyphrases, unparceled.keyphrases));
+ assertEquals(ksm.getUuid(), unparceled.getUuid());
+ assertEquals(ksm.getType(), unparceled.getType());
+ assertTrue(Arrays.equals(ksm.getData(), unparceled.getData()));
+ assertTrue(Arrays.equals(ksm.getKeyphrases(), unparceled.getKeyphrases()));
}
@SmallTest
diff --git a/tests/SoundTriggerTests/src/android/hardware/soundtrigger/stubhal/GenericSoundModelTest.java b/tests/SoundTriggerTests/src/android/hardware/soundtrigger/stubhal/GenericSoundModelTest.java
index c0583ceb2fab..2c3592c640bc 100644
--- a/tests/SoundTriggerTests/src/android/hardware/soundtrigger/stubhal/GenericSoundModelTest.java
+++ b/tests/SoundTriggerTests/src/android/hardware/soundtrigger/stubhal/GenericSoundModelTest.java
@@ -17,7 +17,6 @@
package android.hardware.soundtrigger;
import static org.mockito.Matchers.any;
-import static org.mockito.Matchers.eq;
import static org.mockito.Mockito.reset;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.timeout;
@@ -37,6 +36,8 @@ import android.test.suitebuilder.annotation.SmallTest;
import com.android.internal.app.ISoundTriggerService;
+import org.mockito.MockitoAnnotations;
+
import java.io.DataOutputStream;
import java.net.InetAddress;
import java.net.Socket;
@@ -45,8 +46,6 @@ import java.util.HashSet;
import java.util.Random;
import java.util.UUID;
-import org.mockito.MockitoAnnotations;
-
public class GenericSoundModelTest extends AndroidTestCase {
static final int MSG_DETECTION_ERROR = -1;
static final int MSG_DETECTION_RESUME = 0;
@@ -96,11 +95,11 @@ public class GenericSoundModelTest extends AndroidTestCase {
// Update sound model
soundTriggerService.updateSoundModel(model);
- loadedModelUuids.add(model.uuid);
+ loadedModelUuids.add(model.getUuid());
// Confirm it was updated
GenericSoundModel returnedModel =
- soundTriggerService.getSoundModel(new ParcelUuid(model.uuid));
+ soundTriggerService.getSoundModel(new ParcelUuid(model.getUuid()));
assertEquals(model, returnedModel);
}
@@ -110,15 +109,15 @@ public class GenericSoundModelTest extends AndroidTestCase {
// Update sound model
soundTriggerService.updateSoundModel(model);
- loadedModelUuids.add(model.uuid);
+ loadedModelUuids.add(model.getUuid());
// Delete sound model
- soundTriggerService.deleteSoundModel(new ParcelUuid(model.uuid));
- loadedModelUuids.remove(model.uuid);
+ soundTriggerService.deleteSoundModel(new ParcelUuid(model.getUuid()));
+ loadedModelUuids.remove(model.getUuid());
// Confirm it was deleted
GenericSoundModel returnedModel =
- soundTriggerService.getSoundModel(new ParcelUuid(model.uuid));
+ soundTriggerService.getSoundModel(new ParcelUuid(model.getUuid()));
assertEquals(null, returnedModel);
}
@@ -134,14 +133,14 @@ public class GenericSoundModelTest extends AndroidTestCase {
// Update and start sound model recognition
soundTriggerService.updateSoundModel(model);
- loadedModelUuids.add(model.uuid);
- int r = soundTriggerService.startRecognition(new ParcelUuid(model.uuid), spyCallback,
+ loadedModelUuids.add(model.getUuid());
+ int r = soundTriggerService.startRecognition(new ParcelUuid(model.getUuid()), spyCallback,
config);
assertEquals("Could Not Start Recognition with code: " + r,
android.hardware.soundtrigger.SoundTrigger.STATUS_OK, r);
// Stop recognition
- r = soundTriggerService.stopRecognition(new ParcelUuid(model.uuid), spyCallback);
+ r = soundTriggerService.stopRecognition(new ParcelUuid(model.getUuid()), spyCallback);
assertEquals("Could Not Stop Recognition with code: " + r,
android.hardware.soundtrigger.SoundTrigger.STATUS_OK, r);
}
@@ -158,13 +157,13 @@ public class GenericSoundModelTest extends AndroidTestCase {
// Update and start sound model
soundTriggerService.updateSoundModel(model);
- loadedModelUuids.add(model.uuid);
- soundTriggerService.startRecognition(new ParcelUuid(model.uuid), spyCallback, config);
+ loadedModelUuids.add(model.getUuid());
+ soundTriggerService.startRecognition(new ParcelUuid(model.getUuid()), spyCallback, config);
// Send trigger to stub HAL
Socket socket = new Socket(InetAddress.getLocalHost(), 14035);
DataOutputStream out = new DataOutputStream(socket.getOutputStream());
- out.writeBytes("trig " + model.uuid.toString() + "\r\n");
+ out.writeBytes("trig " + model.getUuid().toString() + "\r\n");
out.flush();
socket.close();
@@ -227,11 +226,12 @@ public class GenericSoundModelTest extends AndroidTestCase {
if (operation == 0 && modelInfo.status == STATUS_UNLOADED) {
// Update and start sound model
soundTriggerService.updateSoundModel(modelInfo.model);
- loadedModelUuids.add(modelInfo.model.uuid);
+ loadedModelUuids.add(modelInfo.model.getUuid());
modelInfo.status = STATUS_LOADED;
} else if (operation == 1 && modelInfo.status == STATUS_LOADED) {
// Start the sound model
- int r = soundTriggerService.startRecognition(new ParcelUuid(modelInfo.model.uuid),
+ int r = soundTriggerService.startRecognition(new ParcelUuid(
+ modelInfo.model.getUuid()),
spyCallback, config);
assertEquals("Could Not Start Recognition with code: " + r,
android.hardware.soundtrigger.SoundTrigger.STATUS_OK, r);
@@ -240,7 +240,7 @@ public class GenericSoundModelTest extends AndroidTestCase {
// Send trigger to stub HAL
Socket socket = new Socket(InetAddress.getLocalHost(), 14035);
DataOutputStream out = new DataOutputStream(socket.getOutputStream());
- out.writeBytes("trig " + modelInfo.model.uuid + "\r\n");
+ out.writeBytes("trig " + modelInfo.model.getUuid() + "\r\n");
out.flush();
socket.close();
@@ -249,19 +249,20 @@ public class GenericSoundModelTest extends AndroidTestCase {
reset(spyCallback);
} else if (operation == 3 && modelInfo.status == STATUS_STARTED) {
// Stop recognition
- int r = soundTriggerService.stopRecognition(new ParcelUuid(modelInfo.model.uuid),
+ int r = soundTriggerService.stopRecognition(new ParcelUuid(
+ modelInfo.model.getUuid()),
spyCallback);
assertEquals("Could Not Stop Recognition with code: " + r,
android.hardware.soundtrigger.SoundTrigger.STATUS_OK, r);
modelInfo.status = STATUS_LOADED;
} else if (operation == 4 && modelInfo.status != STATUS_UNLOADED) {
// Delete sound model
- soundTriggerService.deleteSoundModel(new ParcelUuid(modelInfo.model.uuid));
- loadedModelUuids.remove(modelInfo.model.uuid);
+ soundTriggerService.deleteSoundModel(new ParcelUuid(modelInfo.model.getUuid()));
+ loadedModelUuids.remove(modelInfo.model.getUuid());
// Confirm it was deleted
- GenericSoundModel returnedModel =
- soundTriggerService.getSoundModel(new ParcelUuid(modelInfo.model.uuid));
+ GenericSoundModel returnedModel = soundTriggerService.getSoundModel(
+ new ParcelUuid(modelInfo.model.getUuid()));
assertEquals(null, returnedModel);
modelInfo.status = STATUS_UNLOADED;
}
diff --git a/tests/VoiceEnrollment/src/com/android/test/voiceenrollment/EnrollmentUtil.java b/tests/VoiceEnrollment/src/com/android/test/voiceenrollment/EnrollmentUtil.java
index 7927ac4cb895..287364fec8eb 100644
--- a/tests/VoiceEnrollment/src/com/android/test/voiceenrollment/EnrollmentUtil.java
+++ b/tests/VoiceEnrollment/src/com/android/test/voiceenrollment/EnrollmentUtil.java
@@ -159,36 +159,36 @@ public class EnrollmentUtil {
Log.e(TAG, "KeyphraseSoundModel must be non-null");
return false;
}
- if (soundModel.uuid == null) {
+ if (soundModel.getUuid() == null) {
Log.e(TAG, "KeyphraseSoundModel must have a UUID");
return false;
}
- if (soundModel.data == null) {
+ if (soundModel.getData() == null) {
Log.e(TAG, "KeyphraseSoundModel must have data");
return false;
}
- if (soundModel.keyphrases == null || soundModel.keyphrases.length != 1) {
+ if (soundModel.getKeyphrases() == null || soundModel.getKeyphrases().length != 1) {
Log.e(TAG, "Keyphrase must be exactly 1");
return false;
}
- Keyphrase keyphrase = soundModel.keyphrases[0];
- if (keyphrase.id <= 0) {
+ Keyphrase keyphrase = soundModel.getKeyphrases()[0];
+ if (keyphrase.getId() <= 0) {
Log.e(TAG, "Keyphrase must have a valid ID");
return false;
}
- if (keyphrase.recognitionModes < 0) {
+ if (keyphrase.getRecognitionModes() < 0) {
Log.e(TAG, "Recognition modes must be valid");
return false;
}
- if (keyphrase.locale == null) {
+ if (keyphrase.getLocale() == null) {
Log.e(TAG, "Locale must not be null");
return false;
}
- if (keyphrase.text == null) {
+ if (keyphrase.getText() == null) {
Log.e(TAG, "Text must not be null");
return false;
}
- if (keyphrase.users == null || keyphrase.users.length == 0) {
+ if (keyphrase.getUsers() == null || keyphrase.getUsers().length == 0) {
Log.e(TAG, "Keyphrase must have valid user(s)");
return false;
}
diff --git a/tests/VoiceEnrollment/src/com/android/test/voiceenrollment/TestEnrollmentActivity.java b/tests/VoiceEnrollment/src/com/android/test/voiceenrollment/TestEnrollmentActivity.java
index b357ad076c11..e4880fd10d67 100644
--- a/tests/VoiceEnrollment/src/com/android/test/voiceenrollment/TestEnrollmentActivity.java
+++ b/tests/VoiceEnrollment/src/com/android/test/voiceenrollment/TestEnrollmentActivity.java
@@ -91,7 +91,7 @@ public class TestEnrollmentActivity extends Activity {
}
boolean status = mEnrollmentUtil.deleteSoundModel(KEYPHRASE_ID, BCP47_LOCALE);
if (status) {
- Toast.makeText(this, "Successfully un-enrolled, model UUID=" + soundModel.uuid,
+ Toast.makeText(this, "Successfully un-enrolled, model UUID=" + soundModel.getUuid(),
Toast.LENGTH_SHORT)
.show();
} else {
@@ -112,11 +112,11 @@ public class TestEnrollmentActivity extends Activity {
// Generate a fake model to push.
byte[] data = new byte[2048];
mRandom.nextBytes(data);
- KeyphraseSoundModel updated = new KeyphraseSoundModel(soundModel.uuid,
- soundModel.vendorUuid, data, soundModel.keyphrases);
+ KeyphraseSoundModel updated = new KeyphraseSoundModel(soundModel.getUuid(),
+ soundModel.getVendorUuid(), data, soundModel.getKeyphrases());
boolean status = mEnrollmentUtil.addOrUpdateSoundModel(updated);
if (status) {
- Toast.makeText(this, "Successfully re-enrolled, model UUID=" + updated.uuid,
+ Toast.makeText(this, "Successfully re-enrolled, model UUID=" + updated.getUuid(),
Toast.LENGTH_SHORT)
.show();
} else {
diff --git a/tests/net/java/com/android/server/ConnectivityServiceTest.java b/tests/net/java/com/android/server/ConnectivityServiceTest.java
index 4bfb51bca20e..86d8a820e4bd 100644
--- a/tests/net/java/com/android/server/ConnectivityServiceTest.java
+++ b/tests/net/java/com/android/server/ConnectivityServiceTest.java
@@ -205,6 +205,7 @@ import android.os.UserManager;
import android.provider.Settings;
import android.security.KeyStore;
import android.system.Os;
+import android.telephony.TelephonyManager;
import android.test.mock.MockContentResolver;
import android.text.TextUtils;
import android.util.ArraySet;
@@ -307,6 +308,8 @@ public class ConnectivityServiceTest {
private static final long TIMESTAMP = 1234L;
+ private static final int NET_ID = 110;
+
private static final String CLAT_PREFIX = "v4-";
private static final String MOBILE_IFNAME = "test_rmnet_data0";
private static final String WIFI_IFNAME = "test_wlan0";
@@ -345,6 +348,7 @@ public class ConnectivityServiceTest {
@Mock IBinder mIBinder;
@Mock LocationManager mLocationManager;
@Mock AppOpsManager mAppOpsManager;
+ @Mock TelephonyManager mTelephonyManager;
private ArgumentCaptor<ResolverParamsParcel> mResolverParamsParcelCaptor =
ArgumentCaptor.forClass(ResolverParamsParcel.class);
@@ -431,6 +435,7 @@ public class ConnectivityServiceTest {
if (Context.ALARM_SERVICE.equals(name)) return mAlarmManager;
if (Context.LOCATION_SERVICE.equals(name)) return mLocationManager;
if (Context.APP_OPS_SERVICE.equals(name)) return mAppOpsManager;
+ if (Context.TELEPHONY_SERVICE.equals(name)) return mTelephonyManager;
return super.getSystemService(name);
}
@@ -1015,6 +1020,7 @@ public class ConnectivityServiceTest {
private int mVpnType = VpnManager.TYPE_VPN_SERVICE;
private VpnInfo mVpnInfo;
+ private Network[] mUnderlyingNetworks;
public MockVpn(int userId) {
super(startHandlerThreadAndReturnLooper(), mServiceContext, mNetworkManagementService,
@@ -1104,9 +1110,21 @@ public class ConnectivityServiceTest {
return super.getVpnInfo();
}
- private void setVpnInfo(VpnInfo vpnInfo) {
+ private synchronized void setVpnInfo(VpnInfo vpnInfo) {
mVpnInfo = vpnInfo;
}
+
+ @Override
+ public synchronized Network[] getUnderlyingNetworks() {
+ if (mUnderlyingNetworks != null) return mUnderlyingNetworks;
+
+ return super.getUnderlyingNetworks();
+ }
+
+ /** Don't override behavior for {@link Vpn#setUnderlyingNetworks}. */
+ private synchronized void overrideUnderlyingNetworks(Network[] underlyingNetworks) {
+ mUnderlyingNetworks = underlyingNetworks;
+ }
}
private void mockVpn(int uid) {
@@ -2896,7 +2914,7 @@ public class ConnectivityServiceTest {
class ConfidentialMatchAllNetworkSpecifier extends NetworkSpecifier implements
Parcelable {
@Override
- public boolean satisfiedBy(NetworkSpecifier other) {
+ public boolean canBeSatisfiedBy(NetworkSpecifier other) {
return true;
}
@@ -2924,7 +2942,7 @@ public class ConnectivityServiceTest {
}
@Override
- public boolean satisfiedBy(NetworkSpecifier other) {
+ public boolean canBeSatisfiedBy(NetworkSpecifier other) {
if (other instanceof LocalStringNetworkSpecifier) {
return TextUtils.equals(mString,
((LocalStringNetworkSpecifier) other).mString);
@@ -3045,7 +3063,10 @@ public class ConnectivityServiceTest {
});
class NonParcelableSpecifier extends NetworkSpecifier {
- public boolean satisfiedBy(NetworkSpecifier other) { return false; }
+ @Override
+ public boolean canBeSatisfiedBy(NetworkSpecifier other) {
+ return false;
+ }
};
class ParcelableSpecifier extends NonParcelableSpecifier implements Parcelable {
@Override public int describeContents() { return 0; }
@@ -6795,15 +6816,11 @@ public class ConnectivityServiceTest {
mServiceContext.setPermission(android.Manifest.permission.NETWORK_STACK, PERMISSION_DENIED);
- try {
- assertFalse(
- "Mismatched uid/package name should not pass the location permission check",
- mService.checkConnectivityDiagnosticsPermissions(
- Process.myPid() + 1, Process.myUid() + 1, naiWithoutUid,
- mContext.getOpPackageName()));
- } catch (SecurityException e) {
- fail("checkConnectivityDiagnosticsPermissions shouldn't surface a SecurityException");
- }
+ assertFalse(
+ "Mismatched uid/package name should not pass the location permission check",
+ mService.checkConnectivityDiagnosticsPermissions(
+ Process.myPid() + 1, Process.myUid() + 1, naiWithoutUid,
+ mContext.getOpPackageName()));
}
@Test
@@ -6824,9 +6841,10 @@ public class ConnectivityServiceTest {
@Test
public void testCheckConnectivityDiagnosticsPermissionsActiveVpn() throws Exception {
+ final Network network = new Network(NET_ID);
final NetworkAgentInfo naiWithoutUid =
new NetworkAgentInfo(
- null, null, null, null, null, new NetworkCapabilities(), 0,
+ null, null, network, null, null, new NetworkCapabilities(), 0,
mServiceContext, null, null, mService, null, null, null, 0);
setupLocationPermissions(Build.VERSION_CODES.Q, true, AppOpsManager.OPSTR_FINE_LOCATION,
@@ -6839,11 +6857,19 @@ public class ConnectivityServiceTest {
info.ownerUid = Process.myUid();
info.vpnIface = "interface";
mMockVpn.setVpnInfo(info);
+ mMockVpn.overrideUnderlyingNetworks(new Network[] {network});
assertTrue(
"Active VPN permission not applied",
mService.checkConnectivityDiagnosticsPermissions(
Process.myPid(), Process.myUid(), naiWithoutUid,
mContext.getOpPackageName()));
+
+ mMockVpn.overrideUnderlyingNetworks(null);
+ assertFalse(
+ "VPN shouldn't receive callback on non-underlying network",
+ mService.checkConnectivityDiagnosticsPermissions(
+ Process.myPid(), Process.myUid(), naiWithoutUid,
+ mContext.getOpPackageName()));
}
@Test
diff --git a/wifi/Android.bp b/wifi/Android.bp
index d0f1a26f7dbf..614786193a18 100644
--- a/wifi/Android.bp
+++ b/wifi/Android.bp
@@ -81,7 +81,6 @@ java_library {
libs: [
"framework-annotations-lib",
"unsupportedappusage", // for android.compat.annotation.UnsupportedAppUsage
- "unsupportedappusage-annotation", // for dalvik.annotation.compat.UnsupportedAppUsage
"framework-telephony-stubs",
],
srcs: [
diff --git a/wifi/java/android/net/wifi/WifiNetworkAgentSpecifier.java b/wifi/java/android/net/wifi/WifiNetworkAgentSpecifier.java
index 6632c162fcf9..0d13805a08d8 100644
--- a/wifi/java/android/net/wifi/WifiNetworkAgentSpecifier.java
+++ b/wifi/java/android/net/wifi/WifiNetworkAgentSpecifier.java
@@ -74,7 +74,7 @@ public final class WifiNetworkAgentSpecifier extends NetworkSpecifier implements
}
@Override
- public boolean satisfiedBy(@Nullable NetworkSpecifier other) {
+ public boolean canBeSatisfiedBy(@Nullable NetworkSpecifier other) {
if (this == other) {
return true;
}
diff --git a/wifi/java/android/net/wifi/WifiNetworkSpecifier.java b/wifi/java/android/net/wifi/WifiNetworkSpecifier.java
index 3d946c9f887d..ed54ad13e5e1 100644
--- a/wifi/java/android/net/wifi/WifiNetworkSpecifier.java
+++ b/wifi/java/android/net/wifi/WifiNetworkSpecifier.java
@@ -552,7 +552,7 @@ public final class WifiNetworkSpecifier extends NetworkSpecifier implements Parc
/** @hide */
@Override
- public boolean satisfiedBy(NetworkSpecifier other) {
+ public boolean canBeSatisfiedBy(NetworkSpecifier other) {
if (this == other) {
return true;
}
diff --git a/wifi/java/android/net/wifi/aware/WifiAwareAgentNetworkSpecifier.java b/wifi/java/android/net/wifi/aware/WifiAwareAgentNetworkSpecifier.java
index a4b3e86398a8..9ae3bd0c93c0 100644
--- a/wifi/java/android/net/wifi/aware/WifiAwareAgentNetworkSpecifier.java
+++ b/wifi/java/android/net/wifi/aware/WifiAwareAgentNetworkSpecifier.java
@@ -120,7 +120,7 @@ public class WifiAwareAgentNetworkSpecifier extends NetworkSpecifier implements
}
@Override
- public boolean satisfiedBy(NetworkSpecifier other) {
+ public boolean canBeSatisfiedBy(NetworkSpecifier other) {
if (!(other instanceof WifiAwareAgentNetworkSpecifier)) {
return false;
}
diff --git a/wifi/java/android/net/wifi/aware/WifiAwareNetworkSpecifier.java b/wifi/java/android/net/wifi/aware/WifiAwareNetworkSpecifier.java
index 65ac1ab26064..3547750896b3 100644
--- a/wifi/java/android/net/wifi/aware/WifiAwareNetworkSpecifier.java
+++ b/wifi/java/android/net/wifi/aware/WifiAwareNetworkSpecifier.java
@@ -212,7 +212,7 @@ public final class WifiAwareNetworkSpecifier extends NetworkSpecifier implements
/** @hide */
@Override
- public boolean satisfiedBy(NetworkSpecifier other) {
+ public boolean canBeSatisfiedBy(NetworkSpecifier other) {
// MatchAllNetworkSpecifier is taken care in NetworkCapabilities#satisfiedBySpecifier.
if (other instanceof WifiAwareAgentNetworkSpecifier) {
return ((WifiAwareAgentNetworkSpecifier) other).satisfiesAwareNetworkSpecifier(this);
diff --git a/wifi/tests/src/android/net/wifi/WifiNetworkAgentSpecifierTest.java b/wifi/tests/src/android/net/wifi/WifiNetworkAgentSpecifierTest.java
index 0233ee2e2785..d479aacdd296 100644
--- a/wifi/tests/src/android/net/wifi/WifiNetworkAgentSpecifierTest.java
+++ b/wifi/tests/src/android/net/wifi/WifiNetworkAgentSpecifierTest.java
@@ -155,8 +155,8 @@ public class WifiNetworkAgentSpecifierTest {
public void testWifiNetworkAgentSpecifierSatisifiesNullAndAllMatch() {
WifiNetworkAgentSpecifier specifier = createDefaultNetworkAgentSpecifier();
- assertTrue(specifier.satisfiedBy(null));
- assertTrue(specifier.satisfiedBy(new MatchAllNetworkSpecifier()));
+ assertTrue(specifier.canBeSatisfiedBy(null));
+ assertTrue(specifier.canBeSatisfiedBy(new MatchAllNetworkSpecifier()));
}
/**
@@ -170,7 +170,7 @@ public class WifiNetworkAgentSpecifierTest {
WifiNetworkAgentSpecifier specifier1 = createDefaultNetworkAgentSpecifier();
WifiNetworkAgentSpecifier specifier2 = createDefaultNetworkAgentSpecifier();
- assertTrue(specifier2.satisfiedBy(specifier1));
+ assertTrue(specifier2.canBeSatisfiedBy(specifier1));
}
/**
@@ -196,8 +196,8 @@ public class WifiNetworkAgentSpecifierTest {
bssidPattern,
wificonfigurationNetworkSpecifier);
- assertTrue(wifiNetworkSpecifier.satisfiedBy(wifiNetworkAgentSpecifier));
- assertTrue(wifiNetworkAgentSpecifier.satisfiedBy(wifiNetworkSpecifier));
+ assertTrue(wifiNetworkSpecifier.canBeSatisfiedBy(wifiNetworkAgentSpecifier));
+ assertTrue(wifiNetworkAgentSpecifier.canBeSatisfiedBy(wifiNetworkSpecifier));
}
/**
@@ -224,8 +224,8 @@ public class WifiNetworkAgentSpecifierTest {
bssidPattern,
wificonfigurationNetworkSpecifier);
- assertTrue(wifiNetworkSpecifier.satisfiedBy(wifiNetworkAgentSpecifier));
- assertTrue(wifiNetworkAgentSpecifier.satisfiedBy(wifiNetworkSpecifier));
+ assertTrue(wifiNetworkSpecifier.canBeSatisfiedBy(wifiNetworkAgentSpecifier));
+ assertTrue(wifiNetworkAgentSpecifier.canBeSatisfiedBy(wifiNetworkSpecifier));
}
/**
@@ -252,8 +252,8 @@ public class WifiNetworkAgentSpecifierTest {
bssidPattern,
wificonfigurationNetworkSpecifier);
- assertTrue(wifiNetworkSpecifier.satisfiedBy(wifiNetworkAgentSpecifier));
- assertTrue(wifiNetworkAgentSpecifier.satisfiedBy(wifiNetworkSpecifier));
+ assertTrue(wifiNetworkSpecifier.canBeSatisfiedBy(wifiNetworkAgentSpecifier));
+ assertTrue(wifiNetworkAgentSpecifier.canBeSatisfiedBy(wifiNetworkSpecifier));
}
/**
@@ -283,8 +283,8 @@ public class WifiNetworkAgentSpecifierTest {
bssidPattern,
wificonfigurationNetworkSpecifier);
- assertFalse(wifiNetworkSpecifier.satisfiedBy(wifiNetworkAgentSpecifier));
- assertFalse(wifiNetworkAgentSpecifier.satisfiedBy(wifiNetworkSpecifier));
+ assertFalse(wifiNetworkSpecifier.canBeSatisfiedBy(wifiNetworkAgentSpecifier));
+ assertFalse(wifiNetworkAgentSpecifier.canBeSatisfiedBy(wifiNetworkSpecifier));
}
/**
@@ -315,8 +315,8 @@ public class WifiNetworkAgentSpecifierTest {
bssidPattern,
wificonfigurationNetworkSpecifier);
- assertFalse(wifiNetworkSpecifier.satisfiedBy(wifiNetworkAgentSpecifier));
- assertFalse(wifiNetworkAgentSpecifier.satisfiedBy(wifiNetworkSpecifier));
+ assertFalse(wifiNetworkSpecifier.canBeSatisfiedBy(wifiNetworkAgentSpecifier));
+ assertFalse(wifiNetworkAgentSpecifier.canBeSatisfiedBy(wifiNetworkSpecifier));
}
/**
@@ -347,8 +347,8 @@ public class WifiNetworkAgentSpecifierTest {
bssidPattern,
wificonfigurationNetworkSpecifier);
- assertFalse(wifiNetworkSpecifier.satisfiedBy(wifiNetworkAgentSpecifier));
- assertFalse(wifiNetworkAgentSpecifier.satisfiedBy(wifiNetworkSpecifier));
+ assertFalse(wifiNetworkSpecifier.canBeSatisfiedBy(wifiNetworkAgentSpecifier));
+ assertFalse(wifiNetworkAgentSpecifier.canBeSatisfiedBy(wifiNetworkSpecifier));
}
/**
@@ -374,8 +374,8 @@ public class WifiNetworkAgentSpecifierTest {
bssidPattern,
wificonfigurationNetworkSpecifier);
- assertFalse(wifiNetworkSpecifier.satisfiedBy(wifiNetworkAgentSpecifier));
- assertFalse(wifiNetworkAgentSpecifier.satisfiedBy(wifiNetworkSpecifier));
+ assertFalse(wifiNetworkSpecifier.canBeSatisfiedBy(wifiNetworkAgentSpecifier));
+ assertFalse(wifiNetworkAgentSpecifier.canBeSatisfiedBy(wifiNetworkSpecifier));
}
diff --git a/wifi/tests/src/android/net/wifi/WifiNetworkSpecifierTest.java b/wifi/tests/src/android/net/wifi/WifiNetworkSpecifierTest.java
index 3b6723613c50..53a7d032da42 100644
--- a/wifi/tests/src/android/net/wifi/WifiNetworkSpecifierTest.java
+++ b/wifi/tests/src/android/net/wifi/WifiNetworkSpecifierTest.java
@@ -396,8 +396,8 @@ public class WifiNetworkSpecifierTest {
MacAddress.fromString(TEST_BSSID_OUI_MASK)),
wifiConfiguration);
- assertTrue(specifier.satisfiedBy(null));
- assertTrue(specifier.satisfiedBy(new MatchAllNetworkSpecifier()));
+ assertTrue(specifier.canBeSatisfiedBy(null));
+ assertTrue(specifier.canBeSatisfiedBy(new MatchAllNetworkSpecifier()));
}
/**
@@ -424,7 +424,7 @@ public class WifiNetworkSpecifierTest {
MacAddress.fromString(TEST_BSSID_OUI_MASK)),
wifiConfiguration);
- assertTrue(specifier2.satisfiedBy(specifier1));
+ assertTrue(specifier2.canBeSatisfiedBy(specifier1));
}
/**
@@ -453,7 +453,7 @@ public class WifiNetworkSpecifierTest {
MacAddress.fromString(TEST_BSSID_OUI_MASK)),
wifiConfiguration2);
- assertFalse(specifier2.satisfiedBy(specifier1));
+ assertFalse(specifier2.canBeSatisfiedBy(specifier1));
}
/**
@@ -480,7 +480,7 @@ public class WifiNetworkSpecifierTest {
MacAddress.fromString(TEST_BSSID_OUI_MASK)),
wifiConfiguration);
- assertFalse(specifier2.satisfiedBy(specifier1));
+ assertFalse(specifier2.canBeSatisfiedBy(specifier1));
}
/**
@@ -507,6 +507,6 @@ public class WifiNetworkSpecifierTest {
WifiManager.ALL_ZEROS_MAC_ADDRESS),
wifiConfiguration);
- assertFalse(specifier2.satisfiedBy(specifier1));
+ assertFalse(specifier2.canBeSatisfiedBy(specifier1));
}
}
diff --git a/wifi/tests/src/android/net/wifi/aware/WifiAwareAgentNetworkSpecifierTest.java b/wifi/tests/src/android/net/wifi/aware/WifiAwareAgentNetworkSpecifierTest.java
index 81b02fa5f801..f2961db4eb14 100644
--- a/wifi/tests/src/android/net/wifi/aware/WifiAwareAgentNetworkSpecifierTest.java
+++ b/wifi/tests/src/android/net/wifi/aware/WifiAwareAgentNetworkSpecifierTest.java
@@ -79,7 +79,7 @@ public class WifiAwareAgentNetworkSpecifierTest {
public void testEmptyDoesntMatchAnything() {
WifiAwareAgentNetworkSpecifier dut = new WifiAwareAgentNetworkSpecifier();
WifiAwareNetworkSpecifier ns = getDummyNetworkSpecifier(6);
- collector.checkThat("No match expected", ns.satisfiedBy(dut), equalTo(false));
+ collector.checkThat("No match expected", ns.canBeSatisfiedBy(dut), equalTo(false));
}
/**
@@ -91,8 +91,8 @@ public class WifiAwareAgentNetworkSpecifierTest {
WifiAwareNetworkSpecifier nsThis = getDummyNetworkSpecifier(6);
WifiAwareAgentNetworkSpecifier dut = new WifiAwareAgentNetworkSpecifier(nsThis);
WifiAwareNetworkSpecifier nsOther = getDummyNetworkSpecifier(8);
- collector.checkThat("Match expected", nsThis.satisfiedBy(dut), equalTo(true));
- collector.checkThat("No match expected", nsOther.satisfiedBy(dut), equalTo(false));
+ collector.checkThat("Match expected", nsThis.canBeSatisfiedBy(dut), equalTo(true));
+ collector.checkThat("No match expected", nsOther.canBeSatisfiedBy(dut), equalTo(false));
}
/**
@@ -113,9 +113,9 @@ public class WifiAwareAgentNetworkSpecifierTest {
WifiAwareNetworkSpecifier nsOther = getDummyNetworkSpecifier(10000);
for (WifiAwareNetworkSpecifier nsThis: nsSet) {
- collector.checkThat("Match expected", nsThis.satisfiedBy(dut), equalTo(true));
+ collector.checkThat("Match expected", nsThis.canBeSatisfiedBy(dut), equalTo(true));
}
- collector.checkThat("No match expected", nsOther.satisfiedBy(dut), equalTo(false));
+ collector.checkThat("No match expected", nsOther.canBeSatisfiedBy(dut), equalTo(false));
}
/**
@@ -137,7 +137,7 @@ public class WifiAwareAgentNetworkSpecifierTest {
WifiAwareAgentNetworkSpecifier newNs = new WifiAwareAgentNetworkSpecifier(
nsSet.toArray(new WifiAwareNetworkSpecifier[nsSet.size()]));
- collector.checkThat("Match expected", oldNs.satisfiedBy(newNs), equalTo(true));
+ collector.checkThat("Match expected", oldNs.canBeSatisfiedBy(newNs), equalTo(true));
}
/**
@@ -159,7 +159,7 @@ public class WifiAwareAgentNetworkSpecifierTest {
WifiAwareAgentNetworkSpecifier oldNs = new WifiAwareAgentNetworkSpecifier(
nsSet.toArray(new WifiAwareNetworkSpecifier[nsSet.size()]));
- collector.checkThat("Match unexpected", oldNs.satisfiedBy(newNs), equalTo(false));
+ collector.checkThat("Match unexpected", oldNs.canBeSatisfiedBy(newNs), equalTo(false));
}
// utilities