summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--core/java/android/app/SystemServiceRegistry.java9
-rw-r--r--core/java/android/content/IntentFilter.java8
-rw-r--r--core/java/android/hardware/SensorPrivacyManager.java8
-rw-r--r--core/java/android/os/IHintManager.aidl4
-rw-r--r--core/java/android/os/flags.aconfig8
-rw-r--r--core/java/android/os/vibrator/VibrationConfig.java68
-rw-r--r--core/java/android/permission/flags.aconfig8
-rw-r--r--core/tests/bugreports/Android.bp7
-rw-r--r--core/tests/coretests/Android.bp65
-rw-r--r--core/tests/vibrator/src/android/os/vibrator/VibrationConfigTest.java100
-rw-r--r--libs/WindowManager/Jetpack/tests/unittest/Android.bp7
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/common/pip/PhonePipKeepClearAlgorithm.java6
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/common/pip/PipBoundsState.java23
-rw-r--r--libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/pip/phone/PhonePipKeepClearAlgorithmTest.java46
-rw-r--r--media/tests/LoudnessCodecApiTest/Android.bp7
-rw-r--r--native/android/libandroid.map.txt1
-rw-r--r--native/android/performance_hint.cpp334
-rw-r--r--native/android/tests/performance_hint/Android.bp7
-rw-r--r--native/android/tests/performance_hint/PerformanceHintNativeTest.cpp103
-rw-r--r--packages/SettingsLib/src/com/android/settingslib/media/OWNERS1
-rw-r--r--packages/Shell/tests/Android.bp7
-rw-r--r--packages/SystemUI/compose/features/src/com/android/systemui/bouncer/ui/composable/PinBouncer.kt23
-rw-r--r--packages/SystemUI/multivalentTests/src/com/android/keyguard/KeyguardPasswordViewControllerTest.kt11
-rw-r--r--packages/SystemUI/multivalentTests/src/com/android/keyguard/KeyguardPatternViewControllerTest.kt6
-rw-r--r--packages/SystemUI/multivalentTests/src/com/android/keyguard/KeyguardPinBasedInputViewControllerTest.java8
-rw-r--r--packages/SystemUI/multivalentTests/src/com/android/systemui/bouncer/ui/viewmodel/PinBouncerViewModelTest.kt19
-rw-r--r--packages/SystemUI/multivalentTests/src/com/android/systemui/deviceentry/domain/interactor/DeviceEntryInteractorTest.kt41
-rw-r--r--packages/SystemUI/multivalentTests/src/com/android/systemui/scene/SceneFrameworkIntegrationTest.kt49
-rw-r--r--packages/SystemUI/multivalentTests/src/com/android/systemui/scene/domain/interactor/SceneBackInteractorTest.kt22
-rw-r--r--packages/SystemUI/multivalentTests/src/com/android/systemui/scene/domain/startable/SceneContainerStartableTest.kt184
-rw-r--r--packages/SystemUI/res/drawable/ic_volume_media_off.xml20
-rw-r--r--packages/SystemUI/src/com/android/keyguard/KeyguardAbsKeyInputViewController.java34
-rw-r--r--packages/SystemUI/src/com/android/keyguard/KeyguardInputViewController.java27
-rw-r--r--packages/SystemUI/src/com/android/keyguard/KeyguardPasswordViewController.java10
-rw-r--r--packages/SystemUI/src/com/android/keyguard/KeyguardPatternViewController.java24
-rw-r--r--packages/SystemUI/src/com/android/keyguard/KeyguardPinBasedInputViewController.java28
-rw-r--r--packages/SystemUI/src/com/android/keyguard/KeyguardPinViewController.java8
-rw-r--r--packages/SystemUI/src/com/android/keyguard/KeyguardSimPinViewController.java8
-rw-r--r--packages/SystemUI/src/com/android/keyguard/KeyguardSimPukViewController.java8
-rw-r--r--packages/SystemUI/src/com/android/keyguard/NumPadKey.java15
-rw-r--r--packages/SystemUI/src/com/android/systemui/bouncer/ui/helper/BouncerHapticPlayer.kt (renamed from packages/SystemUI/src/com/android/systemui/bouncer/ui/helper/BouncerHapticHelper.kt)47
-rw-r--r--packages/SystemUI/src/com/android/systemui/bouncer/ui/viewmodel/PinBouncerViewModel.kt10
-rw-r--r--packages/SystemUI/src/com/android/systemui/classifier/FalsingCollectorFake.java11
-rw-r--r--packages/SystemUI/src/com/android/systemui/deviceentry/domain/interactor/DeviceEntryInteractor.kt58
-rw-r--r--packages/SystemUI/src/com/android/systemui/keyboard/shortcut/ui/composable/ShortcutHelper.kt12
-rw-r--r--packages/SystemUI/src/com/android/systemui/keyboard/shortcut/ui/composable/Surfaces.kt199
-rw-r--r--packages/SystemUI/src/com/android/systemui/media/controls/ui/controller/MediaCarouselController.kt12
-rw-r--r--packages/SystemUI/src/com/android/systemui/scene/domain/interactor/SceneBackInteractor.kt6
-rw-r--r--packages/SystemUI/src/com/android/systemui/scene/domain/startable/SceneContainerStartable.kt18
-rw-r--r--packages/SystemUI/src/com/android/systemui/volume/VolumeDialogImpl.java2
-rw-r--r--packages/SystemUI/tests/src/com/android/keyguard/KeyguardAbsKeyInputViewControllerTest.java7
-rw-r--r--packages/SystemUI/tests/src/com/android/keyguard/KeyguardPinViewControllerTest.kt8
-rw-r--r--packages/SystemUI/tests/src/com/android/keyguard/KeyguardSimPinViewControllerTest.kt12
-rw-r--r--packages/SystemUI/tests/src/com/android/keyguard/KeyguardSimPukViewControllerTest.kt8
-rw-r--r--packages/SystemUI/tests/utils/src/com/android/systemui/classifier/FalsingCollectorKosmos.kt4
-rw-r--r--packages/SystemUI/tests/utils/src/com/android/systemui/deviceentry/domain/interactor/DeviceEntryInteractorKosmos.kt2
-rw-r--r--packages/SystemUI/tests/utils/src/com/android/systemui/haptics/msdl/BouncerHapticHelperKosmos.kt28
-rw-r--r--packages/SystemUI/tests/utils/src/com/android/systemui/kosmos/KosmosJavaAdapter.kt2
-rw-r--r--packages/SystemUI/tests/utils/src/com/android/systemui/scene/domain/startable/SceneContainerStartableKosmos.kt3
-rw-r--r--services/core/java/com/android/server/power/hint/HintManagerService.java31
-rw-r--r--services/core/java/com/android/server/sensorprivacy/SensorPrivacyService.java65
-rw-r--r--services/core/jni/com_android_server_hint_HintManagerService.cpp4
-rw-r--r--services/tests/PackageManagerServiceTests/host/Android.bp7
-rw-r--r--services/tests/PackageManagerServiceTests/server/Android.bp10
-rw-r--r--services/tests/VpnTests/Android.bp7
-rw-r--r--services/tests/mockingservicestests/Android.bp10
-rw-r--r--services/tests/performancehinttests/src/com/android/server/power/hint/HintManagerServiceTest.java4
-rw-r--r--services/tests/servicestests/Android.bp296
-rw-r--r--services/tests/uiservicestests/Android.bp10
-rw-r--r--tests/permission/Android.bp7
70 files changed, 1642 insertions, 630 deletions
diff --git a/core/java/android/app/SystemServiceRegistry.java b/core/java/android/app/SystemServiceRegistry.java
index e44e7768724e..5147f12018cf 100644
--- a/core/java/android/app/SystemServiceRegistry.java
+++ b/core/java/android/app/SystemServiceRegistry.java
@@ -104,6 +104,7 @@ import android.debug.IAdbManager;
import android.devicelock.DeviceLockFrameworkInitializer;
import android.graphics.fonts.FontManager;
import android.hardware.ConsumerIrManager;
+import android.hardware.ISensorPrivacyManager;
import android.hardware.ISerialManager;
import android.hardware.SensorManager;
import android.hardware.SensorPrivacyManager;
@@ -707,8 +708,12 @@ public final class SystemServiceRegistry {
registerService(Context.SENSOR_PRIVACY_SERVICE, SensorPrivacyManager.class,
new CachedServiceFetcher<SensorPrivacyManager>() {
@Override
- public SensorPrivacyManager createService(ContextImpl ctx) {
- return SensorPrivacyManager.getInstance(ctx);
+ public SensorPrivacyManager createService(ContextImpl ctx)
+ throws ServiceNotFoundException {
+ IBinder b = ServiceManager.getServiceOrThrow(
+ Context.SENSOR_PRIVACY_SERVICE);
+ return SensorPrivacyManager.getInstance(
+ ctx, ISensorPrivacyManager.Stub.asInterface(b));
}});
registerService(Context.STATUS_BAR_SERVICE, StatusBarManager.class,
diff --git a/core/java/android/content/IntentFilter.java b/core/java/android/content/IntentFilter.java
index 60d1b0d45365..e895d7be1102 100644
--- a/core/java/android/content/IntentFilter.java
+++ b/core/java/android/content/IntentFilter.java
@@ -3141,14 +3141,6 @@ public class IntentFilter implements Parcelable {
for (int i = 0; i < N; i++) {
mUriRelativeFilterGroups.add(new UriRelativeFilterGroup(source));
}
- if (source.dataAvail() > 0) {
- Log.e(TAG, "Parcel data not fully consumed after completed reading"
- + " UriRelativeFilterGroup data");
- }
- }
- if (source.dataAvail() > 0) {
- Log.e(TAG, "Parcel data not fully consumed when unparceling intent filter",
- new Exception());
}
}
diff --git a/core/java/android/hardware/SensorPrivacyManager.java b/core/java/android/hardware/SensorPrivacyManager.java
index 4cdaaddd05bf..a4c0e87c965b 100644
--- a/core/java/android/hardware/SensorPrivacyManager.java
+++ b/core/java/android/hardware/SensorPrivacyManager.java
@@ -797,7 +797,7 @@ public final class SensorPrivacyManager {
public void setSensorPrivacy(@Sensors.Sensor int sensor,
boolean enable) {
setSensorPrivacy(resolveSourceFromCurrentContext(), sensor, enable,
- UserHandle.USER_CURRENT);
+ mContext.getUserId());
}
private @Sources.Source int resolveSourceFromCurrentContext() {
@@ -837,6 +837,8 @@ public final class SensorPrivacyManager {
@RequiresPermission(Manifest.permission.MANAGE_SENSOR_PRIVACY)
public void setSensorPrivacy(@Sources.Source int source, @Sensors.Sensor int sensor,
boolean enable) {
+ // TODO(b/348510106): Replace USER_CURRENT with Context user and fix any tests that may be
+ // affected.
setSensorPrivacy(source, sensor, enable, UserHandle.USER_CURRENT);
}
@@ -894,7 +896,7 @@ public final class SensorPrivacyManager {
@RequiresPermission(Manifest.permission.MANAGE_SENSOR_PRIVACY)
public void setSensorPrivacyForProfileGroup(@Sources.Source int source,
@Sensors.Sensor int sensor, boolean enable) {
- setSensorPrivacyForProfileGroup(source , sensor, enable, UserHandle.USER_CURRENT);
+ setSensorPrivacyForProfileGroup(source , sensor, enable, mContext.getUserId());
}
/**
@@ -950,7 +952,7 @@ public final class SensorPrivacyManager {
@RequiresPermission(Manifest.permission.MANAGE_SENSOR_PRIVACY)
public void suppressSensorPrivacyReminders(int sensor,
boolean suppress) {
- suppressSensorPrivacyReminders(sensor, suppress, UserHandle.USER_CURRENT);
+ suppressSensorPrivacyReminders(sensor, suppress, mContext.getUserId());
}
/**
diff --git a/core/java/android/os/IHintManager.aidl b/core/java/android/os/IHintManager.aidl
index 360b2ac4f3ca..73cdd5682f31 100644
--- a/core/java/android/os/IHintManager.aidl
+++ b/core/java/android/os/IHintManager.aidl
@@ -33,7 +33,7 @@ interface IHintManager {
* if creation is supported but fails.
*/
IHintSession createHintSessionWithConfig(in IBinder token, in int[] threadIds,
- in long durationNanos, in SessionTag tag, out @nullable SessionConfig config);
+ in long durationNanos, in SessionTag tag, out SessionConfig config);
/**
* Get preferred rate limit in nanoseconds.
@@ -48,6 +48,6 @@ interface IHintManager {
*
* Throws IllegalStateException if FMQ channel creation fails.
*/
- ChannelConfig getSessionChannel(in IBinder token);
+ @nullable ChannelConfig getSessionChannel(in IBinder token);
oneway void closeSessionChannel();
}
diff --git a/core/java/android/os/flags.aconfig b/core/java/android/os/flags.aconfig
index 435770326880..39bd15c968d7 100644
--- a/core/java/android/os/flags.aconfig
+++ b/core/java/android/os/flags.aconfig
@@ -107,14 +107,6 @@ flag {
}
flag {
- name: "adpf_fmq_eager_send"
- namespace: "game"
- description: "Guards the use of an eager-sending optimization in FMQ for low-latency messages"
- is_fixed_read_only: true
- bug: "315894228"
-}
-
-flag {
name: "adpf_hwui_gpu"
namespace: "game"
description: "Guards use of the FMQ channel for ADPF"
diff --git a/core/java/android/os/vibrator/VibrationConfig.java b/core/java/android/os/vibrator/VibrationConfig.java
index bc6c5706f6fd..e6e5a27bd731 100644
--- a/core/java/android/os/vibrator/VibrationConfig.java
+++ b/core/java/android/os/vibrator/VibrationConfig.java
@@ -30,17 +30,13 @@ import static android.os.VibrationAttributes.USAGE_UNKNOWN;
import android.annotation.Nullable;
import android.content.res.Resources;
-import android.os.SystemProperties;
import android.os.VibrationAttributes;
import android.os.Vibrator;
import android.os.Vibrator.VibrationIntensity;
import android.util.IndentingPrintWriter;
-import com.android.internal.annotations.VisibleForTesting;
-
import java.io.PrintWriter;
import java.util.Arrays;
-import java.util.function.Function;
/**
* List of device-specific internal vibration configuration loaded from platform config.xml.
@@ -54,37 +50,6 @@ import java.util.function.Function;
public class VibrationConfig {
/**
- * The default gain to be applied between vibration scale levels.
- *
- * <p>Scale levels are defined as the difference between the user vibration intensity setting
- * and the device default config for each usage. The intensity values are defined as one of
- * Vibrator.VIBRATION_INTENSITY_*.
- *
- * <p>A user setting HIGH set on a device with default value LOW will cause the vibration
- * intensity to be scaled up 2 levels, i.e. scale with a factor of gain^2. A system with 3
- * intensities LOW, MEDIUM and HIGH has the following 5 scale levels:
- *
- * <ol>
- * <li>VERY_HIGH: user(HIGH) - device(LOW)
- * <li>HIGH: user(HIGH) - device(MEDIUM) / user(MEDIUM) - device(LOW)
- * <li>NONE: user == device
- * <li>LOW: user(MEDIUM) - device(HIGH) / user(LOW) - device(MEDIUM)
- * <li>VERY_LOW: user(LOW) - device(HIGH)
- * </ol>
- *
- * <p>A device will only ever apply 3 out of these 5 levels based on the default intensity
- * config set for each usage (e.g. config_default[Alarm|Ring|Notification]VibrationIntensity).
- *
- * <p>This value must be greater than 1. The {@link #DEFAULT_SCALE_LEVEL_GAIN} will be used if
- * this property is undefined or invalid.
- *
- * @hide
- */
- @VisibleForTesting
- static final String SCALE_LEVEL_GAIN_SYSTEM_PROPERTY =
- "vendor.vibrator.scale.level.gain";
-
- /**
* Hardcoded default scale level gain to be applied between each scale level to define their
* scale factor value.
*
@@ -104,7 +69,7 @@ public class VibrationConfig {
private final int mRampDownDurationMs;
private final int mRequestVibrationParamsTimeoutMs;
private final int[] mRequestVibrationParamsForUsages;
- private final float mDefaultVibrationScaleLevelGain;
+
private final boolean mIgnoreVibrationsOnWirelessCharger;
@VibrationIntensity
@@ -124,18 +89,8 @@ public class VibrationConfig {
/** @hide */
public VibrationConfig(@Nullable Resources resources) {
- this(resources, SystemProperties::get);
- }
-
- /** @hide */
- @VisibleForTesting
- public VibrationConfig(@Nullable Resources resources,
- Function<String, String> systemPropertiesGetter) {
- mDefaultVibrationAmplitude = loadInteger(resources,
- com.android.internal.R.integer.config_defaultVibrationAmplitude,
- DEFAULT_AMPLITUDE);
- mDefaultVibrationScaleLevelGain = loadFloat(systemPropertiesGetter,
- SCALE_LEVEL_GAIN_SYSTEM_PROPERTY, DEFAULT_SCALE_LEVEL_GAIN);
+ mDefaultVibrationAmplitude = resources.getInteger(
+ com.android.internal.R.integer.config_defaultVibrationAmplitude);
mHapticChannelMaxVibrationAmplitude = loadFloat(resources,
com.android.internal.R.dimen.config_hapticChannelMaxVibrationAmplitude);
mRampDownDurationMs = loadInteger(resources,
@@ -180,15 +135,6 @@ public class VibrationConfig {
return res != null ? res.getFloat(resId) : 0f;
}
- private static float loadFloat(Function<String, String> systemPropertiesGetter,
- String propertyKey, float defaultValue) {
- try {
- return Float.parseFloat(systemPropertiesGetter.apply(propertyKey));
- } catch (Exception e) {
- return defaultValue;
- }
- }
-
private static int loadInteger(@Nullable Resources res, int resId, int defaultValue) {
return res != null ? res.getInteger(resId) : defaultValue;
}
@@ -230,10 +176,8 @@ public class VibrationConfig {
* for each level.
*/
public float getDefaultVibrationScaleLevelGain() {
- if (mDefaultVibrationScaleLevelGain <= 1) {
- return DEFAULT_SCALE_LEVEL_GAIN;
- }
- return mDefaultVibrationScaleLevelGain;
+ // TODO(b/356407380): add device config for this
+ return DEFAULT_SCALE_LEVEL_GAIN;
}
/**
@@ -326,7 +270,6 @@ public class VibrationConfig {
return "VibrationConfig{"
+ "mIgnoreVibrationsOnWirelessCharger=" + mIgnoreVibrationsOnWirelessCharger
+ ", mDefaultVibrationAmplitude=" + mDefaultVibrationAmplitude
- + ", mDefaultVibrationScaleLevelGain=" + mDefaultVibrationScaleLevelGain
+ ", mHapticChannelMaxVibrationAmplitude=" + mHapticChannelMaxVibrationAmplitude
+ ", mRampStepDurationMs=" + mRampStepDurationMs
+ ", mRampDownDurationMs=" + mRampDownDurationMs
@@ -353,7 +296,6 @@ public class VibrationConfig {
pw.increaseIndent();
pw.println("ignoreVibrationsOnWirelessCharger = " + mIgnoreVibrationsOnWirelessCharger);
pw.println("defaultVibrationAmplitude = " + mDefaultVibrationAmplitude);
- pw.println("defaultVibrationScaleLevelGain = " + mDefaultVibrationScaleLevelGain);
pw.println("hapticChannelMaxAmplitude = " + mHapticChannelMaxVibrationAmplitude);
pw.println("rampStepDurationMs = " + mRampStepDurationMs);
pw.println("rampDownDurationMs = " + mRampDownDurationMs);
diff --git a/core/java/android/permission/flags.aconfig b/core/java/android/permission/flags.aconfig
index 6c486dbfd7a2..991611a1af10 100644
--- a/core/java/android/permission/flags.aconfig
+++ b/core/java/android/permission/flags.aconfig
@@ -249,3 +249,11 @@ flag {
description: "This flag is used to enabled the Wallet Role s icon fetching from manifest property"
bug: "349942654"
}
+
+flag {
+ name: "replace_body_sensors_permission_enabled"
+ is_exported: true
+ namespace: "android_health_services"
+ description: "This flag is used to enable replacing permission BODY_SENSORS(and BODY_SENSORS_BACKGROUND) with granular health permission READ_HEART_RATE(and READ_HEALTH_DATA_IN_BACKGROUND)"
+ bug: "364638912"
+}
diff --git a/core/tests/bugreports/Android.bp b/core/tests/bugreports/Android.bp
index c1022a54207d..664d54d374b4 100644
--- a/core/tests/bugreports/Android.bp
+++ b/core/tests/bugreports/Android.bp
@@ -43,3 +43,10 @@ filegroup {
name: "bugreport_artifacts",
srcs: ["config/test-sysconfig.xml"],
}
+
+test_module_config {
+ name: "BugreportManagerTestCases_android_server_os",
+ base: "BugreportManagerTestCases",
+ test_suites: ["general-tests"],
+ exclude_annotations: ["androidx.test.filters.LargeTest"],
+}
diff --git a/core/tests/coretests/Android.bp b/core/tests/coretests/Android.bp
index 5111d2d1e044..d98836f8ce20 100644
--- a/core/tests/coretests/Android.bp
+++ b/core/tests/coretests/Android.bp
@@ -303,6 +303,7 @@ test_module_config {
name: "FrameworksCoreTests_Presubmit",
base: "FrameworksCoreTests",
test_suites: [
+ "automotive-tests",
"device-tests",
"device-platinum-tests",
],
@@ -313,6 +314,7 @@ test_module_config {
name: "FrameworksCoreTests_inputmethod",
base: "FrameworksCoreTests",
test_suites: [
+ "automotive-tests",
"device-tests",
"device-platinum-tests",
],
@@ -327,6 +329,7 @@ test_module_config {
name: "FrameworksCoreTests_context",
base: "FrameworksCoreTests",
test_suites: [
+ "automotive-tests",
"device-tests",
"device-platinum-tests",
],
@@ -337,6 +340,7 @@ test_module_config {
name: "FrameworksCoreTests_keyguard_manager",
base: "FrameworksCoreTests",
test_suites: [
+ "automotive-tests",
"device-tests",
"device-platinum-tests",
],
@@ -347,6 +351,7 @@ test_module_config {
name: "FrameworksCoreTests_property_invalidated_cache",
base: "FrameworksCoreTests",
test_suites: [
+ "automotive-tests",
"device-tests",
"device-platinum-tests",
],
@@ -357,6 +362,7 @@ test_module_config {
name: "FrameworksCoreTests_android_content",
base: "FrameworksCoreTests",
test_suites: [
+ "automotive-tests",
"device-tests",
"device-platinum-tests",
],
@@ -371,6 +377,7 @@ test_module_config {
name: "FrameworksCoreTests_sqlite",
base: "FrameworksCoreTests",
test_suites: [
+ "automotive-tests",
"device-tests",
"device-platinum-tests",
],
@@ -381,6 +388,7 @@ test_module_config {
name: "FrameworksCoreTests_android_net",
base: "FrameworksCoreTests",
test_suites: [
+ "automotive-tests",
"device-tests",
"device-platinum-tests",
],
@@ -392,6 +400,7 @@ test_module_config {
name: "FrameworksCoreTests_battery_stats",
base: "FrameworksCoreTests",
test_suites: [
+ "automotive-tests",
"device-tests",
"device-platinum-tests",
],
@@ -403,6 +412,7 @@ test_module_config {
name: "FrameworksCoreTests_environment",
base: "FrameworksCoreTests",
test_suites: [
+ "automotive-tests",
"device-tests",
"device-platinum-tests",
],
@@ -413,6 +423,7 @@ test_module_config {
name: "FrameworksCoreTests_util_data_charset",
base: "FrameworksCoreTests",
test_suites: [
+ "automotive-tests",
"device-tests",
"device-platinum-tests",
],
@@ -426,6 +437,7 @@ test_module_config {
name: "FrameworksCoreTests_xml",
base: "FrameworksCoreTests",
test_suites: [
+ "automotive-tests",
"device-tests",
"device-platinum-tests",
],
@@ -439,6 +451,7 @@ test_module_config {
name: "FrameworksCoreTests_util_apk",
base: "FrameworksCoreTests",
test_suites: [
+ "automotive-tests",
"device-tests",
"device-platinum-tests",
],
@@ -449,6 +462,7 @@ test_module_config {
name: "FrameworksCoreTests_textclassifier",
base: "FrameworksCoreTests",
test_suites: [
+ "automotive-tests",
"device-tests",
"device-platinum-tests",
],
@@ -460,6 +474,7 @@ test_module_config {
name: "FrameworksCoreTests_internal_app",
base: "FrameworksCoreTests",
test_suites: [
+ "automotive-tests",
"device-tests",
"device-platinum-tests",
],
@@ -474,6 +489,7 @@ test_module_config {
name: "FrameworksCoreTests_internal_content",
base: "FrameworksCoreTests",
test_suites: [
+ "automotive-tests",
"device-tests",
"device-platinum-tests",
],
@@ -484,6 +500,7 @@ test_module_config {
name: "FrameworksCoreTests_internal_infra",
base: "FrameworksCoreTests",
test_suites: [
+ "automotive-tests",
"device-tests",
"device-platinum-tests",
],
@@ -494,6 +511,7 @@ test_module_config {
name: "FrameworksCoreTests_internal_jank",
base: "FrameworksCoreTests",
test_suites: [
+ "automotive-tests",
"device-tests",
"device-platinum-tests",
],
@@ -504,6 +522,7 @@ test_module_config {
name: "FrameworksCoreTests_internal_os_binder",
base: "FrameworksCoreTests",
test_suites: [
+ "automotive-tests",
"device-tests",
"device-platinum-tests",
],
@@ -515,6 +534,7 @@ test_module_config {
name: "FrameworksCoreTests_internal_os_kernel",
base: "FrameworksCoreTests",
test_suites: [
+ "automotive-tests",
"device-tests",
"device-platinum-tests",
],
@@ -531,6 +551,7 @@ test_module_config {
name: "FrameworksCoreTests_server_power",
base: "FrameworksCoreTests",
test_suites: [
+ "automotive-tests",
"device-tests",
"device-platinum-tests",
],
@@ -541,6 +562,7 @@ test_module_config {
name: "FrameworksCoreTests_internal_security",
base: "FrameworksCoreTests",
test_suites: [
+ "automotive-tests",
"device-tests",
"device-platinum-tests",
],
@@ -552,6 +574,7 @@ test_module_config {
name: "FrameworksCoreTests_internal_util_latency_tracker",
base: "FrameworksCoreTests",
test_suites: [
+ "automotive-tests",
"device-tests",
"device-platinum-tests",
],
@@ -562,6 +585,7 @@ test_module_config {
name: "FrameworksCoreTests_content_capture_options",
base: "FrameworksCoreTests",
test_suites: [
+ "automotive-tests",
"device-tests",
"device-platinum-tests",
],
@@ -572,6 +596,7 @@ test_module_config {
name: "FrameworksCoreTests_android_content_integrity",
base: "FrameworksCoreTests",
test_suites: [
+ "automotive-tests",
"device-tests",
"device-platinum-tests",
],
@@ -582,6 +607,7 @@ test_module_config {
name: "FrameworksCoreTests_android_content_pm_PreSubmit",
base: "FrameworksCoreTests",
test_suites: [
+ "automotive-tests",
"device-tests",
"device-platinum-tests",
],
@@ -593,6 +619,7 @@ test_module_config {
name: "FrameworksCoreTests_android_content_pm_PostSubmit",
base: "FrameworksCoreTests",
test_suites: [
+ "automotive-tests",
"device-tests",
"device-platinum-tests",
],
@@ -604,6 +631,7 @@ test_module_config {
name: "FrameworksCoreTests_android_content_res",
base: "FrameworksCoreTests",
test_suites: [
+ "automotive-tests",
"device-tests",
"device-platinum-tests",
],
@@ -620,6 +648,7 @@ test_module_config {
name: "FrameworksCoreTests_android_content_res_PostSubmit",
base: "FrameworksCoreTests",
test_suites: [
+ "automotive-tests",
"device-tests",
"device-platinum-tests",
],
@@ -631,6 +660,7 @@ test_module_config {
name: "FrameworksCoreTests_android_service",
base: "FrameworksCoreTests",
test_suites: [
+ "automotive-tests",
"device-tests",
"device-platinum-tests",
],
@@ -650,6 +680,7 @@ test_module_config {
name: "FrameworksCoreTests_android_view_contentcapture",
base: "FrameworksCoreTests",
test_suites: [
+ "automotive-tests",
"device-tests",
"device-platinum-tests",
],
@@ -660,6 +691,7 @@ test_module_config {
name: "FrameworksCoreTests_android_view_contentprotection",
base: "FrameworksCoreTests",
test_suites: [
+ "automotive-tests",
"device-tests",
"device-platinum-tests",
],
@@ -670,6 +702,7 @@ test_module_config {
name: "FrameworksCoreTests_com_android_internal_content_Presubmit",
base: "FrameworksCoreTests",
test_suites: [
+ "automotive-tests",
"device-tests",
"device-platinum-tests",
],
@@ -681,6 +714,7 @@ test_module_config {
name: "FrameworksCoreTests_drawable",
base: "FrameworksCoreTests",
test_suites: [
+ "automotive-tests",
"device-tests",
"device-platinum-tests",
],
@@ -691,6 +725,7 @@ test_module_config {
name: "FrameworksCoreTests_accessibility",
base: "FrameworksCoreTests",
test_suites: [
+ "automotive-tests",
"device-tests",
"device-platinum-tests",
],
@@ -705,6 +740,7 @@ test_module_config {
name: "FrameworksCoreTests_usage",
base: "FrameworksCoreTests",
test_suites: [
+ "automotive-tests",
"device-tests",
"device-platinum-tests",
],
@@ -715,6 +751,7 @@ test_module_config {
name: "FrameworksCoreTests_fastdata",
base: "FrameworksCoreTests",
test_suites: [
+ "automotive-tests",
"device-tests",
"device-platinum-tests",
],
@@ -725,6 +762,7 @@ test_module_config {
name: "FrameworksCoreTests_hardware_input",
base: "FrameworksCoreTests",
test_suites: [
+ "automotive-tests",
"device-tests",
"device-platinum-tests",
],
@@ -735,6 +773,7 @@ test_module_config {
name: "FrameworksCoreTests_view_verified",
base: "FrameworksCoreTests",
test_suites: [
+ "automotive-tests",
"device-tests",
"device-platinum-tests",
],
@@ -745,9 +784,34 @@ test_module_config {
}
test_module_config {
+ name: "FrameworksCoreTests_android_net_Presubmit",
+ base: "FrameworksCoreTests",
+ test_suites: [
+ "automotive-tests",
+ "device-platinum-tests",
+ "device-tests",
+ ],
+ include_filters: ["android.net"],
+ include_annotations: ["android.platform.test.annotations.Presubmit"],
+}
+
+test_module_config {
+ name: "FrameworksCoreTests_content_pm_Postsubmit",
+ base: "FrameworksCoreTests",
+ test_suites: [
+ "automotive-tests",
+ "device-platinum-tests",
+ "device-tests",
+ ],
+ include_filters: ["android.content.pm."],
+ include_annotations: ["android.platform.test.annotations.Postsubmit"],
+}
+
+test_module_config {
name: "FrameworksCoreTests_jank",
base: "FrameworksCoreTests",
test_suites: [
+ "automotive-tests",
"device-tests",
"device-platinum-tests",
],
@@ -762,6 +826,7 @@ test_module_config {
name: "FrameworksCoreTests_Platinum",
base: "FrameworksCoreTests",
test_suites: [
+ "automotive-tests",
"device-tests",
"device-platinum-tests",
],
diff --git a/core/tests/vibrator/src/android/os/vibrator/VibrationConfigTest.java b/core/tests/vibrator/src/android/os/vibrator/VibrationConfigTest.java
deleted file mode 100644
index a2ff9d77674a..000000000000
--- a/core/tests/vibrator/src/android/os/vibrator/VibrationConfigTest.java
+++ /dev/null
@@ -1,100 +0,0 @@
-/*
- * Copyright (C) 2024 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.os.vibrator;
-
-import static com.google.common.truth.Truth.assertThat;
-
-import static org.mockito.Mockito.when;
-
-import android.content.res.Resources;
-
-import com.android.internal.R;
-
-import org.junit.Rule;
-import org.junit.Test;
-import org.mockito.Mock;
-import org.mockito.junit.MockitoJUnit;
-import org.mockito.junit.MockitoRule;
-
-import java.util.HashMap;
-import java.util.Map;
-
-public class VibrationConfigTest {
-
- @Rule
- public MockitoRule rule = MockitoJUnit.rule();
-
- @Mock
- private Resources mResourcesMock;
-
- private final Map<String, String> mSystemProperties = new HashMap<>();
-
- @Test
- public void getDefaultVibrationAmplitude_returnsConfiguredAmplitude() {
- when(mResourcesMock.getInteger(R.integer.config_defaultVibrationAmplitude)).thenReturn(1);
- assertThat(createConfig().getDefaultVibrationAmplitude()).isEqualTo(1);
-
- when(mResourcesMock.getInteger(R.integer.config_defaultVibrationAmplitude)).thenReturn(123);
- assertThat(createConfig().getDefaultVibrationAmplitude()).isEqualTo(123);
-
- when(mResourcesMock.getInteger(R.integer.config_defaultVibrationAmplitude)).thenReturn(255);
- assertThat(createConfig().getDefaultVibrationAmplitude()).isEqualTo(255);
- }
-
- @Test
- public void getDefaultVibrationAmplitude_invalidValue_returnsMaxAmplitude() {
- when(mResourcesMock.getInteger(R.integer.config_defaultVibrationAmplitude)).thenReturn(-1);
- assertThat(createConfig().getDefaultVibrationAmplitude()).isEqualTo(255);
-
- when(mResourcesMock.getInteger(R.integer.config_defaultVibrationAmplitude)).thenReturn(0);
- assertThat(createConfig().getDefaultVibrationAmplitude()).isEqualTo(255);
-
- when(mResourcesMock.getInteger(R.integer.config_defaultVibrationAmplitude)).thenReturn(500);
- assertThat(createConfig().getDefaultVibrationAmplitude()).isEqualTo(255);
- }
-
- @Test
- public void getDefaultVibrationScaleLevelGain_returnsConfiguredGain() {
- mSystemProperties.put(VibrationConfig.SCALE_LEVEL_GAIN_SYSTEM_PROPERTY, "1.2");
- assertThat(createConfig().getDefaultVibrationScaleLevelGain()).isEqualTo(1.2f);
-
- mSystemProperties.put(VibrationConfig.SCALE_LEVEL_GAIN_SYSTEM_PROPERTY, "2");
- assertThat(createConfig().getDefaultVibrationScaleLevelGain()).isEqualTo(2f);
- }
-
- @Test
- public void getDefaultVibrationScaleLevelGain_invalidValue_returnsFixedScaleGain() {
- mSystemProperties.put(VibrationConfig.SCALE_LEVEL_GAIN_SYSTEM_PROPERTY, "");
- assertThat(createConfig().getDefaultVibrationScaleLevelGain()).isEqualTo(1.4f);
-
- mSystemProperties.put(VibrationConfig.SCALE_LEVEL_GAIN_SYSTEM_PROPERTY, "invalid");
- assertThat(createConfig().getDefaultVibrationScaleLevelGain()).isEqualTo(1.4f);
-
- mSystemProperties.put(VibrationConfig.SCALE_LEVEL_GAIN_SYSTEM_PROPERTY, "-1");
- assertThat(createConfig().getDefaultVibrationScaleLevelGain()).isEqualTo(1.4f);
-
- mSystemProperties.put(VibrationConfig.SCALE_LEVEL_GAIN_SYSTEM_PROPERTY, "0.5");
- assertThat(createConfig().getDefaultVibrationScaleLevelGain()).isEqualTo(1.4f);
-
- mSystemProperties.put(VibrationConfig.SCALE_LEVEL_GAIN_SYSTEM_PROPERTY, "1.0");
- assertThat(createConfig().getDefaultVibrationScaleLevelGain()).isEqualTo(1.4f);
- }
-
- private VibrationConfig createConfig() {
- return new VibrationConfig(mResourcesMock, mSystemProperties::get);
- }
-}
diff --git a/libs/WindowManager/Jetpack/tests/unittest/Android.bp b/libs/WindowManager/Jetpack/tests/unittest/Android.bp
index bc46b70793cd..bd430c0e610b 100644
--- a/libs/WindowManager/Jetpack/tests/unittest/Android.bp
+++ b/libs/WindowManager/Jetpack/tests/unittest/Android.bp
@@ -62,3 +62,10 @@ android_test {
enabled: false,
},
}
+
+test_module_config {
+ name: "WMJetpackUnitTests_Presubmit",
+ base: "WMJetpackUnitTests",
+ test_suites: ["device-tests"],
+ include_annotations: ["android.platform.test.annotations.Presubmit"],
+}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/common/pip/PhonePipKeepClearAlgorithm.java b/libs/WindowManager/Shell/src/com/android/wm/shell/common/pip/PhonePipKeepClearAlgorithm.java
index 133242d15822..a27caf879e8a 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/common/pip/PhonePipKeepClearAlgorithm.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/common/pip/PhonePipKeepClearAlgorithm.java
@@ -57,6 +57,12 @@ public class PhonePipKeepClearAlgorithm implements PipKeepClearAlgorithmInterfac
Rect startingBounds = pipBoundsState.getBounds().isEmpty()
? pipBoundsAlgorithm.getEntryDestinationBoundsIgnoringKeepClearAreas()
: pipBoundsState.getBounds();
+ // If IME is not showing and restore bounds (pre-IME bounds) is not empty, we should set PiP
+ // bounds to the restore bounds.
+ if (!pipBoundsState.isImeShowing() && !pipBoundsState.getRestoreBounds().isEmpty()) {
+ startingBounds.set(pipBoundsState.getRestoreBounds());
+ pipBoundsState.clearRestoreBounds();
+ }
Rect insets = new Rect();
pipBoundsAlgorithm.getInsetBounds(insets);
if (pipBoundsState.isImeShowing()) {
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/common/pip/PipBoundsState.java b/libs/WindowManager/Shell/src/com/android/wm/shell/common/pip/PipBoundsState.java
index 140d7765e5c1..c487f7543dcf 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/common/pip/PipBoundsState.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/common/pip/PipBoundsState.java
@@ -86,6 +86,7 @@ public class PipBoundsState {
@NonNull private final Rect mExpandedBounds = new Rect();
@NonNull private final Rect mNormalMovementBounds = new Rect();
@NonNull private final Rect mExpandedMovementBounds = new Rect();
+ @NonNull private final Rect mRestoreBounds = new Rect();
@NonNull private final PipDisplayLayoutState mPipDisplayLayoutState;
private final Point mMaxSize = new Point();
private final Point mMinSize = new Point();
@@ -404,6 +405,10 @@ public class PipBoundsState {
public void setImeVisibility(boolean imeShowing, int imeHeight) {
mIsImeShowing = imeShowing;
mImeHeight = imeHeight;
+ // If IME is showing, save the current PiP bounds in case we need to restore it later.
+ if (mIsImeShowing) {
+ mRestoreBounds.set(getBounds());
+ }
}
/** Returns whether the IME is currently showing. */
@@ -411,6 +416,16 @@ public class PipBoundsState {
return mIsImeShowing;
}
+ /** Returns the bounds to restore PiP to (bounds before IME was expanded). */
+ public Rect getRestoreBounds() {
+ return mRestoreBounds;
+ }
+
+ /** Sets mRestoreBounds to (0,0,0,0). */
+ public void clearRestoreBounds() {
+ mRestoreBounds.setEmpty();
+ }
+
/** Returns the IME height. */
public int getImeHeight() {
return mImeHeight;
@@ -521,6 +536,10 @@ public class PipBoundsState {
/** Set whether the user has resized the PIP. */
public void setHasUserResizedPip(boolean hasUserResizedPip) {
mHasUserResizedPip = hasUserResizedPip;
+ // If user resized PiP while IME is showing, clear the pre-IME restore bounds.
+ if (hasUserResizedPip && isImeShowing()) {
+ clearRestoreBounds();
+ }
}
/** Returns whether the user has moved the PIP. */
@@ -531,6 +550,10 @@ public class PipBoundsState {
/** Set whether the user has moved the PIP. */
public void setHasUserMovedPip(boolean hasUserMovedPip) {
mHasUserMovedPip = hasUserMovedPip;
+ // If user moved PiP while IME is showing, clear the pre-IME restore bounds.
+ if (hasUserMovedPip && isImeShowing()) {
+ clearRestoreBounds();
+ }
}
/**
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/pip/phone/PhonePipKeepClearAlgorithmTest.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/pip/phone/PhonePipKeepClearAlgorithmTest.java
index 8c7b47ea7d84..e3798e92c092 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/pip/phone/PhonePipKeepClearAlgorithmTest.java
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/pip/phone/PhonePipKeepClearAlgorithmTest.java
@@ -109,6 +109,7 @@ public class PhonePipKeepClearAlgorithmTest extends ShellTestCase {
final Rect pipBounds = new Rect(0, 0, 100, 100);
final Rect keepClearRect = new Rect(50, 50, 150, 150);
when(mMockPipBoundsState.getBounds()).thenReturn(pipBounds);
+ when(mMockPipBoundsState.getRestoreBounds()).thenReturn(new Rect(0, 0, 0, 0));
when(mMockPipBoundsState.getRestrictedKeepClearAreas()).thenReturn(Set.of(keepClearRect));
doAnswer(invocation -> {
Rect arg0 = invocation.getArgument(0);
@@ -127,6 +128,7 @@ public class PhonePipKeepClearAlgorithmTest extends ShellTestCase {
final Rect pipBounds = new Rect(0, 0, 100, 100);
final Rect keepClearRect = new Rect(100, 100, 150, 150);
when(mMockPipBoundsState.getBounds()).thenReturn(pipBounds);
+ when(mMockPipBoundsState.getRestoreBounds()).thenReturn(new Rect(0, 0, 0, 0));
when(mMockPipBoundsState.getRestrictedKeepClearAreas()).thenReturn(Set.of(keepClearRect));
doAnswer(invocation -> {
Rect arg0 = invocation.getArgument(0);
@@ -145,6 +147,7 @@ public class PhonePipKeepClearAlgorithmTest extends ShellTestCase {
final Rect pipBounds = new Rect(0, 0, 100, 100);
final Rect keepClearRect = new Rect(50, 50, 150, 150);
when(mMockPipBoundsState.getBounds()).thenReturn(pipBounds);
+ when(mMockPipBoundsState.getRestoreBounds()).thenReturn(new Rect(0, 0, 0, 0));
when(mMockPipBoundsState.isStashed()).thenReturn(true);
when(mMockPipBoundsState.getRestrictedKeepClearAreas()).thenReturn(Set.of(keepClearRect));
doAnswer(invocation -> {
@@ -164,6 +167,7 @@ public class PhonePipKeepClearAlgorithmTest extends ShellTestCase {
final Rect pipBounds = new Rect(0, 0, 100, 100);
final Rect keepClearRect = new Rect(100, 100, 150, 150);
when(mMockPipBoundsState.getBounds()).thenReturn(pipBounds);
+ when(mMockPipBoundsState.getRestoreBounds()).thenReturn(new Rect(0, 0, 0, 0));
when(mMockPipBoundsState.isStashed()).thenReturn(true);
when(mMockPipBoundsState.getRestrictedKeepClearAreas()).thenReturn(Set.of(keepClearRect));
doAnswer(invocation -> {
@@ -185,6 +189,7 @@ public class PhonePipKeepClearAlgorithmTest extends ShellTestCase {
final Rect expected = new Rect(
0, DISPLAY_BOUNDS.bottom - 100, 100, DISPLAY_BOUNDS.bottom);
when(mMockPipBoundsState.getBounds()).thenReturn(pipBounds);
+ when(mMockPipBoundsState.getRestoreBounds()).thenReturn(new Rect(0, 0, 0, 0));
doAnswer(invocation -> {
Rect arg0 = invocation.getArgument(0);
arg0.set(DISPLAY_BOUNDS);
@@ -205,6 +210,7 @@ public class PhonePipKeepClearAlgorithmTest extends ShellTestCase {
final Rect expected = new Rect(
0, DISPLAY_BOUNDS.bottom - 100, 100, DISPLAY_BOUNDS.bottom);
when(mMockPipBoundsState.getBounds()).thenReturn(pipBounds);
+ when(mMockPipBoundsState.getRestoreBounds()).thenReturn(new Rect(0, 0, 0, 0));
doAnswer(invocation -> {
Rect arg0 = invocation.getArgument(0);
arg0.set(DISPLAY_BOUNDS);
@@ -227,6 +233,7 @@ public class PhonePipKeepClearAlgorithmTest extends ShellTestCase {
DISPLAY_BOUNDS.right - 100, DISPLAY_BOUNDS.bottom - 100,
DISPLAY_BOUNDS.right, DISPLAY_BOUNDS.bottom);
when(mMockPipBoundsState.getBounds()).thenReturn(pipBounds);
+ when(mMockPipBoundsState.getRestoreBounds()).thenReturn(new Rect(0, 0, 0, 0));
doAnswer(invocation -> {
Rect arg0 = invocation.getArgument(0);
arg0.set(DISPLAY_BOUNDS);
@@ -249,6 +256,7 @@ public class PhonePipKeepClearAlgorithmTest extends ShellTestCase {
DISPLAY_BOUNDS.right - 100, DISPLAY_BOUNDS.bottom - 100,
DISPLAY_BOUNDS.right, DISPLAY_BOUNDS.bottom);
when(mMockPipBoundsState.getBounds()).thenReturn(pipBounds);
+ when(mMockPipBoundsState.getRestoreBounds()).thenReturn(new Rect(0, 0, 0, 0));
doAnswer(invocation -> {
Rect arg0 = invocation.getArgument(0);
arg0.set(DISPLAY_BOUNDS);
@@ -269,6 +277,7 @@ public class PhonePipKeepClearAlgorithmTest extends ShellTestCase {
final Rect expected = new Rect(
0, DISPLAY_BOUNDS.bottom - 100, 100, DISPLAY_BOUNDS.bottom);
when(mMockPipBoundsState.getBounds()).thenReturn(pipBounds);
+ when(mMockPipBoundsState.getRestoreBounds()).thenReturn(new Rect(0, 0, 0, 0));
when(mMockPipBoundsState.isStashed()).thenReturn(true);
doAnswer(invocation -> {
Rect arg0 = invocation.getArgument(0);
@@ -289,6 +298,7 @@ public class PhonePipKeepClearAlgorithmTest extends ShellTestCase {
final Rect expected = new Rect(
0, DISPLAY_BOUNDS.bottom - 100, 100, DISPLAY_BOUNDS.bottom);
when(mMockPipBoundsState.getBounds()).thenReturn(pipBounds);
+ when(mMockPipBoundsState.getRestoreBounds()).thenReturn(new Rect(0, 0, 0, 0));
when(mMockPipBoundsState.isStashed()).thenReturn(true);
doAnswer(invocation -> {
Rect arg0 = invocation.getArgument(0);
@@ -301,4 +311,40 @@ public class PhonePipKeepClearAlgorithmTest extends ShellTestCase {
assertEquals(expected, outBounds);
}
+
+ @Test
+ public void adjust_restoreBoundsPresent_appliesRestoreBounds() {
+ final Rect pipBounds = new Rect(0, 0, 100, 100);
+ final Rect restoreBounds = new Rect(50, 50, 150, 150);
+ when(mMockPipBoundsState.getBounds()).thenReturn(pipBounds);
+ when(mMockPipBoundsState.getRestoreBounds()).thenReturn(restoreBounds);
+ when(mMockPipBoundsState.hasUserMovedPip()).thenReturn(true);
+ doAnswer(invocation -> {
+ Rect arg0 = invocation.getArgument(0);
+ arg0.set(DISPLAY_BOUNDS);
+ return null;
+ }).when(mMockPipBoundsAlgorithm).getInsetBounds(any(Rect.class));
+
+ final Rect outBounds = mPipKeepClearAlgorithm.adjust(
+ mMockPipBoundsState, mMockPipBoundsAlgorithm);
+ assertEquals(restoreBounds, outBounds);
+ }
+
+ @Test
+ public void adjust_restoreBoundsCleared_boundsUnchanged() {
+ final Rect pipBounds = new Rect(0, 0, 100, 100);
+ final Rect restoreBounds = new Rect(0, 0, 0, 0);
+ when(mMockPipBoundsState.getBounds()).thenReturn(pipBounds);
+ when(mMockPipBoundsState.getRestoreBounds()).thenReturn(restoreBounds);
+ when(mMockPipBoundsState.hasUserMovedPip()).thenReturn(true);
+ doAnswer(invocation -> {
+ Rect arg0 = invocation.getArgument(0);
+ arg0.set(DISPLAY_BOUNDS);
+ return null;
+ }).when(mMockPipBoundsAlgorithm).getInsetBounds(any(Rect.class));
+
+ final Rect outBounds = mPipKeepClearAlgorithm.adjust(
+ mMockPipBoundsState, mMockPipBoundsAlgorithm);
+ assertEquals(pipBounds, outBounds);
+ }
}
diff --git a/media/tests/LoudnessCodecApiTest/Android.bp b/media/tests/LoudnessCodecApiTest/Android.bp
index 5ca0fc9661c2..5d1153d93b4f 100644
--- a/media/tests/LoudnessCodecApiTest/Android.bp
+++ b/media/tests/LoudnessCodecApiTest/Android.bp
@@ -25,3 +25,10 @@ android_test {
resource_dirs: ["res"],
test_suites: ["device-tests"],
}
+
+test_module_config {
+ name: "LoudnessCodecApiTest_Presubmit",
+ base: "LoudnessCodecApiTest",
+ test_suites: ["device-tests"],
+ include_annotations: ["android.platform.test.annotations.Presubmit"],
+}
diff --git a/native/android/libandroid.map.txt b/native/android/libandroid.map.txt
index 346c87daec87..25c063d6ccd8 100644
--- a/native/android/libandroid.map.txt
+++ b/native/android/libandroid.map.txt
@@ -367,6 +367,7 @@ LIBANDROID_PLATFORM {
APerformanceHint_sendHint;
APerformanceHint_getThreadIds;
APerformanceHint_createSessionInternal;
+ APerformanceHint_setUseFMQForTesting;
extern "C++" {
ASurfaceControl_registerSurfaceStatsListener*;
ASurfaceControl_unregisterSurfaceStatsListener*;
diff --git a/native/android/performance_hint.cpp b/native/android/performance_hint.cpp
index e91c7a9ecda8..095d7d1145ae 100644
--- a/native/android/performance_hint.cpp
+++ b/native/android/performance_hint.cpp
@@ -16,10 +16,14 @@
#define LOG_TAG "perf_hint"
+#include <aidl/android/hardware/power/ChannelConfig.h>
+#include <aidl/android/hardware/power/ChannelMessage.h>
+#include <aidl/android/hardware/power/SessionConfig.h>
#include <aidl/android/hardware/power/SessionHint.h>
#include <aidl/android/hardware/power/SessionMode.h>
#include <aidl/android/hardware/power/SessionTag.h>
#include <aidl/android/hardware/power/WorkDuration.h>
+#include <aidl/android/hardware/power/WorkDurationFixedV1.h>
#include <aidl/android/os/IHintManager.h>
#include <aidl/android/os/IHintSession.h>
#include <android-base/stringprintf.h>
@@ -28,6 +32,8 @@
#include <android/binder_status.h>
#include <android/performance_hint.h>
#include <android/trace.h>
+#include <android_os.h>
+#include <fmq/AidlMessageQueue.h>
#include <inttypes.h>
#include <performance_hint_private.h>
#include <utils/SystemClock.h>
@@ -45,6 +51,10 @@ using namespace std::chrono_literals;
// Namespace for AIDL types coming from the PowerHAL
namespace hal = aidl::android::hardware::power;
+using ::aidl::android::hardware::common::fmq::SynchronizedReadWrite;
+using HalChannelMessageContents = hal::ChannelMessage::ChannelMessageContents;
+using HalMessageQueue = ::android::AidlMessageQueue<hal::ChannelMessage, SynchronizedReadWrite>;
+using HalFlagQueue = ::android::AidlMessageQueue<int8_t, SynchronizedReadWrite>;
using android::base::StringPrintf;
struct APerformanceHintSession;
@@ -54,18 +64,60 @@ struct AWorkDuration : public hal::WorkDuration {};
// Shared lock for the whole PerformanceHintManager and sessions
static std::mutex sHintMutex = std::mutex{};
+class FMQWrapper {
+public:
+ bool isActive();
+ bool isSupported();
+ bool startChannel(IHintManager* manager);
+ void stopChannel(IHintManager* manager);
+ // Number of elements the FMQ can hold
+ bool reportActualWorkDurations(std::optional<hal::SessionConfig>& config,
+ hal::WorkDuration* durations, size_t count) REQUIRES(sHintMutex);
+ bool updateTargetWorkDuration(std::optional<hal::SessionConfig>& config,
+ int64_t targetDurationNanos) REQUIRES(sHintMutex);
+ bool sendHint(std::optional<hal::SessionConfig>& config, SessionHint hint) REQUIRES(sHintMutex);
+ bool setMode(std::optional<hal::SessionConfig>& config, hal::SessionMode, bool enabled)
+ REQUIRES(sHintMutex);
+ void setToken(ndk::SpAIBinder& token);
+ void attemptWake();
+ void setUnsupported();
+
+private:
+ template <HalChannelMessageContents::Tag T, bool urgent = false,
+ class C = HalChannelMessageContents::_at<T>>
+ bool sendMessages(std::optional<hal::SessionConfig>& config, C* message, size_t count = 1)
+ REQUIRES(sHintMutex);
+ template <HalChannelMessageContents::Tag T, class C = HalChannelMessageContents::_at<T>>
+ void writeBuffer(C* message, hal::SessionConfig& config, size_t count) REQUIRES(sHintMutex);
+
+ bool isActiveLocked() REQUIRES(sHintMutex);
+ bool updatePersistentTransaction() REQUIRES(sHintMutex);
+ std::shared_ptr<HalMessageQueue> mQueue GUARDED_BY(sHintMutex) = nullptr;
+ std::shared_ptr<HalFlagQueue> mFlagQueue GUARDED_BY(sHintMutex) = nullptr;
+ // android::hardware::EventFlag* mEventFlag GUARDED_BY(sHintMutex) = nullptr;
+ android::hardware::EventFlag* mEventFlag = nullptr;
+ int32_t mWriteMask;
+ ndk::SpAIBinder mToken = nullptr;
+ // Used to track if operating on the fmq consistently fails
+ bool mCorrupted = false;
+ // Used to keep a persistent transaction open with FMQ to reduce latency a bit
+ size_t mAvailableSlots GUARDED_BY(sHintMutex) = 0;
+ bool mHalSupported = true;
+ HalMessageQueue::MemTransaction mFmqTransaction GUARDED_BY(sHintMutex);
+};
struct APerformanceHintManager {
public:
static APerformanceHintManager* getInstance();
- APerformanceHintManager(std::shared_ptr<IHintManager> service, int64_t preferredRateNanos);
+ APerformanceHintManager(std::shared_ptr<IHintManager>& service, int64_t preferredRateNanos);
APerformanceHintManager() = delete;
- ~APerformanceHintManager() = default;
+ ~APerformanceHintManager();
APerformanceHintSession* createSession(const int32_t* threadIds, size_t size,
int64_t initialTargetWorkDurationNanos,
hal::SessionTag tag = hal::SessionTag::APP);
int64_t getPreferredRateNanos() const;
+ FMQWrapper& getFMQWrapper();
private:
// Necessary to create an empty binder object
@@ -83,6 +135,7 @@ private:
std::shared_ptr<IHintManager> mHintManager;
ndk::SpAIBinder mToken;
const int64_t mPreferredRateNanos;
+ FMQWrapper mFMQWrapper;
};
struct APerformanceHintSession {
@@ -121,40 +174,57 @@ private:
std::vector<int64_t> mLastHintSentTimestamp GUARDED_BY(sHintMutex);
// Cached samples
std::vector<hal::WorkDuration> mActualWorkDurations GUARDED_BY(sHintMutex);
- std::string mSessionName GUARDED_BY(sHintMutex);
+ std::string mSessionName;
static int64_t sIDCounter GUARDED_BY(sHintMutex);
// The most recent set of thread IDs
std::vector<int32_t> mLastThreadIDs GUARDED_BY(sHintMutex);
std::optional<hal::SessionConfig> mSessionConfig GUARDED_BY(sHintMutex);
// Tracing helpers
void traceThreads(std::vector<int32_t>& tids) REQUIRES(sHintMutex);
- void tracePowerEfficient(bool powerEfficient) REQUIRES(sHintMutex);
- void traceActualDuration(int64_t actualDuration) REQUIRES(sHintMutex);
- void traceBatchSize(size_t batchSize) REQUIRES(sHintMutex);
- void traceTargetDuration(int64_t targetDuration) REQUIRES(sHintMutex);
+ void tracePowerEfficient(bool powerEfficient);
+ void traceActualDuration(int64_t actualDuration);
+ void traceBatchSize(size_t batchSize);
+ void traceTargetDuration(int64_t targetDuration);
};
static std::shared_ptr<IHintManager>* gIHintManagerForTesting = nullptr;
-static APerformanceHintManager* gHintManagerForTesting = nullptr;
+static std::shared_ptr<APerformanceHintManager> gHintManagerForTesting = nullptr;
+
+static std::optional<bool> gForceFMQEnabled = std::nullopt;
+
// Start above the int32 range so we don't collide with config sessions
int64_t APerformanceHintSession::sIDCounter = INT32_MAX;
+static FMQWrapper& getFMQ() {
+ return APerformanceHintManager::getInstance()->getFMQWrapper();
+}
+
// ===================================== APerformanceHintManager implementation
-APerformanceHintManager::APerformanceHintManager(std::shared_ptr<IHintManager> manager,
+APerformanceHintManager::APerformanceHintManager(std::shared_ptr<IHintManager>& manager,
int64_t preferredRateNanos)
: mHintManager(std::move(manager)), mPreferredRateNanos(preferredRateNanos) {
static AIBinder_Class* tokenBinderClass =
AIBinder_Class_define("phm_token", tokenStubOnCreate, tokenStubOnDestroy,
tokenStubOnTransact);
mToken = ndk::SpAIBinder(AIBinder_new(tokenBinderClass, nullptr));
+ if (mFMQWrapper.isSupported()) {
+ mFMQWrapper.setToken(mToken);
+ mFMQWrapper.startChannel(mHintManager.get());
+ }
+}
+
+APerformanceHintManager::~APerformanceHintManager() {
+ mFMQWrapper.stopChannel(mHintManager.get());
}
APerformanceHintManager* APerformanceHintManager::getInstance() {
- if (gHintManagerForTesting) return gHintManagerForTesting;
+ if (gHintManagerForTesting) {
+ return gHintManagerForTesting.get();
+ }
if (gIHintManagerForTesting) {
- APerformanceHintManager* manager = create(*gIHintManagerForTesting);
- gIHintManagerForTesting = nullptr;
- return manager;
+ gHintManagerForTesting =
+ std::shared_ptr<APerformanceHintManager>(create(*gIHintManagerForTesting));
+ return gHintManagerForTesting.get();
}
static APerformanceHintManager* instance = create(nullptr);
return instance;
@@ -178,7 +248,7 @@ APerformanceHintManager* APerformanceHintManager::create(std::shared_ptr<IHintMa
if (preferredRateNanos <= 0) {
preferredRateNanos = -1L;
}
- return new APerformanceHintManager(std::move(manager), preferredRateNanos);
+ return new APerformanceHintManager(manager, preferredRateNanos);
}
APerformanceHintSession* APerformanceHintManager::createSession(
@@ -187,15 +257,20 @@ APerformanceHintSession* APerformanceHintManager::createSession(
std::vector<int32_t> tids(threadIds, threadIds + size);
std::shared_ptr<IHintSession> session;
ndk::ScopedAStatus ret;
- std::optional<hal::SessionConfig> sessionConfig;
+ hal::SessionConfig sessionConfig{.id = -1};
ret = mHintManager->createHintSessionWithConfig(mToken, tids, initialTargetWorkDurationNanos,
tag, &sessionConfig, &session);
if (!ret.isOk() || !session) {
+ ALOGE("%s: PerformanceHint cannot create session. %s", __FUNCTION__, ret.getMessage());
return nullptr;
}
auto out = new APerformanceHintSession(mHintManager, std::move(session), mPreferredRateNanos,
- initialTargetWorkDurationNanos, sessionConfig);
+ initialTargetWorkDurationNanos,
+ sessionConfig.id == -1
+ ? std::nullopt
+ : std::make_optional<hal::SessionConfig>(
+ std::move(sessionConfig)));
std::scoped_lock lock(sHintMutex);
out->traceThreads(tids);
out->traceTargetDuration(initialTargetWorkDurationNanos);
@@ -207,8 +282,15 @@ int64_t APerformanceHintManager::getPreferredRateNanos() const {
return mPreferredRateNanos;
}
+FMQWrapper& APerformanceHintManager::getFMQWrapper() {
+ return mFMQWrapper;
+}
+
// ===================================== APerformanceHintSession implementation
+constexpr int kNumEnums =
+ ndk::enum_range<hal::SessionHint>().end() - ndk::enum_range<hal::SessionHint>().begin();
+
APerformanceHintSession::APerformanceHintSession(std::shared_ptr<IHintManager> hintManager,
std::shared_ptr<IHintSession> session,
int64_t preferredRateNanos,
@@ -220,14 +302,11 @@ APerformanceHintSession::APerformanceHintSession(std::shared_ptr<IHintManager> h
mTargetDurationNanos(targetDurationNanos),
mFirstTargetMetTimestamp(0),
mLastTargetMetTimestamp(0),
+ mLastHintSentTimestamp(std::vector<int64_t>(kNumEnums, 0)),
mSessionConfig(sessionConfig) {
if (sessionConfig->id > INT32_MAX) {
ALOGE("Session ID too large, must fit 32-bit integer");
}
- std::scoped_lock lock(sHintMutex);
- constexpr int numEnums =
- ndk::enum_range<hal::SessionHint>().end() - ndk::enum_range<hal::SessionHint>().begin();
- mLastHintSentTimestamp = std::vector<int64_t>(numEnums, 0);
int64_t traceId = sessionConfig.has_value() ? sessionConfig->id : ++sIDCounter;
mSessionName = android::base::StringPrintf("ADPF Session %" PRId64, traceId);
}
@@ -244,19 +323,18 @@ int APerformanceHintSession::updateTargetWorkDuration(int64_t targetDurationNano
ALOGE("%s: targetDurationNanos must be positive", __FUNCTION__);
return EINVAL;
}
- {
- std::scoped_lock lock(sHintMutex);
- if (mTargetDurationNanos == targetDurationNanos) {
- return 0;
- }
+ std::scoped_lock lock(sHintMutex);
+ if (mTargetDurationNanos == targetDurationNanos) {
+ return 0;
}
- ndk::ScopedAStatus ret = mHintSession->updateTargetWorkDuration(targetDurationNanos);
- if (!ret.isOk()) {
- ALOGE("%s: HintSession updateTargetWorkDuration failed: %s", __FUNCTION__,
- ret.getMessage());
- return EPIPE;
+ if (!getFMQ().updateTargetWorkDuration(mSessionConfig, targetDurationNanos)) {
+ ndk::ScopedAStatus ret = mHintSession->updateTargetWorkDuration(targetDurationNanos);
+ if (!ret.isOk()) {
+ ALOGE("%s: HintSession updateTargetWorkDuration failed: %s", __FUNCTION__,
+ ret.getMessage());
+ return EPIPE;
+ }
}
- std::scoped_lock lock(sHintMutex);
mTargetDurationNanos = targetDurationNanos;
/**
* Most of the workload is target_duration dependent, so now clear the cached samples
@@ -292,11 +370,13 @@ int APerformanceHintSession::sendHint(SessionHint hint) {
return 0;
}
- ndk::ScopedAStatus ret = mHintSession->sendHint(hint);
+ if (!getFMQ().sendHint(mSessionConfig, hint)) {
+ ndk::ScopedAStatus ret = mHintSession->sendHint(hint);
- if (!ret.isOk()) {
- ALOGE("%s: HintSession sendHint failed: %s", __FUNCTION__, ret.getMessage());
- return EPIPE;
+ if (!ret.isOk()) {
+ ALOGE("%s: HintSession sendHint failed: %s", __FUNCTION__, ret.getMessage());
+ return EPIPE;
+ }
}
mLastHintSentTimestamp[hint] = now;
return 0;
@@ -369,10 +449,10 @@ int APerformanceHintSession::reportActualWorkDuration(AWorkDuration* workDuratio
int APerformanceHintSession::reportActualWorkDurationInternal(AWorkDuration* workDuration) {
int64_t actualTotalDurationNanos = workDuration->durationNanos;
+ traceActualDuration(workDuration->durationNanos);
int64_t now = uptimeNanos();
workDuration->timeStampNanos = now;
std::scoped_lock lock(sHintMutex);
- traceActualDuration(workDuration->durationNanos);
mActualWorkDurations.push_back(std::move(*workDuration));
if (actualTotalDurationNanos >= mTargetDurationNanos) {
@@ -396,20 +476,177 @@ int APerformanceHintSession::reportActualWorkDurationInternal(AWorkDuration* wor
mLastTargetMetTimestamp = now;
}
- ndk::ScopedAStatus ret = mHintSession->reportActualWorkDuration2(mActualWorkDurations);
- if (!ret.isOk()) {
- ALOGE("%s: HintSession reportActualWorkDuration failed: %s", __FUNCTION__,
- ret.getMessage());
- mFirstTargetMetTimestamp = 0;
- mLastTargetMetTimestamp = 0;
- traceBatchSize(mActualWorkDurations.size());
- return ret.getExceptionCode() == EX_ILLEGAL_ARGUMENT ? EINVAL : EPIPE;
+ if (!getFMQ().reportActualWorkDurations(mSessionConfig, mActualWorkDurations.data(),
+ mActualWorkDurations.size())) {
+ ndk::ScopedAStatus ret = mHintSession->reportActualWorkDuration2(mActualWorkDurations);
+ if (!ret.isOk()) {
+ ALOGE("%s: HintSession reportActualWorkDuration failed: %s", __FUNCTION__,
+ ret.getMessage());
+ mFirstTargetMetTimestamp = 0;
+ mLastTargetMetTimestamp = 0;
+ traceBatchSize(mActualWorkDurations.size());
+ return ret.getExceptionCode() == EX_ILLEGAL_ARGUMENT ? EINVAL : EPIPE;
+ }
}
+
mActualWorkDurations.clear();
traceBatchSize(0);
return 0;
}
+
+// ===================================== FMQ wrapper implementation
+
+bool FMQWrapper::isActive() {
+ std::scoped_lock lock{sHintMutex};
+ return isActiveLocked();
+}
+
+bool FMQWrapper::isActiveLocked() {
+ return mQueue != nullptr;
+}
+
+void FMQWrapper::setUnsupported() {
+ mHalSupported = false;
+}
+
+bool FMQWrapper::isSupported() {
+ if (!mHalSupported) {
+ return false;
+ }
+ // Used for testing
+ if (gForceFMQEnabled.has_value()) {
+ return *gForceFMQEnabled;
+ }
+ return android::os::adpf_use_fmq_channel_fixed();
+}
+
+bool FMQWrapper::startChannel(IHintManager* manager) {
+ if (isSupported() && !isActive()) {
+ std::optional<hal::ChannelConfig> config;
+ auto ret = manager->getSessionChannel(mToken, &config);
+ if (ret.isOk() && config.has_value()) {
+ std::scoped_lock lock{sHintMutex};
+ mQueue = std::make_shared<HalMessageQueue>(config->channelDescriptor, true);
+ if (config->eventFlagDescriptor.has_value()) {
+ mFlagQueue = std::make_shared<HalFlagQueue>(*config->eventFlagDescriptor, true);
+ android::hardware::EventFlag::createEventFlag(mFlagQueue->getEventFlagWord(),
+ &mEventFlag);
+ mWriteMask = config->writeFlagBitmask;
+ }
+ updatePersistentTransaction();
+ } else if (ret.isOk() && !config.has_value()) {
+ ALOGV("FMQ channel enabled but unsupported.");
+ setUnsupported();
+ } else {
+ ALOGE("%s: FMQ channel initialization failed: %s", __FUNCTION__, ret.getMessage());
+ }
+ }
+ return isActive();
+}
+
+void FMQWrapper::stopChannel(IHintManager* manager) {
+ {
+ std::scoped_lock lock{sHintMutex};
+ if (!isActiveLocked()) {
+ return;
+ }
+ mFlagQueue = nullptr;
+ mQueue = nullptr;
+ }
+ manager->closeSessionChannel();
+}
+
+template <HalChannelMessageContents::Tag T, class C>
+void FMQWrapper::writeBuffer(C* message, hal::SessionConfig& config, size_t) {
+ new (mFmqTransaction.getSlot(0)) hal::ChannelMessage{
+ .sessionID = static_cast<int32_t>(config.id),
+ .timeStampNanos = ::android::uptimeNanos(),
+ .data = HalChannelMessageContents::make<T, C>(std::move(*message)),
+ };
+}
+
+template <>
+void FMQWrapper::writeBuffer<HalChannelMessageContents::workDuration>(hal::WorkDuration* messages,
+ hal::SessionConfig& config,
+ size_t count) {
+ for (size_t i = 0; i < count; ++i) {
+ hal::WorkDuration& message = messages[i];
+ new (mFmqTransaction.getSlot(i)) hal::ChannelMessage{
+ .sessionID = static_cast<int32_t>(config.id),
+ .timeStampNanos =
+ (i == count - 1) ? ::android::uptimeNanos() : message.timeStampNanos,
+ .data = HalChannelMessageContents::make<HalChannelMessageContents::workDuration,
+ hal::WorkDurationFixedV1>({
+ .durationNanos = message.cpuDurationNanos,
+ .workPeriodStartTimestampNanos = message.workPeriodStartTimestampNanos,
+ .cpuDurationNanos = message.cpuDurationNanos,
+ .gpuDurationNanos = message.gpuDurationNanos,
+ }),
+ };
+ }
+}
+
+template <HalChannelMessageContents::Tag T, bool urgent, class C>
+bool FMQWrapper::sendMessages(std::optional<hal::SessionConfig>& config, C* message, size_t count) {
+ if (!isActiveLocked() || !config.has_value() || mCorrupted) {
+ return false;
+ }
+ // If we didn't reserve enough space, try re-creating the transaction
+ if (count > mAvailableSlots) {
+ if (!updatePersistentTransaction()) {
+ return false;
+ }
+ // If we actually don't have enough space, give up
+ if (count > mAvailableSlots) {
+ return false;
+ }
+ }
+ writeBuffer<T, C>(message, *config, count);
+ mQueue->commitWrite(count);
+ mEventFlag->wake(mWriteMask);
+ // Re-create the persistent transaction after writing
+ updatePersistentTransaction();
+ return true;
+}
+
+void FMQWrapper::setToken(ndk::SpAIBinder& token) {
+ mToken = token;
+}
+
+bool FMQWrapper::updatePersistentTransaction() {
+ mAvailableSlots = mQueue->availableToWrite();
+ if (mAvailableSlots > 0 && !mQueue->beginWrite(mAvailableSlots, &mFmqTransaction)) {
+ ALOGE("ADPF FMQ became corrupted, falling back to binder calls!");
+ mCorrupted = true;
+ return false;
+ }
+ return true;
+}
+
+bool FMQWrapper::reportActualWorkDurations(std::optional<hal::SessionConfig>& config,
+ hal::WorkDuration* durations, size_t count) {
+ return sendMessages<HalChannelMessageContents::workDuration>(config, durations, count);
+}
+
+bool FMQWrapper::updateTargetWorkDuration(std::optional<hal::SessionConfig>& config,
+ int64_t targetDurationNanos) {
+ return sendMessages<HalChannelMessageContents::targetDuration>(config, &targetDurationNanos);
+}
+
+bool FMQWrapper::sendHint(std::optional<hal::SessionConfig>& config, SessionHint hint) {
+ return sendMessages<HalChannelMessageContents::hint>(config,
+ reinterpret_cast<hal::SessionHint*>(
+ &hint));
+}
+
+bool FMQWrapper::setMode(std::optional<hal::SessionConfig>& config, hal::SessionMode mode,
+ bool enabled) {
+ hal::ChannelMessage::ChannelMessageContents::SessionModeSetter modeObj{.modeInt = mode,
+ .enabled = enabled};
+ return sendMessages<HalChannelMessageContents::mode, true>(config, &modeObj);
+}
+
// ===================================== Tracing helpers
void APerformanceHintSession::traceThreads(std::vector<int32_t>& tids) {
@@ -585,7 +822,12 @@ void AWorkDuration_setActualGpuDurationNanos(AWorkDuration* aWorkDuration,
}
void APerformanceHint_setIHintManagerForTesting(void* iManager) {
- delete gHintManagerForTesting;
- gHintManagerForTesting = nullptr;
+ if (iManager == nullptr) {
+ gHintManagerForTesting = nullptr;
+ }
gIHintManagerForTesting = static_cast<std::shared_ptr<IHintManager>*>(iManager);
}
+
+void APerformanceHint_setUseFMQForTesting(bool enabled) {
+ gForceFMQEnabled = enabled;
+}
diff --git a/native/android/tests/performance_hint/Android.bp b/native/android/tests/performance_hint/Android.bp
index 608d5d8a923a..f6f1da1eed79 100644
--- a/native/android/tests/performance_hint/Android.bp
+++ b/native/android/tests/performance_hint/Android.bp
@@ -36,10 +36,13 @@ cc_test {
srcs: ["PerformanceHintNativeTest.cpp"],
shared_libs: [
+ "android.hardware.common.fmq-V1-ndk",
"libandroid",
- "liblog",
"libbinder",
"libbinder_ndk",
+ "libcutils",
+ "libfmq",
+ "liblog",
"libpowermanager",
"libutils",
],
@@ -56,8 +59,8 @@ cc_test {
],
cflags: [
- "-Werror",
"-Wall",
+ "-Werror",
],
header_libs: [
diff --git a/native/android/tests/performance_hint/PerformanceHintNativeTest.cpp b/native/android/tests/performance_hint/PerformanceHintNativeTest.cpp
index d19fa98f1171..9de3a6f525e6 100644
--- a/native/android/tests/performance_hint/PerformanceHintNativeTest.cpp
+++ b/native/android/tests/performance_hint/PerformanceHintNativeTest.cpp
@@ -24,6 +24,7 @@
#include <android/binder_manager.h>
#include <android/binder_status.h>
#include <android/performance_hint.h>
+#include <fmq/AidlMessageQueue.h>
#include <gmock/gmock.h>
#include <gtest/gtest.h>
#include <performance_hint_private.h>
@@ -31,11 +32,16 @@
#include <memory>
#include <vector>
+using namespace std::chrono_literals;
namespace hal = aidl::android::hardware::power;
using aidl::android::os::IHintManager;
using aidl::android::os::IHintSession;
using ndk::ScopedAStatus;
using ndk::SpAIBinder;
+using HalChannelMessageContents = hal::ChannelMessage::ChannelMessageContents;
+
+using ::aidl::android::hardware::common::fmq::SynchronizedReadWrite;
+using HalFlagQueue = ::android::AidlMessageQueue<int8_t, SynchronizedReadWrite>;
using namespace android;
using namespace testing;
@@ -44,7 +50,7 @@ class MockIHintManager : public IHintManager {
public:
MOCK_METHOD(ScopedAStatus, createHintSessionWithConfig,
(const SpAIBinder& token, const ::std::vector<int32_t>& tids, int64_t durationNanos,
- hal::SessionTag tag, std::optional<hal::SessionConfig>* config,
+ hal::SessionTag tag, hal::SessionConfig* config,
std::shared_ptr<IHintSession>* _aidl_return),
(override));
MOCK_METHOD(ScopedAStatus, getHintSessionPreferredRate, (int64_t * _aidl_return), (override));
@@ -56,7 +62,9 @@ public:
(const std::shared_ptr<IHintSession>& hintSession, ::std::vector<int32_t>* tids),
(override));
MOCK_METHOD(ScopedAStatus, getSessionChannel,
- (const ::ndk::SpAIBinder& in_token, hal::ChannelConfig* _aidl_return), (override));
+ (const ::ndk::SpAIBinder& in_token,
+ std::optional<hal::ChannelConfig>* _aidl_return),
+ (override));
MOCK_METHOD(ScopedAStatus, closeSessionChannel, (), (override));
MOCK_METHOD(SpAIBinder, asBinder, (), (override));
MOCK_METHOD(bool, isRemote, (), (override));
@@ -92,10 +100,12 @@ public:
}
APerformanceHintManager* createManager() {
+ APerformanceHint_setUseFMQForTesting(mUsingFMQ);
ON_CALL(*mMockIHintManager, getHintSessionPreferredRate(_))
.WillByDefault(DoAll(SetArgPointee<0>(123L), [] { return ScopedAStatus::ok(); }));
return APerformanceHint_getManager();
}
+
APerformanceHintSession* createSession(APerformanceHintManager* manager,
int64_t targetDuration = 56789L, bool isHwui = false) {
mMockSession = ndk::SharedRefBase::make<NiceMock<MockIHintSession>>();
@@ -106,8 +116,7 @@ public:
ON_CALL(*mMockIHintManager,
createHintSessionWithConfig(_, Eq(tids), Eq(targetDuration), _, _, _))
- .WillByDefault(DoAll(SetArgPointee<4>(std::make_optional<hal::SessionConfig>(
- {.id = sessionId})),
+ .WillByDefault(DoAll(SetArgPointee<4>(hal::SessionConfig({.id = sessionId})),
SetArgPointee<5>(std::shared_ptr<IHintSession>(mMockSession)),
[] { return ScopedAStatus::ok(); }));
@@ -133,8 +142,47 @@ public:
return APerformanceHint_createSession(manager, tids.data(), tids.size(), targetDuration);
}
+ void setFMQEnabled(bool enabled) {
+ mUsingFMQ = enabled;
+ if (enabled) {
+ mMockFMQ = std::make_shared<
+ AidlMessageQueue<hal::ChannelMessage, SynchronizedReadWrite>>(kMockQueueSize,
+ true);
+ mMockFlagQueue =
+ std::make_shared<AidlMessageQueue<int8_t, SynchronizedReadWrite>>(1, true);
+ hardware::EventFlag::createEventFlag(mMockFlagQueue->getEventFlagWord(), &mEventFlag);
+
+ ON_CALL(*mMockIHintManager, getSessionChannel(_, _))
+ .WillByDefault([&](ndk::SpAIBinder, std::optional<hal::ChannelConfig>* config) {
+ config->emplace(
+ hal::ChannelConfig{.channelDescriptor = mMockFMQ->dupeDesc(),
+ .eventFlagDescriptor =
+ mMockFlagQueue->dupeDesc(),
+ .readFlagBitmask =
+ static_cast<int32_t>(mReadBits),
+ .writeFlagBitmask =
+ static_cast<int32_t>(mWriteBits)});
+ return ::ndk::ScopedAStatus::ok();
+ });
+ }
+ }
+ uint32_t mReadBits = 0x00000001;
+ uint32_t mWriteBits = 0x00000002;
std::shared_ptr<NiceMock<MockIHintManager>> mMockIHintManager = nullptr;
std::shared_ptr<NiceMock<MockIHintSession>> mMockSession = nullptr;
+ std::shared_ptr<AidlMessageQueue<hal::ChannelMessage, SynchronizedReadWrite>> mMockFMQ;
+ std::shared_ptr<AidlMessageQueue<int8_t, SynchronizedReadWrite>> mMockFlagQueue;
+ hardware::EventFlag* mEventFlag;
+ int kMockQueueSize = 20;
+ bool mUsingFMQ = false;
+
+ template <HalChannelMessageContents::Tag T, class C = HalChannelMessageContents::_at<T>>
+ void expectToReadFromFmq(C expected) {
+ hal::ChannelMessage readData;
+ mMockFMQ->readBlocking(&readData, 1, mReadBits, mWriteBits, 1000000000, mEventFlag);
+ C got = static_cast<C>(readData.data.get<T>());
+ ASSERT_EQ(got, expected);
+ }
};
bool equalsWithoutTimestamp(hal::WorkDuration lhs, hal::WorkDuration rhs) {
@@ -306,7 +354,7 @@ TEST_F(PerformanceHintTest, TestAPerformanceHint_reportActualWorkDuration2) {
actualWorkDurations.push_back(pair.duration);
EXPECT_CALL(*mMockSession, reportActualWorkDuration2(WorkDurationEq(actualWorkDurations)))
- .Times(Exactly(1));
+ .Times(Exactly(pair.expectedResult == OK));
result = APerformanceHint_reportActualWorkDuration2(session,
reinterpret_cast<AWorkDuration*>(
&pair.duration));
@@ -327,3 +375,48 @@ TEST_F(PerformanceHintTest, TestAWorkDuration) {
AWorkDuration_setActualGpuDurationNanos(aWorkDuration, 8);
AWorkDuration_release(aWorkDuration);
}
+
+TEST_F(PerformanceHintTest, TestCreateUsingFMQ) {
+ setFMQEnabled(true);
+ APerformanceHintManager* manager = createManager();
+ APerformanceHintSession* session = createSession(manager);
+ ASSERT_TRUE(session);
+}
+
+TEST_F(PerformanceHintTest, TestUpdateTargetWorkDurationUsingFMQ) {
+ setFMQEnabled(true);
+ APerformanceHintManager* manager = createManager();
+ APerformanceHintSession* session = createSession(manager);
+ APerformanceHint_updateTargetWorkDuration(session, 456);
+ expectToReadFromFmq<HalChannelMessageContents::Tag::targetDuration>(456);
+}
+
+TEST_F(PerformanceHintTest, TestSendHintUsingFMQ) {
+ setFMQEnabled(true);
+ APerformanceHintManager* manager = createManager();
+ APerformanceHintSession* session = createSession(manager);
+ APerformanceHint_sendHint(session, SessionHint::CPU_LOAD_UP);
+ expectToReadFromFmq<HalChannelMessageContents::Tag::hint>(hal::SessionHint::CPU_LOAD_UP);
+}
+
+TEST_F(PerformanceHintTest, TestReportActualUsingFMQ) {
+ setFMQEnabled(true);
+ APerformanceHintManager* manager = createManager();
+ APerformanceHintSession* session = createSession(manager);
+ hal::WorkDuration duration{.timeStampNanos = 3,
+ .durationNanos = 999999,
+ .workPeriodStartTimestampNanos = 1,
+ .cpuDurationNanos = 999999,
+ .gpuDurationNanos = 999999};
+
+ hal::WorkDurationFixedV1 durationExpected{
+ .durationNanos = duration.durationNanos,
+ .workPeriodStartTimestampNanos = duration.workPeriodStartTimestampNanos,
+ .cpuDurationNanos = duration.cpuDurationNanos,
+ .gpuDurationNanos = duration.gpuDurationNanos,
+ };
+
+ APerformanceHint_reportActualWorkDuration2(session,
+ reinterpret_cast<AWorkDuration*>(&duration));
+ expectToReadFromFmq<HalChannelMessageContents::Tag::workDuration>(durationExpected);
+}
diff --git a/packages/SettingsLib/src/com/android/settingslib/media/OWNERS b/packages/SettingsLib/src/com/android/settingslib/media/OWNERS
index 7467ee1c1a7c..d58add4bb5eb 100644
--- a/packages/SettingsLib/src/com/android/settingslib/media/OWNERS
+++ b/packages/SettingsLib/src/com/android/settingslib/media/OWNERS
@@ -2,7 +2,6 @@
ethibodeau@google.com
michaelmikhil@google.com
apotapov@google.com
-shaoweishen@google.com
#Android Media - For minor changes and renames only.
aquilescanta@google.com #{LAST_RESORT_SUGGESTION}
diff --git a/packages/Shell/tests/Android.bp b/packages/Shell/tests/Android.bp
index 6399ffdfdf2f..082a58942059 100644
--- a/packages/Shell/tests/Android.bp
+++ b/packages/Shell/tests/Android.bp
@@ -26,3 +26,10 @@ android_test {
instrumentation_for: "Shell",
certificate: "platform",
}
+
+test_module_config {
+ name: "ShellTests_android_server_os",
+ base: "ShellTests",
+ test_suites: ["device-tests"],
+ exclude_annotations: ["androidx.test.filters.LargeTest"],
+}
diff --git a/packages/SystemUI/compose/features/src/com/android/systemui/bouncer/ui/composable/PinBouncer.kt b/packages/SystemUI/compose/features/src/com/android/systemui/bouncer/ui/composable/PinBouncer.kt
index 480e4e47ecf0..1287993081fa 100644
--- a/packages/SystemUI/compose/features/src/com/android/systemui/bouncer/ui/composable/PinBouncer.kt
+++ b/packages/SystemUI/compose/features/src/com/android/systemui/bouncer/ui/composable/PinBouncer.kt
@@ -17,6 +17,7 @@
package com.android.systemui.bouncer.ui.composable
import android.view.HapticFeedbackConstants
+import android.view.MotionEvent
import androidx.compose.animation.animateColorAsState
import androidx.compose.animation.core.Animatable
import androidx.compose.animation.core.AnimationSpec
@@ -49,6 +50,7 @@ import androidx.compose.ui.focus.focusRequester
import androidx.compose.ui.geometry.CornerRadius
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.graphicsLayer
+import androidx.compose.ui.input.pointer.pointerInteropFilter
import androidx.compose.ui.platform.LocalView
import androidx.compose.ui.unit.Dp
import androidx.compose.ui.unit.dp
@@ -110,6 +112,7 @@ fun PinPad(
onClicked = viewModel::onPinButtonClicked,
scaling = buttonScaleAnimatables[index]::value,
isAnimationEnabled = isDigitButtonAnimationEnabled,
+ onPointerDown = viewModel::onDigitButtonDown,
)
}
@@ -133,6 +136,7 @@ fun PinPad(
onClicked = viewModel::onPinButtonClicked,
scaling = buttonScaleAnimatables[10]::value,
isAnimationEnabled = isDigitButtonAnimationEnabled,
+ onPointerDown = viewModel::onDigitButtonDown
)
ActionButton(
@@ -155,6 +159,7 @@ private fun DigitButton(
digit: Int,
isInputEnabled: Boolean,
onClicked: (Int) -> Unit,
+ onPointerDown: () -> Unit,
scaling: () -> Float,
isAnimationEnabled: Boolean,
) {
@@ -164,6 +169,7 @@ private fun DigitButton(
backgroundColor = MaterialTheme.colorScheme.surfaceVariant,
foregroundColor = MaterialTheme.colorScheme.onSurfaceVariant,
isAnimationEnabled = isAnimationEnabled,
+ onPointerDown = onPointerDown,
modifier =
Modifier.graphicsLayer {
val scale = if (isAnimationEnabled) scaling() else 1f
@@ -235,6 +241,7 @@ private fun PinPadButton(
isAnimationEnabled: Boolean,
modifier: Modifier = Modifier,
onLongPressed: (() -> Unit)? = null,
+ onPointerDown: (() -> Unit)? = null,
content: @Composable (contentColor: () -> Color) -> Unit,
) {
val interactionSource = remember { MutableInteractionSource() }
@@ -303,11 +310,17 @@ private fun PinPadButton(
.clip(CircleShape)
.thenIf(isEnabled) {
Modifier.combinedClickable(
- interactionSource = interactionSource,
- indication = indication,
- onClick = onClicked,
- onLongClick = onLongPressed
- )
+ interactionSource = interactionSource,
+ indication = indication,
+ onClick = onClicked,
+ onLongClick = onLongPressed
+ )
+ .pointerInteropFilter { motionEvent ->
+ if (motionEvent.action == MotionEvent.ACTION_DOWN) {
+ onPointerDown?.let { it() }
+ }
+ false
+ }
},
) {
content(contentColor::value)
diff --git a/packages/SystemUI/multivalentTests/src/com/android/keyguard/KeyguardPasswordViewControllerTest.kt b/packages/SystemUI/multivalentTests/src/com/android/keyguard/KeyguardPasswordViewControllerTest.kt
index 062d351100d6..a1d944b403d3 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/keyguard/KeyguardPasswordViewControllerTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/keyguard/KeyguardPasswordViewControllerTest.kt
@@ -34,9 +34,11 @@ import com.android.systemui.SysuiTestCase
import com.android.systemui.classifier.FalsingCollector
import com.android.systemui.flags.FakeFeatureFlags
import com.android.systemui.flags.Flags
+import com.android.systemui.haptics.msdl.bouncerHapticPlayer
import com.android.systemui.keyboard.data.repository.FakeKeyboardRepository
import com.android.systemui.res.R
import com.android.systemui.statusbar.policy.DevicePostureController
+import com.android.systemui.testKosmos
import com.android.systemui.user.domain.interactor.SelectedUserInteractor
import com.android.systemui.util.concurrency.DelayableExecutor
import com.android.systemui.util.mockito.mock
@@ -86,6 +88,7 @@ class KeyguardPasswordViewControllerTest : SysuiTestCase() {
@Mock private lateinit var postureController: DevicePostureController
@Mock private lateinit var mUserActivityNotifier: UserActivityNotifier
@Captor private lateinit var keyListenerArgumentCaptor: ArgumentCaptor<View.OnKeyListener>
+ private val kosmos = testKosmos()
private lateinit var keyguardPasswordViewController: KeyguardPasswordViewController
@@ -132,8 +135,8 @@ class KeyguardPasswordViewControllerTest : SysuiTestCase() {
fakeFeatureFlags,
mSelectedUserInteractor,
keyguardKeyboardInteractor,
- null,
- mUserActivityNotifier
+ kosmos.bouncerHapticPlayer,
+ mUserActivityNotifier,
)
}
@@ -194,7 +197,7 @@ class KeyguardPasswordViewControllerTest : SysuiTestCase() {
keyListenerArgumentCaptor.value.onKey(
keyguardPasswordView,
KeyEvent.KEYCODE_SPACE,
- KeyEvent(KeyEvent.ACTION_UP, KeyEvent.KEYCODE_SPACE)
+ KeyEvent(KeyEvent.ACTION_UP, KeyEvent.KEYCODE_SPACE),
)
assertFalse("Unlock attempted.", eventHandled)
@@ -213,7 +216,7 @@ class KeyguardPasswordViewControllerTest : SysuiTestCase() {
keyListenerArgumentCaptor.value.onKey(
keyguardPasswordView,
KeyEvent.KEYCODE_ENTER,
- KeyEvent(KeyEvent.ACTION_UP, KeyEvent.KEYCODE_ENTER)
+ KeyEvent(KeyEvent.ACTION_UP, KeyEvent.KEYCODE_ENTER),
)
assertTrue("Unlock not attempted.", eventHandled)
diff --git a/packages/SystemUI/multivalentTests/src/com/android/keyguard/KeyguardPatternViewControllerTest.kt b/packages/SystemUI/multivalentTests/src/com/android/keyguard/KeyguardPatternViewControllerTest.kt
index bb152086cdab..d63e728cf443 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/keyguard/KeyguardPatternViewControllerTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/keyguard/KeyguardPatternViewControllerTest.kt
@@ -30,7 +30,7 @@ import com.android.systemui.classifier.FalsingCollector
import com.android.systemui.classifier.FalsingCollectorFake
import com.android.systemui.flags.FakeFeatureFlags
import com.android.systemui.flags.Flags
-import com.android.systemui.haptics.msdl.msdlPlayer
+import com.android.systemui.haptics.msdl.bouncerHapticPlayer
import com.android.systemui.res.R
import com.android.systemui.statusbar.policy.DevicePostureController
import com.android.systemui.statusbar.policy.DevicePostureController.DEVICE_POSTURE_HALF_OPENED
@@ -92,7 +92,7 @@ class KeyguardPatternViewControllerTest : SysuiTestCase() {
@Captor lateinit var postureCallbackCaptor: ArgumentCaptor<DevicePostureController.Callback>
private val kosmos = testKosmos()
- private val msdlPlayer = kosmos.msdlPlayer
+ private val bouncerHapticHelper = kosmos.bouncerHapticPlayer
@Before
fun setup() {
@@ -118,7 +118,7 @@ class KeyguardPatternViewControllerTest : SysuiTestCase() {
mPostureController,
fakeFeatureFlags,
mSelectedUserInteractor,
- msdlPlayer,
+ bouncerHapticHelper,
)
mKeyguardPatternView.onAttachedToWindow()
}
diff --git a/packages/SystemUI/multivalentTests/src/com/android/keyguard/KeyguardPinBasedInputViewControllerTest.java b/packages/SystemUI/multivalentTests/src/com/android/keyguard/KeyguardPinBasedInputViewControllerTest.java
index 1076d9089d79..4d1660e71c0a 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/keyguard/KeyguardPinBasedInputViewControllerTest.java
+++ b/packages/SystemUI/multivalentTests/src/com/android/keyguard/KeyguardPinBasedInputViewControllerTest.java
@@ -34,10 +34,12 @@ import com.android.internal.widget.LockPatternUtils;
import com.android.keyguard.KeyguardSecurityModel.SecurityMode;
import com.android.keyguard.domain.interactor.KeyguardKeyboardInteractor;
import com.android.systemui.SysuiTestCase;
+import com.android.systemui.bouncer.ui.helper.BouncerHapticPlayer;
import com.android.systemui.classifier.FalsingCollector;
import com.android.systemui.classifier.FalsingCollectorFake;
import com.android.systemui.flags.FakeFeatureFlags;
import com.android.systemui.keyboard.data.repository.FakeKeyboardRepository;
+import com.android.systemui.kosmos.KosmosJavaAdapter;
import com.android.systemui.res.R;
import com.android.systemui.user.domain.interactor.SelectedUserInteractor;
@@ -93,6 +95,9 @@ public class KeyguardPinBasedInputViewControllerTest extends SysuiTestCase {
private KeyguardPinBasedInputViewController mKeyguardPinViewController;
+ private KosmosJavaAdapter mKosmosJavaAdapter = new KosmosJavaAdapter(this);
+ private BouncerHapticPlayer mBouncerHapticPlayer = mKosmosJavaAdapter.getBouncerHapticHelper();
+
@Before
public void setup() {
MockitoAnnotations.initMocks(this);
@@ -119,7 +124,8 @@ public class KeyguardPinBasedInputViewControllerTest extends SysuiTestCase {
mKeyguardUpdateMonitor, mSecurityMode, mLockPatternUtils, mKeyguardSecurityCallback,
mKeyguardMessageAreaControllerFactory, mLatencyTracker, mLiftToactivateListener,
mEmergencyButtonController, mFalsingCollector, featureFlags,
- mSelectedUserInteractor, keyguardKeyboardInteractor, null, mUserActivityNotifier) {
+ mSelectedUserInteractor, keyguardKeyboardInteractor, mBouncerHapticPlayer,
+ mUserActivityNotifier) {
@Override
public void onResume(int reason) {
super.onResume(reason);
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/bouncer/ui/viewmodel/PinBouncerViewModelTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/bouncer/ui/viewmodel/PinBouncerViewModelTest.kt
index 8d82e972bdaa..2ee4aee2abab 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/bouncer/ui/viewmodel/PinBouncerViewModelTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/bouncer/ui/viewmodel/PinBouncerViewModelTest.kt
@@ -16,6 +16,8 @@
package com.android.systemui.bouncer.ui.viewmodel
+import android.platform.test.annotations.DisableFlags
+import android.platform.test.annotations.EnableFlags
import android.view.KeyEvent.KEYCODE_0
import android.view.KeyEvent.KEYCODE_4
import android.view.KeyEvent.KEYCODE_A
@@ -31,6 +33,7 @@ import com.android.systemui.authentication.data.repository.fakeAuthenticationRep
import com.android.systemui.authentication.domain.interactor.authenticationInteractor
import com.android.systemui.authentication.shared.model.AuthenticationMethodModel
import com.android.systemui.bouncer.data.repository.fakeSimBouncerRepository
+import com.android.systemui.classifier.fakeFalsingCollector
import com.android.systemui.coroutines.collectLastValue
import com.android.systemui.kosmos.testScope
import com.android.systemui.lifecycle.activateIn
@@ -41,6 +44,7 @@ import com.android.systemui.testKosmos
import com.google.common.truth.Truth.assertThat
import kotlin.random.Random
import kotlin.random.nextInt
+import kotlin.test.assertTrue
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.map
@@ -60,12 +64,13 @@ class PinBouncerViewModelTest : SysuiTestCase() {
private val testScope = kosmos.testScope
private val sceneInteractor by lazy { kosmos.sceneInteractor }
private val authenticationInteractor by lazy { kosmos.authenticationInteractor }
- private val underTest =
+ private val underTest by lazy {
kosmos.pinBouncerViewModelFactory.create(
isInputEnabled = MutableStateFlow(true),
onIntentionalUserInput = {},
authenticationMethod = AuthenticationMethodModel.Pin,
)
+ }
@Before
fun setUp() {
@@ -475,6 +480,18 @@ class PinBouncerViewModelTest : SysuiTestCase() {
assertThat(pin).containsExactly(*expectedPin)
}
+ @Test
+ @EnableFlags(com.android.systemui.Flags.FLAG_COMPOSE_BOUNCER)
+ @DisableFlags(com.android.systemui.Flags.FLAG_SCENE_CONTAINER)
+ fun onDigitButtonDown_avoidGesture_invoked() =
+ testScope.runTest {
+ lockDeviceAndOpenPinBouncer()
+
+ underTest.onDigitButtonDown()
+
+ assertTrue(kosmos.fakeFalsingCollector.wasLastGestureAvoided())
+ }
+
private fun TestScope.switchToScene(toScene: SceneKey) {
val currentScene by collectLastValue(sceneInteractor.currentScene)
val bouncerHidden = currentScene == Scenes.Bouncer && toScene != Scenes.Bouncer
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/deviceentry/domain/interactor/DeviceEntryInteractorTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/deviceentry/domain/interactor/DeviceEntryInteractorTest.kt
index 3253edfb5fca..d90d58b8d25c 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/deviceentry/domain/interactor/DeviceEntryInteractorTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/deviceentry/domain/interactor/DeviceEntryInteractorTest.kt
@@ -19,6 +19,7 @@ package com.android.systemui.deviceentry.domain.interactor
import android.testing.TestableLooper
import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.filters.SmallTest
+import com.android.compose.animation.scene.ObservableTransitionState
import com.android.compose.animation.scene.SceneKey
import com.android.systemui.SysuiTestCase
import com.android.systemui.authentication.data.repository.FakeAuthenticationRepository
@@ -42,11 +43,16 @@ import com.android.systemui.keyguard.data.repository.fakeTrustRepository
import com.android.systemui.keyguard.shared.model.KeyguardState
import com.android.systemui.keyguard.shared.model.SuccessFingerprintAuthenticationStatus
import com.android.systemui.kosmos.testScope
+import com.android.systemui.scene.domain.interactor.sceneBackInteractor
import com.android.systemui.scene.domain.interactor.sceneInteractor
+import com.android.systemui.scene.domain.startable.sceneContainerStartable
import com.android.systemui.scene.shared.model.Scenes
+import com.android.systemui.statusbar.sysuiStatusBarStateController
import com.android.systemui.testKosmos
import com.google.common.truth.Truth.assertThat
import kotlinx.coroutines.ExperimentalCoroutinesApi
+import kotlinx.coroutines.flow.flowOf
+import kotlinx.coroutines.test.TestScope
import kotlinx.coroutines.test.runCurrent
import kotlinx.coroutines.test.runTest
import org.junit.Before
@@ -66,10 +72,14 @@ class DeviceEntryInteractorTest : SysuiTestCase() {
private val trustRepository by lazy { kosmos.fakeTrustRepository }
private val sceneInteractor by lazy { kosmos.sceneInteractor }
private val authenticationInteractor by lazy { kosmos.authenticationInteractor }
+ private val sceneBackInteractor by lazy { kosmos.sceneBackInteractor }
+ private val sceneContainerStartable by lazy { kosmos.sceneContainerStartable }
+ private val sysuiStatusBarStateController by lazy { kosmos.sysuiStatusBarStateController }
private lateinit var underTest: DeviceEntryInteractor
@Before
fun setUp() {
+ sceneContainerStartable.start()
underTest = kosmos.deviceEntryInteractor
}
@@ -423,8 +433,37 @@ class DeviceEntryInteractorTest : SysuiTestCase() {
assertThat(isUnlocked).isTrue()
}
- private fun switchToScene(sceneKey: SceneKey) {
+ @Test
+ fun isDeviceEntered_unlockedWhileOnShade_emitsTrue() =
+ testScope.runTest {
+ val isDeviceEntered by collectLastValue(underTest.isDeviceEntered)
+ assertThat(isDeviceEntered).isFalse()
+ val currentScene by collectLastValue(sceneInteractor.currentScene)
+ assertThat(currentScene).isEqualTo(Scenes.Lockscreen)
+
+ // Navigate to shade and bouncer:
+ switchToScene(Scenes.Shade)
+ assertThat(currentScene).isEqualTo(Scenes.Shade)
+ // Simulating a "leave it open when the keyguard is hidden" which means the bouncer will
+ // be
+ // shown and successful authentication should take the user back to where they are, the
+ // shade scene.
+ sysuiStatusBarStateController.setLeaveOpenOnKeyguardHide(true)
+ switchToScene(Scenes.Bouncer)
+ assertThat(currentScene).isEqualTo(Scenes.Bouncer)
+
+ assertThat(isDeviceEntered).isFalse()
+ // Authenticate with PIN to unlock and dismiss the lockscreen:
+ authenticationInteractor.authenticate(FakeAuthenticationRepository.DEFAULT_PIN)
+ runCurrent()
+
+ assertThat(isDeviceEntered).isTrue()
+ }
+
+ private fun TestScope.switchToScene(sceneKey: SceneKey) {
sceneInteractor.changeScene(sceneKey, "reason")
+ sceneInteractor.setTransitionState(flowOf(ObservableTransitionState.Idle(sceneKey)))
+ runCurrent()
}
private suspend fun givenCanShowAlternateBouncer() {
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/scene/SceneFrameworkIntegrationTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/scene/SceneFrameworkIntegrationTest.kt
index 2d42c4247ab7..a0cafcbd5ad1 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/scene/SceneFrameworkIntegrationTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/scene/SceneFrameworkIntegrationTest.kt
@@ -161,9 +161,7 @@ class SceneFrameworkIntegrationTest : SysuiTestCase() {
val upDestinationSceneKey =
(actions?.get(Swipe.Up) as? UserActionResult.ChangeScene)?.toScene
assertThat(upDestinationSceneKey).isEqualTo(Scenes.Bouncer)
- kosmos.emulateUserDrivenTransition(
- to = upDestinationSceneKey,
- )
+ kosmos.emulateUserDrivenTransition(to = upDestinationSceneKey)
kosmos.fakeSceneDataSource.pause()
kosmos.enterPin()
@@ -226,16 +224,14 @@ class SceneFrameworkIntegrationTest : SysuiTestCase() {
(actions?.get(Swipe.Up) as? UserActionResult.ChangeScene)?.toScene
assertThat(upDestinationSceneKey).isEqualTo(SceneFamilies.Home)
assertThat(homeScene).isEqualTo(Scenes.Gone)
- kosmos.emulateUserDrivenTransition(
- to = homeScene,
- )
+ kosmos.emulateUserDrivenTransition(to = homeScene)
}
@Test
fun withAuthMethodNone_deviceWakeUp_skipsLockscreen() =
testScope.runTest {
kosmos.setAuthMethod(AuthenticationMethodModel.None, enableLockscreen = false)
- kosmos.putDeviceToSleep(instantlyLockDevice = false)
+ kosmos.putDeviceToSleep()
kosmos.assertCurrentScene(Scenes.Lockscreen)
kosmos.wakeUpDevice()
@@ -246,7 +242,7 @@ class SceneFrameworkIntegrationTest : SysuiTestCase() {
fun withAuthMethodSwipe_deviceWakeUp_doesNotSkipLockscreen() =
testScope.runTest {
kosmos.setAuthMethod(AuthenticationMethodModel.None, enableLockscreen = true)
- kosmos.putDeviceToSleep(instantlyLockDevice = false)
+ kosmos.putDeviceToSleep()
kosmos.assertCurrentScene(Scenes.Lockscreen)
kosmos.wakeUpDevice()
@@ -302,7 +298,7 @@ class SceneFrameworkIntegrationTest : SysuiTestCase() {
testScope.runTest {
kosmos.unlockDevice()
kosmos.assertCurrentScene(Scenes.Gone)
- kosmos.putDeviceToSleep(instantlyLockDevice = false)
+ kosmos.putDeviceToSleep()
kosmos.assertCurrentScene(Scenes.Lockscreen)
// Pretend like the timeout elapsed and now lock the device.
@@ -318,9 +314,7 @@ class SceneFrameworkIntegrationTest : SysuiTestCase() {
val upDestinationSceneKey =
(actions?.get(Swipe.Up) as? UserActionResult.ChangeScene)?.toScene
assertThat(upDestinationSceneKey).isEqualTo(Scenes.Bouncer)
- kosmos.emulateUserDrivenTransition(
- to = upDestinationSceneKey,
- )
+ kosmos.emulateUserDrivenTransition(to = upDestinationSceneKey)
kosmos.fakeSceneDataSource.pause()
kosmos.dismissIme()
@@ -388,7 +382,7 @@ class SceneFrameworkIntegrationTest : SysuiTestCase() {
kosmos.emulatePendingTransitionProgress(expectedVisible = true)
kosmos.enterSimPin(
authMethodAfterSimUnlock = AuthenticationMethodModel.None,
- enableLockscreen = false
+ enableLockscreen = false,
)
kosmos.assertCurrentScene(Scenes.Gone)
@@ -434,7 +428,7 @@ class SceneFrameworkIntegrationTest : SysuiTestCase() {
/** Updates the current authentication method and related states in the data layer. */
private fun Kosmos.setAuthMethod(
authMethod: AuthenticationMethodModel,
- enableLockscreen: Boolean = true
+ enableLockscreen: Boolean = true,
) {
if (authMethod.isSecure) {
assert(enableLockscreen) {
@@ -538,24 +532,27 @@ class SceneFrameworkIntegrationTest : SysuiTestCase() {
kosmos.fakeSceneDataSource.pause()
sceneInteractor.changeScene(to, "reason")
- emulatePendingTransitionProgress(
- expectedVisible = to != Scenes.Gone,
- )
+ emulatePendingTransitionProgress(expectedVisible = to != Scenes.Gone)
}
/**
- * Locks the device immediately (without delay).
+ * Locks the device.
*
* Asserts the device to be lockable (e.g. that the current authentication is secure).
*
- * Not to be confused with [putDeviceToSleep], which may also instantly lock the device.
+ * Internally emulates a power button press that puts the device to sleep, followed by another
+ * power button press that wakes up the device but is then expected to be in the locked state.
*/
private suspend fun Kosmos.lockDevice() {
val authMethod = authenticationInteractor.getAuthenticationMethod()
assertWithMessage("The authentication method of $authMethod is not secure, cannot lock!")
.that(authMethod.isSecure)
.isTrue()
- sceneInteractor.changeScene(Scenes.Lockscreen, "")
+
+ powerInteractor.setAsleepForTest()
+ testScope.runCurrent()
+
+ powerInteractor.setAwakeForTest()
testScope.runCurrent()
}
@@ -569,9 +566,7 @@ class SceneFrameworkIntegrationTest : SysuiTestCase() {
fakeSceneDataSource.pause()
enterPin()
- emulatePendingTransitionProgress(
- expectedVisible = false,
- )
+ emulatePendingTransitionProgress(expectedVisible = false)
}
/**
@@ -645,9 +640,7 @@ class SceneFrameworkIntegrationTest : SysuiTestCase() {
}
/** Changes device wakefulness state from awake to asleep, going through intermediary states. */
- private suspend fun Kosmos.putDeviceToSleep(
- instantlyLockDevice: Boolean = true,
- ) {
+ private suspend fun Kosmos.putDeviceToSleep() {
val wakefulnessModel = powerInteractor.detailedWakefulness.value
assertWithMessage("Cannot put device to sleep as it's already asleep!")
.that(wakefulnessModel.isAwake())
@@ -655,10 +648,6 @@ class SceneFrameworkIntegrationTest : SysuiTestCase() {
powerInteractor.setAsleepForTest()
testScope.runCurrent()
-
- if (instantlyLockDevice) {
- lockDevice()
- }
}
/** Emulates the dismissal of the IME (soft keyboard). */
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/scene/domain/interactor/SceneBackInteractorTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/scene/domain/interactor/SceneBackInteractorTest.kt
index 1f3454de14d7..405cfd38d49a 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/scene/domain/interactor/SceneBackInteractorTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/scene/domain/interactor/SceneBackInteractorTest.kt
@@ -28,6 +28,8 @@ import com.android.systemui.authentication.domain.interactor.authenticationInter
import com.android.systemui.coroutines.collectLastValue
import com.android.systemui.flags.EnableSceneContainer
import com.android.systemui.kosmos.testScope
+import com.android.systemui.scene.data.model.asIterable
+import com.android.systemui.scene.data.model.sceneStackOf
import com.android.systemui.scene.domain.startable.sceneContainerStartable
import com.android.systemui.scene.shared.model.Scenes
import com.android.systemui.testKosmos
@@ -173,12 +175,32 @@ class SceneBackInteractorTest : SysuiTestCase() {
)
}
+ @Test
+ @EnableSceneContainer
+ fun updateBackStack() =
+ testScope.runTest {
+ underTest.onSceneChange(from = Scenes.Lockscreen, to = Scenes.Shade)
+ underTest.onSceneChange(from = Scenes.Shade, to = Scenes.QuickSettings)
+ underTest.onSceneChange(from = Scenes.QuickSettings, to = Scenes.Bouncer)
+ assertThat(underTest.backStack.value.asIterable().toList())
+ .isEqualTo(listOf(Scenes.QuickSettings, Scenes.Shade, Scenes.Lockscreen))
+
+ underTest.updateBackStack { stack ->
+ // Reverse the stack, just to see if it can be done:
+ sceneStackOf(*stack.asIterable().reversed().toTypedArray())
+ }
+
+ assertThat(underTest.backStack.value.asIterable().toList())
+ .isEqualTo(listOf(Scenes.Lockscreen, Scenes.Shade, Scenes.QuickSettings))
+ }
+
private suspend fun TestScope.assertRoute(vararg route: RouteNode) {
val currentScene by collectLastValue(sceneInteractor.currentScene)
val backScene by collectLastValue(underTest.backScene)
route.forEachIndexed { index, node ->
sceneInteractor.changeScene(node.changeSceneTo, "")
+ runCurrent()
assertWithMessage("node at index $index currentScene mismatch")
.that(currentScene)
.isEqualTo(node.changeSceneTo)
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/scene/domain/startable/SceneContainerStartableTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/scene/domain/startable/SceneContainerStartableTest.kt
index d1804608d130..763a1a943bf8 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/scene/domain/startable/SceneContainerStartableTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/scene/domain/startable/SceneContainerStartableTest.kt
@@ -33,7 +33,9 @@ import com.android.internal.policy.IKeyguardDismissCallback
import com.android.keyguard.AuthInteractionProperties
import com.android.systemui.Flags
import com.android.systemui.SysuiTestCase
+import com.android.systemui.authentication.data.repository.FakeAuthenticationRepository
import com.android.systemui.authentication.data.repository.fakeAuthenticationRepository
+import com.android.systemui.authentication.domain.interactor.authenticationInteractor
import com.android.systemui.authentication.shared.model.AuthenticationMethodModel
import com.android.systemui.biometrics.data.repository.fingerprintPropertyRepository
import com.android.systemui.biometrics.shared.model.FingerprintSensorType
@@ -82,7 +84,9 @@ import com.android.systemui.power.domain.interactor.PowerInteractor.Companion.se
import com.android.systemui.power.domain.interactor.powerInteractor
import com.android.systemui.power.shared.model.WakeSleepReason
import com.android.systemui.power.shared.model.WakefulnessState
+import com.android.systemui.scene.data.model.asIterable
import com.android.systemui.scene.data.repository.Transition
+import com.android.systemui.scene.domain.interactor.sceneBackInteractor
import com.android.systemui.scene.domain.interactor.sceneInteractor
import com.android.systemui.scene.shared.model.Scenes
import com.android.systemui.scene.shared.model.fakeSceneDataSource
@@ -131,6 +135,7 @@ class SceneContainerStartableTest : SysuiTestCase() {
private val testScope = kosmos.testScope
private val deviceEntryHapticsInteractor by lazy { kosmos.deviceEntryHapticsInteractor }
private val sceneInteractor by lazy { kosmos.sceneInteractor }
+ private val sceneBackInteractor by lazy { kosmos.sceneBackInteractor }
private val bouncerInteractor by lazy { kosmos.bouncerInteractor }
private val faceAuthRepository by lazy { kosmos.fakeDeviceEntryFaceAuthRepository }
private val bouncerRepository by lazy { kosmos.fakeKeyguardBouncerRepository }
@@ -237,17 +242,14 @@ class SceneContainerStartableTest : SysuiTestCase() {
fun hydrateVisibility_basedOnOcclusion() =
testScope.runTest {
val isVisible by collectLastValue(sceneInteractor.isVisible)
- prepareState(
- isDeviceUnlocked = true,
- initialSceneKey = Scenes.Lockscreen,
- )
+ prepareState(isDeviceUnlocked = true, initialSceneKey = Scenes.Lockscreen)
underTest.start()
assertThat(isVisible).isTrue()
kosmos.keyguardOcclusionInteractor.setWmNotifiedShowWhenLockedActivityOnTop(
true,
- mock()
+ mock(),
)
assertThat(isVisible).isFalse()
@@ -259,10 +261,7 @@ class SceneContainerStartableTest : SysuiTestCase() {
fun hydrateVisibility_basedOnAlternateBouncer() =
testScope.runTest {
val isVisible by collectLastValue(sceneInteractor.isVisible)
- prepareState(
- isDeviceUnlocked = false,
- initialSceneKey = Scenes.Lockscreen,
- )
+ prepareState(isDeviceUnlocked = false, initialSceneKey = Scenes.Lockscreen)
underTest.start()
assertThat(isVisible).isTrue()
@@ -270,7 +269,7 @@ class SceneContainerStartableTest : SysuiTestCase() {
// WHEN the device is occluded,
kosmos.keyguardOcclusionInteractor.setWmNotifiedShowWhenLockedActivityOnTop(
true,
- mock()
+ mock(),
)
// THEN scenes are not visible
assertThat(isVisible).isFalse()
@@ -393,6 +392,7 @@ class SceneContainerStartableTest : SysuiTestCase() {
fun switchFromBouncerToQuickSettingsWhenDeviceUnlocked_whenLeaveOpenShade() =
testScope.runTest {
val currentSceneKey by collectLastValue(sceneInteractor.currentScene)
+ val backStack by collectLastValue(sceneBackInteractor.backStack)
kosmos.sysuiStatusBarStateController.leaveOpen = true // leave shade open
val transitionState =
@@ -414,12 +414,14 @@ class SceneContainerStartableTest : SysuiTestCase() {
transitionState.value = ObservableTransitionState.Idle(Scenes.Bouncer)
runCurrent()
assertThat(currentSceneKey).isEqualTo(Scenes.Bouncer)
+ assertThat(backStack?.asIterable()?.last()).isEqualTo(Scenes.Lockscreen)
kosmos.fakeDeviceEntryFingerprintAuthRepository.setAuthenticationStatus(
SuccessFingerprintAuthenticationStatus(0, true)
)
assertThat(currentSceneKey).isEqualTo(Scenes.QuickSettings)
+ assertThat(backStack?.asIterable()?.last()).isEqualTo(Scenes.Gone)
}
@Test
@@ -478,10 +480,7 @@ class SceneContainerStartableTest : SysuiTestCase() {
fun stayOnLockscreenWhenDeviceUnlocksWithBypassOff() =
testScope.runTest {
val currentSceneKey by collectLastValue(sceneInteractor.currentScene)
- prepareState(
- isBypassEnabled = false,
- initialSceneKey = Scenes.Lockscreen,
- )
+ prepareState(isBypassEnabled = false, initialSceneKey = Scenes.Lockscreen)
assertThat(currentSceneKey).isEqualTo(Scenes.Lockscreen)
underTest.start()
@@ -520,10 +519,7 @@ class SceneContainerStartableTest : SysuiTestCase() {
fun switchToGoneWhenDeviceIsUnlockedAndUserIsOnBouncerWithBypassDisabled() =
testScope.runTest {
val currentSceneKey by collectLastValue(sceneInteractor.currentScene)
- prepareState(
- isBypassEnabled = false,
- initialSceneKey = Scenes.Bouncer,
- )
+ prepareState(isBypassEnabled = false, initialSceneKey = Scenes.Bouncer)
assertThat(currentSceneKey).isEqualTo(Scenes.Bouncer)
underTest.start()
@@ -539,10 +535,7 @@ class SceneContainerStartableTest : SysuiTestCase() {
val alternateBouncerVisible by
collectLastValue(bouncerRepository.alternateBouncerVisible)
val currentSceneKey by collectLastValue(sceneInteractor.currentScene)
- prepareState(
- isDeviceUnlocked = false,
- initialSceneKey = Scenes.Shade,
- )
+ prepareState(isDeviceUnlocked = false, initialSceneKey = Scenes.Shade)
assertThat(currentSceneKey).isEqualTo(Scenes.Shade)
bouncerRepository.setAlternateVisible(true)
underTest.start()
@@ -564,10 +557,7 @@ class SceneContainerStartableTest : SysuiTestCase() {
fun switchToLockscreenWhenDeviceSleepsLocked() =
testScope.runTest {
val currentSceneKey by collectLastValue(sceneInteractor.currentScene)
- prepareState(
- isDeviceUnlocked = false,
- initialSceneKey = Scenes.Shade,
- )
+ prepareState(isDeviceUnlocked = false, initialSceneKey = Scenes.Shade)
assertThat(currentSceneKey).isEqualTo(Scenes.Shade)
underTest.start()
powerInteractor.setAsleepForTest()
@@ -583,10 +573,7 @@ class SceneContainerStartableTest : SysuiTestCase() {
val currentTransitionInfo by
collectLastValue(kosmos.keyguardTransitionRepository.currentTransitionInfoInternal)
val transitionState =
- prepareState(
- isDeviceUnlocked = false,
- initialSceneKey = Scenes.Shade,
- )
+ prepareState(isDeviceUnlocked = false, initialSceneKey = Scenes.Shade)
kosmos.keyguardRepository.setAodAvailable(true)
runCurrent()
assertThat(asleepState).isEqualTo(KeyguardState.AOD)
@@ -615,10 +602,7 @@ class SceneContainerStartableTest : SysuiTestCase() {
val currentTransitionInfo by
collectLastValue(kosmos.keyguardTransitionRepository.currentTransitionInfoInternal)
val transitionState =
- prepareState(
- isDeviceUnlocked = false,
- initialSceneKey = Scenes.Shade,
- )
+ prepareState(isDeviceUnlocked = false, initialSceneKey = Scenes.Shade)
kosmos.keyguardRepository.setAodAvailable(false)
runCurrent()
assertThat(asleepState).isEqualTo(KeyguardState.DOZING)
@@ -1078,16 +1062,14 @@ class SceneContainerStartableTest : SysuiTestCase() {
@Test
fun hydrateSystemUiState_onLockscreen_basedOnOcclusion() =
testScope.runTest {
- prepareState(
- initialSceneKey = Scenes.Lockscreen,
- )
+ prepareState(initialSceneKey = Scenes.Lockscreen)
underTest.start()
runCurrent()
clearInvocations(sysUiState)
kosmos.keyguardOcclusionInteractor.setWmNotifiedShowWhenLockedActivityOnTop(
true,
- mock()
+ mock(),
)
runCurrent()
assertThat(
@@ -1210,7 +1192,7 @@ class SceneContainerStartableTest : SysuiTestCase() {
initialSceneKey = Scenes.Lockscreen,
authenticationMethod = AuthenticationMethodModel.Pin,
isDeviceUnlocked = false,
- startsAwake = false
+ startsAwake = false,
)
assertThat(currentSceneKey).isEqualTo(Scenes.Lockscreen)
underTest.start()
@@ -1228,11 +1210,14 @@ class SceneContainerStartableTest : SysuiTestCase() {
@Test
fun collectFalsingSignals_onSuccessfulUnlock() =
testScope.runTest {
- prepareState(
- initialSceneKey = Scenes.Lockscreen,
- authenticationMethod = AuthenticationMethodModel.Pin,
- isDeviceUnlocked = false,
- )
+ val currentScene by collectLastValue(sceneInteractor.currentScene)
+
+ val transitionStateFlow =
+ prepareState(
+ initialSceneKey = Scenes.Lockscreen,
+ authenticationMethod = AuthenticationMethodModel.Pin,
+ isDeviceUnlocked = false,
+ )
underTest.start()
runCurrent()
verify(falsingCollector, never()).onSuccessfulUnlock()
@@ -1247,36 +1232,46 @@ class SceneContainerStartableTest : SysuiTestCase() {
)
.forEach { sceneKey ->
sceneInteractor.changeScene(sceneKey, "reason")
+ transitionStateFlow.value = ObservableTransitionState.Idle(sceneKey)
runCurrent()
verify(falsingCollector, never()).onSuccessfulUnlock()
}
// Changing to the Gone scene should report a successful unlock.
- kosmos.fakeDeviceEntryFingerprintAuthRepository.setAuthenticationStatus(
- SuccessFingerprintAuthenticationStatus(0, true)
- )
+ kosmos.authenticationInteractor.authenticate(FakeAuthenticationRepository.DEFAULT_PIN)
runCurrent()
- sceneInteractor.changeScene(Scenes.Gone, "reason")
+ // Make sure that the startable changed the scene to Gone because the device unlocked.
+ assertThat(currentScene).isEqualTo(Scenes.Gone)
+ // Make the transition state match the current state
+ transitionStateFlow.value = ObservableTransitionState.Idle(Scenes.Gone)
runCurrent()
verify(falsingCollector).onSuccessfulUnlock()
// Move around scenes without changing back to Lockscreen, shouldn't report another
// unlock.
- listOf(
- Scenes.Shade,
- Scenes.QuickSettings,
- Scenes.Shade,
- Scenes.Gone,
- )
- .forEach { sceneKey ->
- sceneInteractor.changeScene(sceneKey, "reason")
- runCurrent()
- verify(falsingCollector, times(1)).onSuccessfulUnlock()
- }
-
- // Changing to the Lockscreen scene shouldn't report a successful unlock.
- sceneInteractor.changeScene(Scenes.Lockscreen, "reason")
+ listOf(Scenes.Shade, Scenes.QuickSettings, Scenes.Shade, Scenes.Gone).forEach { sceneKey
+ ->
+ sceneInteractor.changeScene(sceneKey, "reason")
+ transitionStateFlow.value = ObservableTransitionState.Idle(sceneKey)
+ runCurrent()
+ verify(falsingCollector, times(1)).onSuccessfulUnlock()
+ }
+
+ // Putting the device to sleep to lock it again, which shouldn't report another
+ // successful unlock.
+ kosmos.powerInteractor.setAsleepForTest()
+ runCurrent()
+ // Verify that the startable changed the scene to Lockscreen because the device locked
+ // following the sleep.
+ assertThat(currentScene).isEqualTo(Scenes.Lockscreen)
+ // Make the transition state match the current state
+ transitionStateFlow.value = ObservableTransitionState.Idle(Scenes.Lockscreen)
+ // Wake up the device again before continuing with the test.
+ kosmos.powerInteractor.setAwakeForTest()
runCurrent()
+ // Verify that the current scene is still the Lockscreen scene, now that the device is
+ // still locked.
+ assertThat(currentScene).isEqualTo(Scenes.Lockscreen)
verify(falsingCollector, times(1)).onSuccessfulUnlock()
// Move around scenes without unlocking.
@@ -1289,12 +1284,17 @@ class SceneContainerStartableTest : SysuiTestCase() {
)
.forEach { sceneKey ->
sceneInteractor.changeScene(sceneKey, "reason")
+ transitionStateFlow.value = ObservableTransitionState.Idle(sceneKey)
runCurrent()
verify(falsingCollector, times(1)).onSuccessfulUnlock()
}
- // Changing to the Gone scene should report a second successful unlock.
- sceneInteractor.changeScene(Scenes.Gone, "reason")
+ kosmos.authenticationInteractor.authenticate(FakeAuthenticationRepository.DEFAULT_PIN)
+ runCurrent()
+ // Make sure that the startable changed the scene to Gone because the device unlocked.
+ assertThat(currentScene).isEqualTo(Scenes.Gone)
+ // Make the transition state match the current scene.
+ transitionStateFlow.value = ObservableTransitionState.Idle(Scenes.Gone)
runCurrent()
verify(falsingCollector, times(2)).onSuccessfulUnlock()
}
@@ -1608,7 +1608,7 @@ class SceneContainerStartableTest : SysuiTestCase() {
kosmos.keyguardOcclusionInteractor.setWmNotifiedShowWhenLockedActivityOnTop(
true,
- mock()
+ mock(),
)
runCurrent()
verify(notificationShadeWindowController, times(1)).setKeyguardOccluded(true)
@@ -1623,10 +1623,7 @@ class SceneContainerStartableTest : SysuiTestCase() {
@Test
fun hydrateInteractionState_whileLocked() =
testScope.runTest {
- val transitionStateFlow =
- prepareState(
- initialSceneKey = Scenes.Lockscreen,
- )
+ val transitionStateFlow = prepareState(initialSceneKey = Scenes.Lockscreen)
underTest.start()
runCurrent()
verify(centralSurfaces).setInteracting(StatusBarManager.WINDOW_STATUS_BAR, true)
@@ -1643,10 +1640,7 @@ class SceneContainerStartableTest : SysuiTestCase() {
},
verifyAfterTransition = {
verify(centralSurfaces)
- .setInteracting(
- StatusBarManager.WINDOW_STATUS_BAR,
- false,
- )
+ .setInteracting(StatusBarManager.WINDOW_STATUS_BAR, false)
},
)
@@ -1661,11 +1655,7 @@ class SceneContainerStartableTest : SysuiTestCase() {
verify(centralSurfaces, never()).setInteracting(anyInt(), anyBoolean())
},
verifyAfterTransition = {
- verify(centralSurfaces)
- .setInteracting(
- StatusBarManager.WINDOW_STATUS_BAR,
- true,
- )
+ verify(centralSurfaces).setInteracting(StatusBarManager.WINDOW_STATUS_BAR, true)
},
)
@@ -1681,10 +1671,7 @@ class SceneContainerStartableTest : SysuiTestCase() {
},
verifyAfterTransition = {
verify(centralSurfaces)
- .setInteracting(
- StatusBarManager.WINDOW_STATUS_BAR,
- false,
- )
+ .setInteracting(StatusBarManager.WINDOW_STATUS_BAR, false)
},
)
@@ -1699,11 +1686,7 @@ class SceneContainerStartableTest : SysuiTestCase() {
verify(centralSurfaces, never()).setInteracting(anyInt(), anyBoolean())
},
verifyAfterTransition = {
- verify(centralSurfaces)
- .setInteracting(
- StatusBarManager.WINDOW_STATUS_BAR,
- true,
- )
+ verify(centralSurfaces).setInteracting(StatusBarManager.WINDOW_STATUS_BAR, true)
},
)
@@ -1881,9 +1864,7 @@ class SceneContainerStartableTest : SysuiTestCase() {
testScope.runTest {
val currentScene by collectLastValue(sceneInteractor.currentScene)
val transitionStateFlow =
- prepareState(
- authenticationMethod = AuthenticationMethodModel.None,
- )
+ prepareState(authenticationMethod = AuthenticationMethodModel.None)
underTest.start()
assertThat(currentScene).isEqualTo(Scenes.Lockscreen)
// Swipe to Gone, more than halfway
@@ -1949,9 +1930,7 @@ class SceneContainerStartableTest : SysuiTestCase() {
fun switchToGone_whenKeyguardBecomesDisabled_whenOnShadeScene() =
testScope.runTest {
val currentScene by collectLastValue(sceneInteractor.currentScene)
- prepareState(
- initialSceneKey = Scenes.Shade,
- )
+ prepareState(initialSceneKey = Scenes.Shade)
assertThat(currentScene).isEqualTo(Scenes.Shade)
underTest.start()
@@ -1981,10 +1960,7 @@ class SceneContainerStartableTest : SysuiTestCase() {
fun doesNotSwitchToGone_whenKeyguardBecomesDisabled_whenDeviceEntered() =
testScope.runTest {
val currentScene by collectLastValue(sceneInteractor.currentScene)
- prepareState(
- isDeviceUnlocked = true,
- initialSceneKey = Scenes.Gone,
- )
+ prepareState(isDeviceUnlocked = true, initialSceneKey = Scenes.Gone)
assertThat(currentScene).isEqualTo(Scenes.Gone)
assertThat(kosmos.deviceEntryInteractor.isDeviceEntered.value).isTrue()
underTest.start()
@@ -2097,10 +2073,7 @@ class SceneContainerStartableTest : SysuiTestCase() {
fun refreshLockscreenEnabled() =
testScope.runTest {
val transitionState =
- prepareState(
- isDeviceUnlocked = true,
- initialSceneKey = Scenes.Gone,
- )
+ prepareState(isDeviceUnlocked = true, initialSceneKey = Scenes.Gone)
underTest.start()
val isLockscreenEnabled by
collectLastValue(kosmos.deviceEntryInteractor.isLockscreenEnabled)
@@ -2174,10 +2147,7 @@ class SceneContainerStartableTest : SysuiTestCase() {
runCurrent()
verifyDuringTransition?.invoke()
- transitionStateFlow.value =
- ObservableTransitionState.Idle(
- currentScene = toScene,
- )
+ transitionStateFlow.value = ObservableTransitionState.Idle(currentScene = toScene)
runCurrent()
verifyAfterTransition?.invoke()
}
@@ -2262,7 +2232,7 @@ class SceneContainerStartableTest : SysuiTestCase() {
private fun TestScope.allowHapticsOnSfps(
isPowerButtonDown: Boolean = false,
- lastPowerPress: Long = 10000
+ lastPowerPress: Long = 10000,
) {
kosmos.fakeKeyEventRepository.setPowerButtonDown(isPowerButtonDown)
@@ -2287,7 +2257,7 @@ class SceneContainerStartableTest : SysuiTestCase() {
private fun TestScope.setupBiometricAuth(
hasSfps: Boolean = false,
hasUdfps: Boolean = false,
- hasFace: Boolean = false
+ hasFace: Boolean = false,
) {
if (hasSfps) {
setFingerprintSensorType(FingerprintSensorType.POWER_BUTTON)
diff --git a/packages/SystemUI/res/drawable/ic_volume_media_off.xml b/packages/SystemUI/res/drawable/ic_volume_media_off.xml
deleted file mode 100644
index 875b7b6d1f40..000000000000
--- a/packages/SystemUI/res/drawable/ic_volume_media_off.xml
+++ /dev/null
@@ -1,20 +0,0 @@
-<?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
- -->
-
-<selector xmlns:android="http://schemas.android.com/apk/res/android">
- <item android:drawable="@drawable/ic_volume_media_mute" />
-</selector>
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardAbsKeyInputViewController.java b/packages/SystemUI/src/com/android/keyguard/KeyguardAbsKeyInputViewController.java
index 28f1381d94af..b43d8b667756 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardAbsKeyInputViewController.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardAbsKeyInputViewController.java
@@ -19,10 +19,8 @@ package com.android.keyguard;
import static com.android.internal.util.LatencyTracker.ACTION_CHECK_CREDENTIAL;
import static com.android.internal.util.LatencyTracker.ACTION_CHECK_CREDENTIAL_UNLOCKED;
import static com.android.keyguard.KeyguardAbsKeyInputView.MINIMUM_PASSWORD_LENGTH_BEFORE_REPORT;
-import static com.android.systemui.Flags.msdlFeedback;
import static com.android.systemui.Flags.notifyPasswordTextViewUserActivityInBackground;
-import android.annotation.Nullable;
import android.content.res.ColorStateList;
import android.os.AsyncTask;
import android.os.CountDownTimer;
@@ -37,15 +35,13 @@ import com.android.internal.widget.LockscreenCredential;
import com.android.keyguard.EmergencyButtonController.EmergencyButtonCallback;
import com.android.keyguard.KeyguardAbsKeyInputView.KeyDownListener;
import com.android.keyguard.KeyguardSecurityModel.SecurityMode;
+import com.android.systemui.bouncer.ui.helper.BouncerHapticPlayer;
import com.android.systemui.classifier.FalsingClassifier;
import com.android.systemui.classifier.FalsingCollector;
import com.android.systemui.flags.FeatureFlags;
import com.android.systemui.res.R;
import com.android.systemui.user.domain.interactor.SelectedUserInteractor;
-import com.google.android.msdl.data.model.MSDLToken;
-import com.google.android.msdl.domain.MSDLPlayer;
-
import java.util.HashMap;
import java.util.Map;
@@ -62,8 +58,6 @@ public abstract class KeyguardAbsKeyInputViewController<T extends KeyguardAbsKey
protected AsyncTask<?, ?, ?> mPendingLockCheck;
protected boolean mResumed;
protected boolean mLockedOut;
- @Nullable
- protected MSDLPlayer mMSDLPlayer;
private final KeyDownListener mKeyDownListener = (keyCode, keyEvent) -> {
// Fingerprint sensor sends a KeyEvent.KEYCODE_UNKNOWN.
@@ -91,16 +85,16 @@ public abstract class KeyguardAbsKeyInputViewController<T extends KeyguardAbsKey
LatencyTracker latencyTracker, FalsingCollector falsingCollector,
EmergencyButtonController emergencyButtonController,
FeatureFlags featureFlags, SelectedUserInteractor selectedUserInteractor,
- @Nullable MSDLPlayer msdlPlayer,
+ BouncerHapticPlayer bouncerHapticPlayer,
UserActivityNotifier userActivityNotifier) {
super(view, securityMode, keyguardSecurityCallback, emergencyButtonController,
- messageAreaControllerFactory, featureFlags, selectedUserInteractor);
+ messageAreaControllerFactory, featureFlags, selectedUserInteractor,
+ bouncerHapticPlayer);
mKeyguardUpdateMonitor = keyguardUpdateMonitor;
mLockPatternUtils = lockPatternUtils;
mLatencyTracker = latencyTracker;
mFalsingCollector = falsingCollector;
mEmergencyButtonController = emergencyButtonController;
- mMSDLPlayer = msdlPlayer;
mUserActivityNotifier = userActivityNotifier;
}
@@ -191,7 +185,9 @@ public abstract class KeyguardAbsKeyInputViewController<T extends KeyguardAbsKey
void onPasswordChecked(int userId, boolean matched, int timeoutMs, boolean isValidPassword) {
boolean dismissKeyguard = mSelectedUserInteractor.getSelectedUserId() == userId;
if (matched) {
- playAuthenticationHaptics(/* unlock= */true);
+ mBouncerHapticPlayer.playAuthenticationFeedback(
+ /* authenticationSucceeded = */true
+ );
getKeyguardSecurityCallback().reportUnlockAttempt(userId, true, 0);
if (dismissKeyguard) {
mDismissing = true;
@@ -199,7 +195,9 @@ public abstract class KeyguardAbsKeyInputViewController<T extends KeyguardAbsKey
getKeyguardSecurityCallback().dismiss(true, userId, getSecurityMode());
}
} else {
- playAuthenticationHaptics(/* unlock= */false);
+ mBouncerHapticPlayer.playAuthenticationFeedback(
+ /* authenticationSucceeded = */false
+ );
mView.resetPasswordText(true /* animate */, false /* announce deletion if no match */);
if (isValidPassword) {
getKeyguardSecurityCallback().reportUnlockAttempt(userId, false, timeoutMs);
@@ -216,18 +214,6 @@ public abstract class KeyguardAbsKeyInputViewController<T extends KeyguardAbsKey
}
}
- private void playAuthenticationHaptics(boolean unlock) {
- if (!msdlFeedback() || mMSDLPlayer == null) return;
-
- MSDLToken token;
- if (unlock) {
- token = MSDLToken.UNLOCK;
- } else {
- token = MSDLToken.FAILURE;
- }
- mMSDLPlayer.playToken(token, mAuthInteractionProperties);
- }
-
protected void startErrorAnimation() { /* no-op */ }
protected void verifyPasswordAndUnlock() {
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardInputViewController.java b/packages/SystemUI/src/com/android/keyguard/KeyguardInputViewController.java
index 92e5432ad243..ff788484c819 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardInputViewController.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardInputViewController.java
@@ -35,6 +35,7 @@ import com.android.systemui.Flags;
import com.android.systemui.bouncer.domain.interactor.BouncerMessageInteractor;
import com.android.systemui.bouncer.ui.BouncerMessageView;
import com.android.systemui.bouncer.ui.binder.BouncerMessageViewBinder;
+import com.android.systemui.bouncer.ui.helper.BouncerHapticPlayer;
import com.android.systemui.classifier.FalsingCollector;
import com.android.systemui.dagger.qualifiers.Main;
import com.android.systemui.flags.FeatureFlags;
@@ -45,9 +46,6 @@ import com.android.systemui.user.domain.interactor.SelectedUserInteractor;
import com.android.systemui.util.ViewController;
import com.android.systemui.util.concurrency.DelayableExecutor;
-import com.google.android.msdl.domain.InteractionProperties;
-import com.google.android.msdl.domain.MSDLPlayer;
-
import javax.inject.Inject;
/** Controller for a {@link KeyguardSecurityView}. */
@@ -66,21 +64,22 @@ public abstract class KeyguardInputViewController<T extends KeyguardInputView>
private KeyguardSecurityCallback mNullCallback = new KeyguardSecurityCallback() {};
private final FeatureFlags mFeatureFlags;
protected final SelectedUserInteractor mSelectedUserInteractor;
- protected final InteractionProperties mAuthInteractionProperties =
- new AuthInteractionProperties();
+ protected final BouncerHapticPlayer mBouncerHapticPlayer;
protected KeyguardInputViewController(T view, SecurityMode securityMode,
KeyguardSecurityCallback keyguardSecurityCallback,
EmergencyButtonController emergencyButtonController,
@Nullable KeyguardMessageAreaController.Factory messageAreaControllerFactory,
FeatureFlags featureFlags,
- SelectedUserInteractor selectedUserInteractor) {
+ SelectedUserInteractor selectedUserInteractor,
+ BouncerHapticPlayer bouncerHapticPlayer) {
super(view);
mSecurityMode = securityMode;
mKeyguardSecurityCallback = keyguardSecurityCallback;
mEmergencyButtonController = emergencyButtonController;
mFeatureFlags = featureFlags;
mSelectedUserInteractor = selectedUserInteractor;
+ mBouncerHapticPlayer = bouncerHapticPlayer;
if (messageAreaControllerFactory != null) {
try {
BouncerKeyguardMessageArea kma = view.requireViewById(R.id.bouncer_message_area);
@@ -219,7 +218,7 @@ public abstract class KeyguardInputViewController<T extends KeyguardInputView>
private final SelectedUserInteractor mSelectedUserInteractor;
private final UiEventLogger mUiEventLogger;
private final KeyguardKeyboardInteractor mKeyguardKeyboardInteractor;
- private final MSDLPlayer mMSDLPlayer;
+ private final BouncerHapticPlayer mBouncerHapticPlayer;
private final UserActivityNotifier mUserActivityNotifier;
@Inject
@@ -236,7 +235,7 @@ public abstract class KeyguardInputViewController<T extends KeyguardInputView>
FeatureFlags featureFlags, SelectedUserInteractor selectedUserInteractor,
UiEventLogger uiEventLogger,
KeyguardKeyboardInteractor keyguardKeyboardInteractor,
- MSDLPlayer msdlPlayer,
+ BouncerHapticPlayer bouncerHapticPlayer,
UserActivityNotifier userActivityNotifier) {
mKeyguardUpdateMonitor = keyguardUpdateMonitor;
mLockPatternUtils = lockPatternUtils;
@@ -255,7 +254,7 @@ public abstract class KeyguardInputViewController<T extends KeyguardInputView>
mSelectedUserInteractor = selectedUserInteractor;
mUiEventLogger = uiEventLogger;
mKeyguardKeyboardInteractor = keyguardKeyboardInteractor;
- mMSDLPlayer = msdlPlayer;
+ mBouncerHapticPlayer = bouncerHapticPlayer;
mUserActivityNotifier = userActivityNotifier;
}
@@ -272,7 +271,7 @@ public abstract class KeyguardInputViewController<T extends KeyguardInputView>
keyguardSecurityCallback, mLatencyTracker, mFalsingCollector,
emergencyButtonController, mMessageAreaControllerFactory,
mDevicePostureController, mFeatureFlags, mSelectedUserInteractor,
- mMSDLPlayer);
+ mBouncerHapticPlayer);
} else if (keyguardInputView instanceof KeyguardPasswordView) {
return new KeyguardPasswordViewController((KeyguardPasswordView) keyguardInputView,
mKeyguardUpdateMonitor, securityMode, mLockPatternUtils,
@@ -280,14 +279,14 @@ public abstract class KeyguardInputViewController<T extends KeyguardInputView>
mInputMethodManager, emergencyButtonController, mMainExecutor, mResources,
mFalsingCollector, mKeyguardViewController,
mDevicePostureController, mFeatureFlags, mSelectedUserInteractor,
- mKeyguardKeyboardInteractor, mMSDLPlayer, mUserActivityNotifier);
+ mKeyguardKeyboardInteractor, mBouncerHapticPlayer, mUserActivityNotifier);
} else if (keyguardInputView instanceof KeyguardPINView) {
return new KeyguardPinViewController((KeyguardPINView) keyguardInputView,
mKeyguardUpdateMonitor, securityMode, mLockPatternUtils,
keyguardSecurityCallback, mMessageAreaControllerFactory, mLatencyTracker,
mLiftToActivateListener, emergencyButtonController, mFalsingCollector,
mDevicePostureController, mFeatureFlags, mSelectedUserInteractor,
- mUiEventLogger, mKeyguardKeyboardInteractor, mMSDLPlayer,
+ mUiEventLogger, mKeyguardKeyboardInteractor, mBouncerHapticPlayer,
mUserActivityNotifier);
} else if (keyguardInputView instanceof KeyguardSimPinView) {
return new KeyguardSimPinViewController((KeyguardSimPinView) keyguardInputView,
@@ -295,14 +294,14 @@ public abstract class KeyguardInputViewController<T extends KeyguardInputView>
keyguardSecurityCallback, mMessageAreaControllerFactory, mLatencyTracker,
mLiftToActivateListener, mTelephonyManager, mFalsingCollector,
emergencyButtonController, mFeatureFlags, mSelectedUserInteractor,
- mKeyguardKeyboardInteractor, mMSDLPlayer, mUserActivityNotifier);
+ mKeyguardKeyboardInteractor, mBouncerHapticPlayer, mUserActivityNotifier);
} else if (keyguardInputView instanceof KeyguardSimPukView) {
return new KeyguardSimPukViewController((KeyguardSimPukView) keyguardInputView,
mKeyguardUpdateMonitor, securityMode, mLockPatternUtils,
keyguardSecurityCallback, mMessageAreaControllerFactory, mLatencyTracker,
mLiftToActivateListener, mTelephonyManager, mFalsingCollector,
emergencyButtonController, mFeatureFlags, mSelectedUserInteractor,
- mKeyguardKeyboardInteractor, mMSDLPlayer, mUserActivityNotifier
+ mKeyguardKeyboardInteractor, mBouncerHapticPlayer, mUserActivityNotifier
);
}
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardPasswordViewController.java b/packages/SystemUI/src/com/android/keyguard/KeyguardPasswordViewController.java
index 905fa0939a46..4628ed705d00 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardPasswordViewController.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardPasswordViewController.java
@@ -19,7 +19,6 @@ package com.android.keyguard;
import static com.android.systemui.flags.Flags.LOCKSCREEN_ENABLE_LANDSCAPE;
import static com.android.systemui.util.kotlin.JavaAdapterKt.collectFlow;
-import android.annotation.Nullable;
import android.content.Context;
import android.content.pm.PackageManager;
import android.content.res.Resources;
@@ -48,6 +47,7 @@ import com.android.internal.widget.LockPatternUtils;
import com.android.keyguard.KeyguardSecurityModel.SecurityMode;
import com.android.keyguard.domain.interactor.KeyguardKeyboardInteractor;
import com.android.systemui.Flags;
+import com.android.systemui.bouncer.ui.helper.BouncerHapticPlayer;
import com.android.systemui.classifier.FalsingCollector;
import com.android.systemui.dagger.qualifiers.Main;
import com.android.systemui.flags.FeatureFlags;
@@ -56,8 +56,6 @@ import com.android.systemui.statusbar.policy.DevicePostureController;
import com.android.systemui.user.domain.interactor.SelectedUserInteractor;
import com.android.systemui.util.concurrency.DelayableExecutor;
-import com.google.android.msdl.domain.MSDLPlayer;
-
import java.util.List;
public class KeyguardPasswordViewController
@@ -138,12 +136,12 @@ public class KeyguardPasswordViewController
FeatureFlags featureFlags,
SelectedUserInteractor selectedUserInteractor,
KeyguardKeyboardInteractor keyguardKeyboardInteractor,
- @Nullable MSDLPlayer msdlPlayer,
+ BouncerHapticPlayer bouncerHapticPlayer,
UserActivityNotifier userActivityNotifier) {
super(view, keyguardUpdateMonitor, securityMode, lockPatternUtils, keyguardSecurityCallback,
messageAreaControllerFactory, latencyTracker, falsingCollector,
- emergencyButtonController, featureFlags, selectedUserInteractor, msdlPlayer,
- userActivityNotifier);
+ emergencyButtonController, featureFlags, selectedUserInteractor,
+ bouncerHapticPlayer, userActivityNotifier);
mKeyguardSecurityCallback = keyguardSecurityCallback;
mInputMethodManager = inputMethodManager;
mPostureController = postureController;
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardPatternViewController.java b/packages/SystemUI/src/com/android/keyguard/KeyguardPatternViewController.java
index f74d93e1d88d..7fb66640b29f 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardPatternViewController.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardPatternViewController.java
@@ -36,7 +36,7 @@ import com.android.internal.widget.LockPatternView.Cell;
import com.android.internal.widget.LockscreenCredential;
import com.android.keyguard.EmergencyButtonController.EmergencyButtonCallback;
import com.android.keyguard.KeyguardSecurityModel.SecurityMode;
-import com.android.systemui.bouncer.ui.helper.BouncerHapticHelper;
+import com.android.systemui.bouncer.ui.helper.BouncerHapticPlayer;
import com.android.systemui.classifier.FalsingClassifier;
import com.android.systemui.classifier.FalsingCollector;
import com.android.systemui.flags.FeatureFlags;
@@ -44,8 +44,6 @@ import com.android.systemui.res.R;
import com.android.systemui.statusbar.policy.DevicePostureController;
import com.android.systemui.user.domain.interactor.SelectedUserInteractor;
-import com.google.android.msdl.domain.MSDLPlayer;
-
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@@ -70,7 +68,6 @@ public class KeyguardPatternViewController
private LockPatternView mLockPatternView;
private CountDownTimer mCountdownTimer;
private AsyncTask<?, ?, ?> mPendingLockCheck;
- private MSDLPlayer mMSDLPlayer;
private EmergencyButtonCallback mEmergencyButtonCallback = new EmergencyButtonCallback() {
@Override
@@ -80,7 +77,7 @@ public class KeyguardPatternViewController
};
private final LockPatternView.ExternalHapticsPlayer mExternalHapticsPlayer = () -> {
- BouncerHapticHelper.INSTANCE.playPatternDotFeedback(mMSDLPlayer, mView);
+ mBouncerHapticPlayer.playPatternDotFeedback(mView);
};
/**
@@ -174,9 +171,8 @@ public class KeyguardPatternViewController
boolean isValidPattern) {
boolean dismissKeyguard = mSelectedUserInteractor.getSelectedUserId() == userId;
if (matched) {
- BouncerHapticHelper.INSTANCE.playMSDLAuthenticationFeedback(
- /* authenticationSucceeded= */true,
- /* player =*/mMSDLPlayer
+ mBouncerHapticPlayer.playAuthenticationFeedback(
+ /* authenticationSucceeded= */true
);
getKeyguardSecurityCallback().reportUnlockAttempt(userId, true, 0);
if (dismissKeyguard) {
@@ -185,9 +181,8 @@ public class KeyguardPatternViewController
getKeyguardSecurityCallback().dismiss(true, userId, SecurityMode.Pattern);
}
} else {
- BouncerHapticHelper.INSTANCE.playMSDLAuthenticationFeedback(
- /* authenticationSucceeded= */false,
- /* player =*/mMSDLPlayer
+ mBouncerHapticPlayer.playAuthenticationFeedback(
+ /* authenticationSucceeded= */false
);
mLockPatternView.setDisplayMode(LockPatternView.DisplayMode.Wrong);
if (isValidPattern) {
@@ -216,9 +211,11 @@ public class KeyguardPatternViewController
EmergencyButtonController emergencyButtonController,
KeyguardMessageAreaController.Factory messageAreaControllerFactory,
DevicePostureController postureController, FeatureFlags featureFlags,
- SelectedUserInteractor selectedUserInteractor, MSDLPlayer msdlPlayer) {
+ SelectedUserInteractor selectedUserInteractor, BouncerHapticPlayer bouncerHapticPlayer
+ ) {
super(view, securityMode, keyguardSecurityCallback, emergencyButtonController,
- messageAreaControllerFactory, featureFlags, selectedUserInteractor);
+ messageAreaControllerFactory, featureFlags, selectedUserInteractor,
+ bouncerHapticPlayer);
mKeyguardUpdateMonitor = keyguardUpdateMonitor;
mLockPatternUtils = lockPatternUtils;
mLatencyTracker = latencyTracker;
@@ -228,7 +225,6 @@ public class KeyguardPatternViewController
featureFlags.isEnabled(LOCKSCREEN_ENABLE_LANDSCAPE));
mLockPatternView = mView.findViewById(R.id.lockPatternView);
mPostureController = postureController;
- mMSDLPlayer = msdlPlayer;
}
@Override
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardPinBasedInputViewController.java b/packages/SystemUI/src/com/android/keyguard/KeyguardPinBasedInputViewController.java
index f575cf29f402..d999994a3312 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardPinBasedInputViewController.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardPinBasedInputViewController.java
@@ -16,11 +16,9 @@
package com.android.keyguard;
-import static com.android.systemui.Flags.msdlFeedback;
import static com.android.systemui.Flags.pinInputFieldStyledFocusState;
import static com.android.systemui.util.kotlin.JavaAdapterKt.collectFlow;
-import android.annotation.Nullable;
import android.graphics.drawable.Drawable;
import android.graphics.drawable.GradientDrawable;
import android.graphics.drawable.StateListDrawable;
@@ -37,14 +35,12 @@ import com.android.internal.widget.LockPatternUtils;
import com.android.keyguard.KeyguardSecurityModel.SecurityMode;
import com.android.keyguard.domain.interactor.KeyguardKeyboardInteractor;
import com.android.systemui.Flags;
+import com.android.systemui.bouncer.ui.helper.BouncerHapticPlayer;
import com.android.systemui.classifier.FalsingCollector;
import com.android.systemui.flags.FeatureFlags;
import com.android.systemui.res.R;
import com.android.systemui.user.domain.interactor.SelectedUserInteractor;
-import com.google.android.msdl.data.model.MSDLToken;
-import com.google.android.msdl.domain.MSDLPlayer;
-
public abstract class KeyguardPinBasedInputViewController<T extends KeyguardPinBasedInputView>
extends KeyguardAbsKeyInputViewController<T> {
@@ -83,12 +79,12 @@ public abstract class KeyguardPinBasedInputViewController<T extends KeyguardPinB
FeatureFlags featureFlags,
SelectedUserInteractor selectedUserInteractor,
KeyguardKeyboardInteractor keyguardKeyboardInteractor,
- @Nullable MSDLPlayer msdlPlayer,
+ BouncerHapticPlayer bouncerHapticPlayer,
UserActivityNotifier userActivityNotifier) {
super(view, keyguardUpdateMonitor, securityMode, lockPatternUtils, keyguardSecurityCallback,
messageAreaControllerFactory, latencyTracker, falsingCollector,
- emergencyButtonController, featureFlags, selectedUserInteractor, msdlPlayer,
- userActivityNotifier);
+ emergencyButtonController, featureFlags, selectedUserInteractor,
+ bouncerHapticPlayer, userActivityNotifier);
mLiftToActivateListener = liftToActivateListener;
mFalsingCollector = falsingCollector;
mKeyguardKeyboardInteractor = keyguardKeyboardInteractor;
@@ -110,16 +106,16 @@ public abstract class KeyguardPinBasedInputViewController<T extends KeyguardPinB
return false;
});
button.setAnimationEnabled(showAnimations);
- button.setMSDLPlayer(mMSDLPlayer);
+ button.setBouncerHapticHelper(mBouncerHapticPlayer);
}
mPasswordEntry.setOnKeyListener(mOnKeyListener);
mPasswordEntry.setUserActivityListener(this::onUserInput);
View deleteButton = mView.findViewById(R.id.delete_button);
- if (msdlFeedback()) {
+ if (mBouncerHapticPlayer.isEnabled()) {
deleteButton.setOnTouchListener((View view, MotionEvent event) -> {
- if (event.getActionMasked() == MotionEvent.ACTION_DOWN && mMSDLPlayer != null) {
- mMSDLPlayer.playToken(MSDLToken.KEYPRESS_DELETE, null);
+ if (event.getActionMasked() == MotionEvent.ACTION_DOWN) {
+ mBouncerHapticPlayer.playDeleteKeyPressFeedback();
}
return false;
});
@@ -137,8 +133,8 @@ public abstract class KeyguardPinBasedInputViewController<T extends KeyguardPinB
if (mPasswordEntry.isEnabled()) {
mView.resetPasswordText(true /* animate */, true /* announce */);
}
- if (msdlFeedback() && mMSDLPlayer != null) {
- mMSDLPlayer.playToken(MSDLToken.LONG_PRESS, null);
+ if (mBouncerHapticPlayer.isEnabled()) {
+ mBouncerHapticPlayer.playDeleteKeyLongPressedFeedback();
} else {
mView.doHapticKeyClick();
}
@@ -147,7 +143,7 @@ public abstract class KeyguardPinBasedInputViewController<T extends KeyguardPinB
View okButton = mView.findViewById(R.id.key_enter);
if (okButton != null) {
- if (!msdlFeedback()) {
+ if (!mBouncerHapticPlayer.isEnabled()) {
okButton.setOnTouchListener(mActionButtonTouchListener);
}
okButton.setOnClickListener(v -> {
@@ -201,7 +197,7 @@ public abstract class KeyguardPinBasedInputViewController<T extends KeyguardPinB
for (NumPadKey button : mView.getButtons()) {
button.setOnTouchListener(null);
- button.setMSDLPlayer(null);
+ button.setBouncerHapticHelper(null);
}
}
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardPinViewController.java b/packages/SystemUI/src/com/android/keyguard/KeyguardPinViewController.java
index 3b5bf1a422a3..d3c02e6f6449 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardPinViewController.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardPinViewController.java
@@ -18,7 +18,6 @@ package com.android.keyguard;
import static com.android.systemui.flags.Flags.LOCKSCREEN_ENABLE_LANDSCAPE;
-import android.annotation.Nullable;
import android.view.View;
import com.android.internal.logging.UiEvent;
@@ -27,6 +26,7 @@ import com.android.internal.util.LatencyTracker;
import com.android.internal.widget.LockPatternUtils;
import com.android.keyguard.KeyguardSecurityModel.SecurityMode;
import com.android.keyguard.domain.interactor.KeyguardKeyboardInteractor;
+import com.android.systemui.bouncer.ui.helper.BouncerHapticPlayer;
import com.android.systemui.classifier.FalsingCollector;
import com.android.systemui.flags.FeatureFlags;
import com.android.systemui.flags.Flags;
@@ -34,8 +34,6 @@ import com.android.systemui.res.R;
import com.android.systemui.statusbar.policy.DevicePostureController;
import com.android.systemui.user.domain.interactor.SelectedUserInteractor;
-import com.google.android.msdl.domain.MSDLPlayer;
-
public class KeyguardPinViewController
extends KeyguardPinBasedInputViewController<KeyguardPINView> {
private final KeyguardUpdateMonitor mKeyguardUpdateMonitor;
@@ -65,12 +63,12 @@ public class KeyguardPinViewController
DevicePostureController postureController, FeatureFlags featureFlags,
SelectedUserInteractor selectedUserInteractor, UiEventLogger uiEventLogger,
KeyguardKeyboardInteractor keyguardKeyboardInteractor,
- @Nullable MSDLPlayer msdlPlayer,
+ BouncerHapticPlayer bouncerHapticPlayer,
UserActivityNotifier userActivityNotifier) {
super(view, keyguardUpdateMonitor, securityMode, lockPatternUtils, keyguardSecurityCallback,
messageAreaControllerFactory, latencyTracker, liftToActivateListener,
emergencyButtonController, falsingCollector, featureFlags, selectedUserInteractor,
- keyguardKeyboardInteractor, msdlPlayer, userActivityNotifier);
+ keyguardKeyboardInteractor, bouncerHapticPlayer, userActivityNotifier);
mKeyguardUpdateMonitor = keyguardUpdateMonitor;
mPostureController = postureController;
mLockPatternUtils = lockPatternUtils;
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardSimPinViewController.java b/packages/SystemUI/src/com/android/keyguard/KeyguardSimPinViewController.java
index 47fe2b22b5f6..1c1acf83fa12 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardSimPinViewController.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardSimPinViewController.java
@@ -21,7 +21,6 @@ import static android.telephony.SubscriptionManager.INVALID_SUBSCRIPTION_ID;
import static com.android.systemui.util.PluralMessageFormaterKt.icuMessageFormat;
import android.annotation.NonNull;
-import android.annotation.Nullable;
import android.app.AlertDialog;
import android.app.AlertDialog.Builder;
import android.app.Dialog;
@@ -44,13 +43,12 @@ import com.android.internal.util.LatencyTracker;
import com.android.internal.widget.LockPatternUtils;
import com.android.keyguard.KeyguardSecurityModel.SecurityMode;
import com.android.keyguard.domain.interactor.KeyguardKeyboardInteractor;
+import com.android.systemui.bouncer.ui.helper.BouncerHapticPlayer;
import com.android.systemui.classifier.FalsingCollector;
import com.android.systemui.flags.FeatureFlags;
import com.android.systemui.res.R;
import com.android.systemui.user.domain.interactor.SelectedUserInteractor;
-import com.google.android.msdl.domain.MSDLPlayer;
-
public class KeyguardSimPinViewController
extends KeyguardPinBasedInputViewController<KeyguardSimPinView> {
public static final String TAG = "KeyguardSimPinView";
@@ -99,12 +97,12 @@ public class KeyguardSimPinViewController
EmergencyButtonController emergencyButtonController, FeatureFlags featureFlags,
SelectedUserInteractor selectedUserInteractor,
KeyguardKeyboardInteractor keyguardKeyboardInteractor,
- @Nullable MSDLPlayer msdlPlayer,
+ BouncerHapticPlayer bouncerHapticPlayer,
UserActivityNotifier userActivityNotifier) {
super(view, keyguardUpdateMonitor, securityMode, lockPatternUtils, keyguardSecurityCallback,
messageAreaControllerFactory, latencyTracker, liftToActivateListener,
emergencyButtonController, falsingCollector, featureFlags, selectedUserInteractor,
- keyguardKeyboardInteractor, msdlPlayer, userActivityNotifier);
+ keyguardKeyboardInteractor, bouncerHapticPlayer, userActivityNotifier);
mKeyguardUpdateMonitor = keyguardUpdateMonitor;
mTelephonyManager = telephonyManager;
mSimImageView = mView.findViewById(R.id.keyguard_sim);
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardSimPukViewController.java b/packages/SystemUI/src/com/android/keyguard/KeyguardSimPukViewController.java
index c688acb8d760..9adc5bae1ada 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardSimPukViewController.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardSimPukViewController.java
@@ -17,7 +17,6 @@
package com.android.keyguard;
import android.annotation.NonNull;
-import android.annotation.Nullable;
import android.app.Activity;
import android.app.AlertDialog;
import android.app.Dialog;
@@ -39,13 +38,12 @@ import com.android.internal.util.LatencyTracker;
import com.android.internal.widget.LockPatternUtils;
import com.android.keyguard.KeyguardSecurityModel.SecurityMode;
import com.android.keyguard.domain.interactor.KeyguardKeyboardInteractor;
+import com.android.systemui.bouncer.ui.helper.BouncerHapticPlayer;
import com.android.systemui.classifier.FalsingCollector;
import com.android.systemui.flags.FeatureFlags;
import com.android.systemui.res.R;
import com.android.systemui.user.domain.interactor.SelectedUserInteractor;
-import com.google.android.msdl.domain.MSDLPlayer;
-
public class KeyguardSimPukViewController
extends KeyguardPinBasedInputViewController<KeyguardSimPukView> {
private static final boolean DEBUG = KeyguardConstants.DEBUG;
@@ -96,12 +94,12 @@ public class KeyguardSimPukViewController
EmergencyButtonController emergencyButtonController, FeatureFlags featureFlags,
SelectedUserInteractor selectedUserInteractor,
KeyguardKeyboardInteractor keyguardKeyboardInteractor,
- @Nullable MSDLPlayer msdlPlayer,
+ BouncerHapticPlayer bouncerHapticPlayer,
UserActivityNotifier userActivityNotifier) {
super(view, keyguardUpdateMonitor, securityMode, lockPatternUtils, keyguardSecurityCallback,
messageAreaControllerFactory, latencyTracker, liftToActivateListener,
emergencyButtonController, falsingCollector, featureFlags, selectedUserInteractor,
- keyguardKeyboardInteractor, msdlPlayer, userActivityNotifier);
+ keyguardKeyboardInteractor, bouncerHapticPlayer, userActivityNotifier);
mKeyguardUpdateMonitor = keyguardUpdateMonitor;
mTelephonyManager = telephonyManager;
mSimImageView = mView.findViewById(R.id.keyguard_sim);
diff --git a/packages/SystemUI/src/com/android/keyguard/NumPadKey.java b/packages/SystemUI/src/com/android/keyguard/NumPadKey.java
index 4fb80de2d4ec..7fe4ec852045 100644
--- a/packages/SystemUI/src/com/android/keyguard/NumPadKey.java
+++ b/packages/SystemUI/src/com/android/keyguard/NumPadKey.java
@@ -15,7 +15,6 @@
*/
package com.android.keyguard;
-import static com.android.systemui.Flags.msdlFeedback;
import static com.android.systemui.bouncer.shared.constants.KeyguardBouncerConstants.ColorId.NUM_PAD_KEY;
import android.content.Context;
@@ -37,11 +36,9 @@ import android.widget.TextView;
import androidx.annotation.Nullable;
import com.android.settingslib.Utils;
+import com.android.systemui.bouncer.ui.helper.BouncerHapticPlayer;
import com.android.systemui.res.R;
-import com.google.android.msdl.data.model.MSDLToken;
-import com.google.android.msdl.domain.MSDLPlayer;
-
/**
* Viewgroup for the bouncer numpad button, specifically for digits.
*/
@@ -62,7 +59,7 @@ public class NumPadKey extends ViewGroup implements NumPadAnimationListener {
private NumPadAnimator mAnimator;
private int mOrientation;
@Nullable
- private MSDLPlayer mMSDLPlayer;
+ private BouncerHapticPlayer mBouncerHapticPlayer;
private View.OnClickListener mListener = new View.OnClickListener() {
@Override
@@ -227,8 +224,8 @@ public class NumPadKey extends ViewGroup implements NumPadAnimationListener {
// Cause a VIRTUAL_KEY vibration
public void doHapticKeyClick() {
- if (msdlFeedback() && mMSDLPlayer != null) {
- mMSDLPlayer.playToken(MSDLToken.KEYPRESS_STANDARD, null);
+ if (mBouncerHapticPlayer != null && mBouncerHapticPlayer.isEnabled()) {
+ mBouncerHapticPlayer.playNumpadKeyFeedback();
} else {
performHapticFeedback(HapticFeedbackConstants.VIRTUAL_KEY,
HapticFeedbackConstants.FLAG_IGNORE_VIEW_SETTING);
@@ -255,7 +252,7 @@ public class NumPadKey extends ViewGroup implements NumPadAnimationListener {
info.setTextEntryKey(true);
}
- public void setMSDLPlayer(@Nullable MSDLPlayer player) {
- mMSDLPlayer = player;
+ public void setBouncerHapticHelper(@Nullable BouncerHapticPlayer bouncerHapticPlayer) {
+ mBouncerHapticPlayer = bouncerHapticPlayer;
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/bouncer/ui/helper/BouncerHapticHelper.kt b/packages/SystemUI/src/com/android/systemui/bouncer/ui/helper/BouncerHapticPlayer.kt
index 1faacff996ca..19e7537007bf 100644
--- a/packages/SystemUI/src/com/android/systemui/bouncer/ui/helper/BouncerHapticHelper.kt
+++ b/packages/SystemUI/src/com/android/systemui/bouncer/ui/helper/BouncerHapticPlayer.kt
@@ -23,25 +23,28 @@ import com.android.systemui.Flags
//noinspection CleanArchitectureDependencyViolation: Data layer only referenced for this enum class
import com.google.android.msdl.data.model.MSDLToken
import com.google.android.msdl.domain.MSDLPlayer
+import javax.inject.Inject
-/** A helper object to deliver haptic feedback in bouncer interactions. */
-object BouncerHapticHelper {
+/**
+ * A helper class to deliver haptic feedback in bouncer interactions.
+ *
+ * @param[msdlPlayer] The [MSDLPlayer] used to deliver MSDL feedback.
+ */
+class BouncerHapticPlayer @Inject constructor(private val msdlPlayer: dagger.Lazy<MSDLPlayer>) {
+
+ private val authInteractionProperties by
+ lazy(LazyThreadSafetyMode.NONE) { AuthInteractionProperties() }
- private val authInteractionProperties = AuthInteractionProperties()
+ val isEnabled: Boolean
+ get() = Flags.msdlFeedback()
/**
* Deliver MSDL feedback as a result of authenticating through a bouncer.
*
* @param[authenticationSucceeded] Whether the authentication was successful or not.
- * @param[player] The [MSDLPlayer] that delivers the correct feedback.
*/
- fun playMSDLAuthenticationFeedback(
- authenticationSucceeded: Boolean,
- player: MSDLPlayer?,
- ) {
- if (player == null || !Flags.msdlFeedback()) {
- return
- }
+ fun playAuthenticationFeedback(authenticationSucceeded: Boolean) {
+ if (!isEnabled) return
val token =
if (authenticationSucceeded) {
@@ -49,7 +52,7 @@ object BouncerHapticHelper {
} else {
MSDLToken.FAILURE
}
- player.playToken(token, authInteractionProperties)
+ msdlPlayer.get().playToken(token, authInteractionProperties)
}
/**
@@ -57,17 +60,29 @@ object BouncerHapticHelper {
* MSDL feedback using a [MSDLPlayer], or fallback to a default haptic feedback using the
* [View.performHapticFeedback] API and a [View].
*
- * @param[player] [MSDLPlayer] for MSDL feedback.
* @param[view] A [View] for default haptic feedback using [View.performHapticFeedback]
*/
- fun playPatternDotFeedback(player: MSDLPlayer?, view: View?) {
- if (player == null || !Flags.msdlFeedback()) {
+ fun playPatternDotFeedback(view: View?) {
+ if (!isEnabled) {
view?.performHapticFeedback(
HapticFeedbackConstants.VIRTUAL_KEY,
HapticFeedbackConstants.FLAG_IGNORE_VIEW_SETTING,
)
} else {
- player.playToken(MSDLToken.DRAG_INDICATOR)
+ msdlPlayer.get().playToken(MSDLToken.DRAG_INDICATOR)
}
}
+
+ /** Deliver MSDL feedback when the delete key of the pin bouncer is pressed */
+ fun playDeleteKeyPressFeedback() = msdlPlayer.get().playToken(MSDLToken.KEYPRESS_DELETE)
+
+ /**
+ * Deliver MSDL feedback when the delete key of the pin bouncer is long-pressed
+ *
+ * @return whether MSDL feedback is allowed to play.
+ */
+ fun playDeleteKeyLongPressedFeedback() = msdlPlayer.get().playToken(MSDLToken.LONG_PRESS)
+
+ /** Deliver MSDL feedback when a numpad key is pressed on the pin bouncer */
+ fun playNumpadKeyFeedback() = msdlPlayer.get().playToken(MSDLToken.KEYPRESS_STANDARD)
}
diff --git a/packages/SystemUI/src/com/android/systemui/bouncer/ui/viewmodel/PinBouncerViewModel.kt b/packages/SystemUI/src/com/android/systemui/bouncer/ui/viewmodel/PinBouncerViewModel.kt
index df6ca9bf0511..da29c6230cd8 100644
--- a/packages/SystemUI/src/com/android/systemui/bouncer/ui/viewmodel/PinBouncerViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/bouncer/ui/viewmodel/PinBouncerViewModel.kt
@@ -31,6 +31,7 @@ import com.android.keyguard.PinShapeAdapter
import com.android.systemui.authentication.shared.model.AuthenticationMethodModel
import com.android.systemui.bouncer.domain.interactor.BouncerInteractor
import com.android.systemui.bouncer.domain.interactor.SimBouncerInteractor
+import com.android.systemui.bouncer.shared.flag.ComposeBouncerFlags
import com.android.systemui.res.R
import dagger.assisted.Assisted
import dagger.assisted.AssistedFactory
@@ -265,6 +266,15 @@ constructor(
}
}
+ /** Notifies that the user has pressed down on a digit button. */
+ fun onDigitButtonDown() {
+ if (ComposeBouncerFlags.isOnlyComposeBouncerEnabled()) {
+ // Current PIN bouncer informs FalsingInteractor#avoidGesture() upon every Pin button
+ // touch.
+ super.onDown()
+ }
+ }
+
@AssistedFactory
interface Factory {
fun create(
diff --git a/packages/SystemUI/src/com/android/systemui/classifier/FalsingCollectorFake.java b/packages/SystemUI/src/com/android/systemui/classifier/FalsingCollectorFake.java
index dcd419512498..a62600d65d4b 100644
--- a/packages/SystemUI/src/com/android/systemui/classifier/FalsingCollectorFake.java
+++ b/packages/SystemUI/src/com/android/systemui/classifier/FalsingCollectorFake.java
@@ -25,6 +25,7 @@ import javax.inject.Inject;
public class FalsingCollectorFake implements FalsingCollector {
public KeyEvent lastKeyEvent = null;
+ public boolean avoidGestureInvoked = false;
@Override
public void init() {
@@ -87,6 +88,16 @@ public class FalsingCollectorFake implements FalsingCollector {
@Override
public void avoidGesture() {
+ avoidGestureInvoked = true;
+ }
+
+ /**
+ * @return whether {@link #avoidGesture()} was invoked.
+ */
+ public boolean wasLastGestureAvoided() {
+ boolean wasLastGestureAvoided = avoidGestureInvoked;
+ avoidGestureInvoked = false;
+ return wasLastGestureAvoided;
}
@Override
diff --git a/packages/SystemUI/src/com/android/systemui/deviceentry/domain/interactor/DeviceEntryInteractor.kt b/packages/SystemUI/src/com/android/systemui/deviceentry/domain/interactor/DeviceEntryInteractor.kt
index 7018f9dc8556..dbd7f0739f6c 100644
--- a/packages/SystemUI/src/com/android/systemui/deviceentry/domain/interactor/DeviceEntryInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/deviceentry/domain/interactor/DeviceEntryInteractor.kt
@@ -24,8 +24,11 @@ import com.android.systemui.dagger.SysUISingleton
import com.android.systemui.dagger.qualifiers.Application
import com.android.systemui.deviceentry.data.repository.DeviceEntryRepository
import com.android.systemui.keyguard.DismissCallbackRegistry
+import com.android.systemui.scene.data.model.asIterable
+import com.android.systemui.scene.domain.interactor.SceneBackInteractor
import com.android.systemui.scene.domain.interactor.SceneInteractor
import com.android.systemui.scene.shared.model.Scenes
+import com.android.systemui.util.kotlin.pairwise
import com.android.systemui.utils.coroutines.flow.mapLatestConflated
import javax.inject.Inject
import kotlinx.coroutines.CoroutineScope
@@ -34,6 +37,7 @@ import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.SharingStarted
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.combine
+import kotlinx.coroutines.flow.distinctUntilChanged
import kotlinx.coroutines.flow.filter
import kotlinx.coroutines.flow.first
import kotlinx.coroutines.flow.map
@@ -59,6 +63,7 @@ constructor(
private val deviceUnlockedInteractor: DeviceUnlockedInteractor,
private val alternateBouncerInteractor: AlternateBouncerInteractor,
private val dismissCallbackRegistry: DismissCallbackRegistry,
+ sceneBackInteractor: SceneBackInteractor,
) {
/**
* Whether the device is unlocked.
@@ -86,19 +91,40 @@ constructor(
* Note: This does not imply that the lockscreen is visible or not.
*/
val isDeviceEntered: StateFlow<Boolean> =
- sceneInteractor.currentScene
- .filter { currentScene ->
- currentScene == Scenes.Gone || currentScene == Scenes.Lockscreen
- }
- .mapLatestConflated { scene ->
- if (scene == Scenes.Gone) {
- // Make sure device unlock status is definitely unlocked before we consider the
- // device "entered".
- deviceUnlockedInteractor.deviceUnlockStatus.first { it.isUnlocked }
- true
- } else {
- false
- }
+ combine(
+ // This flow emits true when the currentScene switches to Gone for the first time
+ // after having been on Lockscreen.
+ sceneInteractor.currentScene
+ .filter { currentScene ->
+ currentScene == Scenes.Gone || currentScene == Scenes.Lockscreen
+ }
+ .mapLatestConflated { scene ->
+ if (scene == Scenes.Gone) {
+ // Make sure device unlock status is definitely unlocked before we
+ // consider the device "entered".
+ deviceUnlockedInteractor.deviceUnlockStatus.first { it.isUnlocked }
+ true
+ } else {
+ false
+ }
+ },
+ // This flow emits true only if the bottom of the navigation back stack has been
+ // switched from Lockscreen to Gone. In other words, only if the device was unlocked
+ // while visiting at least one scene "above" the Lockscreen scene.
+ sceneBackInteractor.backStack
+ // The bottom of the back stack, which is Lockscreen, Gone, or null if empty.
+ .map { it.asIterable().lastOrNull() }
+ // Filter out cases where the stack changes but the bottom remains unchanged.
+ .distinctUntilChanged()
+ // Detect changes of the bottom of the stack, start with null, so the first
+ // update emits a value and the logic doesn't need to wait for a second value
+ // before emitting something.
+ .pairwise(initialValue = null)
+ // Replacing a bottom of the stack that was Lockscreen with Gone constitutes a
+ // "device entered" event.
+ .map { (from, to) -> from == Scenes.Lockscreen && to == Scenes.Gone },
+ ) { enteredDirectly, enteredOnBackStack ->
+ enteredOnBackStack || enteredDirectly
}
.stateIn(
scope = applicationScope,
@@ -129,7 +155,7 @@ constructor(
},
isLockscreenEnabled,
deviceUnlockedInteractor.deviceUnlockStatus,
- isDeviceEntered
+ isDeviceEntered,
) { isNoneAuthMethod, isLockscreenEnabled, deviceUnlockStatus, isDeviceEntered ->
val isSwipeAuthMethod = isNoneAuthMethod && isLockscreenEnabled
(isSwipeAuthMethod ||
@@ -155,9 +181,7 @@ constructor(
* canceled
*/
@JvmOverloads
- fun attemptDeviceEntry(
- callback: IKeyguardDismissCallback? = null,
- ) {
+ fun attemptDeviceEntry(callback: IKeyguardDismissCallback? = null) {
callback?.let { dismissCallbackRegistry.addCallback(it) }
// TODO (b/307768356),
diff --git a/packages/SystemUI/src/com/android/systemui/keyboard/shortcut/ui/composable/ShortcutHelper.kt b/packages/SystemUI/src/com/android/systemui/keyboard/shortcut/ui/composable/ShortcutHelper.kt
index dcca12f29287..beec34881636 100644
--- a/packages/SystemUI/src/com/android/systemui/keyboard/shortcut/ui/composable/ShortcutHelper.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyboard/shortcut/ui/composable/ShortcutHelper.kt
@@ -736,14 +736,13 @@ private fun CategoryItemTwoPane(
val interactionSource = remember { MutableInteractionSource() }
val isFocused by interactionSource.collectIsFocusedAsState()
- Surface(
+ SelectableShortcutSurface(
selected = selected,
onClick = onClick,
modifier =
Modifier.semantics { role = Role.Tab }
.heightIn(min = 64.dp)
.fillMaxWidth()
- .focusable(interactionSource = interactionSource)
.outlineFocusModifier(
isFocused = isFocused,
focusColor = MaterialTheme.colorScheme.secondary,
@@ -752,6 +751,7 @@ private fun CategoryItemTwoPane(
),
shape = RoundedCornerShape(28.dp),
color = colors.containerColor(selected).value,
+ interactionSource = interactionSource
) {
Row(Modifier.padding(horizontal = 24.dp), verticalAlignment = Alignment.CenterVertically) {
ShortcutCategoryIcon(
@@ -860,14 +860,12 @@ private fun ShortcutsSearchBar(onQueryChange: (String) -> Unit) {
private fun KeyboardSettings(horizontalPadding: Dp, verticalPadding: Dp, onClick: () -> Unit) {
val interactionSource = remember { MutableInteractionSource() }
val isFocused by interactionSource.collectIsFocusedAsState()
- Surface(
+ ClickableShortcutSurface(
onClick = onClick,
shape = RoundedCornerShape(24.dp),
color = Color.Transparent,
- modifier =
- Modifier.semantics { role = Role.Button }
- .fillMaxWidth()
- .focusable(interactionSource = interactionSource)
+ modifier = Modifier.semantics { role = Role.Button }.fillMaxWidth(),
+ interactionSource = interactionSource
) {
Row(
modifier =
diff --git a/packages/SystemUI/src/com/android/systemui/keyboard/shortcut/ui/composable/Surfaces.kt b/packages/SystemUI/src/com/android/systemui/keyboard/shortcut/ui/composable/Surfaces.kt
new file mode 100644
index 000000000000..3ba3bd8fdc2f
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/keyboard/shortcut/ui/composable/Surfaces.kt
@@ -0,0 +1,199 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.keyboard.shortcut.ui.composable
+
+import androidx.compose.foundation.BorderStroke
+import androidx.compose.foundation.background
+import androidx.compose.foundation.border
+import androidx.compose.foundation.clickable
+import androidx.compose.foundation.interaction.MutableInteractionSource
+import androidx.compose.foundation.layout.Box
+import androidx.compose.foundation.selection.selectable
+import androidx.compose.material3.ColorScheme
+import androidx.compose.material3.LocalAbsoluteTonalElevation
+import androidx.compose.material3.LocalContentColor
+import androidx.compose.material3.LocalTonalElevationEnabled
+import androidx.compose.material3.MaterialTheme
+import androidx.compose.material3.contentColorFor
+import androidx.compose.material3.minimumInteractiveComponentSize
+import androidx.compose.material3.surfaceColorAtElevation
+import androidx.compose.runtime.Composable
+import androidx.compose.runtime.CompositionLocalProvider
+import androidx.compose.runtime.NonRestartableComposable
+import androidx.compose.runtime.Stable
+import androidx.compose.runtime.remember
+import androidx.compose.ui.Modifier
+import androidx.compose.ui.draw.clip
+import androidx.compose.ui.graphics.Color
+import androidx.compose.ui.graphics.RectangleShape
+import androidx.compose.ui.graphics.Shape
+import androidx.compose.ui.graphics.graphicsLayer
+import androidx.compose.ui.platform.LocalDensity
+import androidx.compose.ui.unit.Dp
+import androidx.compose.ui.unit.dp
+import com.android.compose.modifiers.thenIf
+
+/**
+ * A selectable surface with no default focus/hover indications.
+ *
+ * This composable is similar to [androidx.compose.material3.Surface], but removes default
+ * focus/hover states to enable custom implementations.
+ */
+@Composable
+@NonRestartableComposable
+fun SelectableShortcutSurface(
+ selected: Boolean,
+ onClick: () -> Unit,
+ modifier: Modifier = Modifier,
+ enabled: Boolean = true,
+ shape: Shape = RectangleShape,
+ color: Color = MaterialTheme.colorScheme.surface,
+ contentColor: Color = contentColorFor(color),
+ tonalElevation: Dp = 0.dp,
+ shadowElevation: Dp = 0.dp,
+ border: BorderStroke? = null,
+ interactionSource: MutableInteractionSource? = null,
+ content: @Composable () -> Unit
+) {
+ @Suppress("NAME_SHADOWING")
+ val interactionSource = interactionSource ?: remember { MutableInteractionSource() }
+ val absoluteElevation = LocalAbsoluteTonalElevation.current + tonalElevation
+ CompositionLocalProvider(
+ LocalContentColor provides contentColor,
+ LocalAbsoluteTonalElevation provides absoluteElevation
+ ) {
+ Box(
+ modifier =
+ modifier
+ .minimumInteractiveComponentSize()
+ .surface(
+ shape = shape,
+ backgroundColor =
+ surfaceColorAtElevation(color = color, elevation = absoluteElevation),
+ border = border,
+ shadowElevation = with(LocalDensity.current) { shadowElevation.toPx() }
+ )
+ .selectable(
+ selected = selected,
+ interactionSource = interactionSource,
+ indication = null,
+ enabled = enabled,
+ onClick = onClick
+ ),
+ propagateMinConstraints = true
+ ) {
+ content()
+ }
+ }
+}
+
+/**
+ * A clickable surface with no default focus/hover indications.
+ *
+ * This composable is similar to [androidx.compose.material3.Surface], but removes default
+ * focus/hover states to enable custom implementations.
+ */
+@Composable
+@NonRestartableComposable
+fun ClickableShortcutSurface(
+ onClick: () -> Unit,
+ modifier: Modifier = Modifier,
+ enabled: Boolean = true,
+ shape: Shape = RectangleShape,
+ color: Color = MaterialTheme.colorScheme.surface,
+ contentColor: Color = contentColorFor(color),
+ tonalElevation: Dp = 0.dp,
+ shadowElevation: Dp = 0.dp,
+ border: BorderStroke? = null,
+ interactionSource: MutableInteractionSource? = null,
+ content: @Composable () -> Unit
+) {
+ @Suppress("NAME_SHADOWING")
+ val interactionSource = interactionSource ?: remember { MutableInteractionSource() }
+ val absoluteElevation = LocalAbsoluteTonalElevation.current + tonalElevation
+ CompositionLocalProvider(
+ LocalContentColor provides contentColor,
+ LocalAbsoluteTonalElevation provides absoluteElevation
+ ) {
+ Box(
+ modifier =
+ modifier
+ .minimumInteractiveComponentSize()
+ .surface(
+ shape = shape,
+ backgroundColor =
+ surfaceColorAtElevation(color = color, elevation = absoluteElevation),
+ border = border,
+ shadowElevation = with(LocalDensity.current) { shadowElevation.toPx() }
+ )
+ .clickable(
+ interactionSource = interactionSource,
+ indication = null,
+ enabled = enabled,
+ onClick = onClick
+ ),
+ propagateMinConstraints = true
+ ) {
+ content()
+ }
+ }
+}
+
+@Composable
+private fun surfaceColorAtElevation(color: Color, elevation: Dp): Color {
+ return MaterialTheme.colorScheme.applyTonalElevation(color, elevation)
+}
+
+@Composable
+internal fun ColorScheme.applyTonalElevation(backgroundColor: Color, elevation: Dp): Color {
+ val tonalElevationEnabled = LocalTonalElevationEnabled.current
+ return if (backgroundColor == surface && tonalElevationEnabled) {
+ surfaceColorAtElevation(elevation)
+ } else {
+ backgroundColor
+ }
+}
+
+/**
+ * Applies surface-related modifiers to a composable.
+ *
+ * This function adds background, border, and shadow effects to a composable. Also ensure the
+ * composable is clipped to the given shape.
+ *
+ * @param shape The shape to apply to the composable's background, border, and clipping.
+ * @param backgroundColor The background color to apply to the composable.
+ * @param border An optional border to draw around the composable.
+ * @param shadowElevation The size of the shadow below the surface. To prevent shadow creep, only
+ * apply shadow elevation when absolutely necessary, such as when the surface requires visual
+ * separation from a patterned background. Note that It will not affect z index of the Surface. If
+ * you want to change the drawing order you can use `Modifier.zIndex`.
+ * @return The modified Modifier instance with surface-related modifiers applied.
+ */
+@Stable
+private fun Modifier.surface(
+ shape: Shape,
+ backgroundColor: Color,
+ border: BorderStroke?,
+ shadowElevation: Float,
+): Modifier {
+ return this.thenIf(shadowElevation > 0f) {
+ Modifier.graphicsLayer(shadowElevation = shadowElevation, shape = shape, clip = false)
+ }
+ .thenIf(border != null) { Modifier.border(border!!, shape) }
+ .background(color = backgroundColor, shape = shape)
+ .clip(shape)
+}
diff --git a/packages/SystemUI/src/com/android/systemui/media/controls/ui/controller/MediaCarouselController.kt b/packages/SystemUI/src/com/android/systemui/media/controls/ui/controller/MediaCarouselController.kt
index bf9ef8c5d24e..8505a784d302 100644
--- a/packages/SystemUI/src/com/android/systemui/media/controls/ui/controller/MediaCarouselController.kt
+++ b/packages/SystemUI/src/com/android/systemui/media/controls/ui/controller/MediaCarouselController.kt
@@ -1202,13 +1202,17 @@ constructor(
commonViewModels.forEach { viewModel ->
when (viewModel) {
is MediaCommonViewModel.MediaControl -> {
- controllerById[viewModel.instanceId.toString()]?.mediaViewHolder?.let {
- mediaContent.addView(it.player)
+ controllerById[viewModel.instanceId.toString()]?.let {
+ it.widthInSceneContainerPx = widthInSceneContainerPx
+ it.heightInSceneContainerPx = heightInSceneContainerPx
+ mediaContent.addView(it.mediaViewHolder?.player)
}
}
is MediaCommonViewModel.MediaRecommendations -> {
- controllerById[viewModel.key]?.recommendationViewHolder?.let {
- mediaContent.addView(it.recommendations)
+ controllerById[viewModel.key]?.let {
+ it.widthInSceneContainerPx = widthInSceneContainerPx
+ it.heightInSceneContainerPx = heightInSceneContainerPx
+ mediaContent.addView(it.recommendationViewHolder?.recommendations)
}
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/scene/domain/interactor/SceneBackInteractor.kt b/packages/SystemUI/src/com/android/systemui/scene/domain/interactor/SceneBackInteractor.kt
index 2d40845df802..afb72f03b28d 100644
--- a/packages/SystemUI/src/com/android/systemui/scene/domain/interactor/SceneBackInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/scene/domain/interactor/SceneBackInteractor.kt
@@ -71,6 +71,12 @@ constructor(
logger.logSceneBackStack(backStack.value.asIterable())
}
+ /** Applies the given [transform] to the back stack. */
+ fun updateBackStack(transform: (SceneStack) -> SceneStack) {
+ _backStack.update { stack -> transform(stack) }
+ logger.logSceneBackStack(backStack.value.asIterable())
+ }
+
private fun stackOperation(from: SceneKey, to: SceneKey, stack: SceneStack): StackOperation? {
val fromDistance =
checkNotNull(sceneContainerConfig.navigationDistances[from]) {
diff --git a/packages/SystemUI/src/com/android/systemui/scene/domain/startable/SceneContainerStartable.kt b/packages/SystemUI/src/com/android/systemui/scene/domain/startable/SceneContainerStartable.kt
index 18767f576fef..b11d8ed9ee3d 100644
--- a/packages/SystemUI/src/com/android/systemui/scene/domain/startable/SceneContainerStartable.kt
+++ b/packages/SystemUI/src/com/android/systemui/scene/domain/startable/SceneContainerStartable.kt
@@ -45,7 +45,6 @@ import com.android.systemui.deviceentry.shared.model.DeviceUnlockSource
import com.android.systemui.keyguard.DismissCallbackRegistry
import com.android.systemui.keyguard.domain.interactor.KeyguardEnabledInteractor
import com.android.systemui.keyguard.domain.interactor.KeyguardInteractor
-import com.android.systemui.keyguard.domain.interactor.KeyguardTransitionInteractor
import com.android.systemui.keyguard.domain.interactor.WindowManagerLockscreenVisibilityInteractor
import com.android.systemui.model.SceneContainerPlugin
import com.android.systemui.model.SysUiState
@@ -55,6 +54,7 @@ import com.android.systemui.plugins.FalsingManager.FalsingBeliefListener
import com.android.systemui.power.domain.interactor.PowerInteractor
import com.android.systemui.power.shared.model.WakeSleepReason
import com.android.systemui.scene.data.model.asIterable
+import com.android.systemui.scene.data.model.sceneStackOf
import com.android.systemui.scene.domain.interactor.SceneBackInteractor
import com.android.systemui.scene.domain.interactor.SceneContainerOcclusionInteractor
import com.android.systemui.scene.domain.interactor.SceneInteractor
@@ -118,7 +118,6 @@ constructor(
private val deviceUnlockedInteractor: DeviceUnlockedInteractor,
private val bouncerInteractor: BouncerInteractor,
private val keyguardInteractor: KeyguardInteractor,
- private val keyguardTransitionInteractor: KeyguardTransitionInteractor,
private val sysUiState: SysUiState,
@DisplayId private val displayId: Int,
private val sceneLogger: SceneLogger,
@@ -419,7 +418,20 @@ constructor(
" didn't need to be left open"
} else {
val prevScene = previousScene.value
- (prevScene ?: Scenes.Gone) to
+ val targetScene = prevScene ?: Scenes.Gone
+ if (targetScene != Scenes.Gone) {
+ sceneBackInteractor.updateBackStack { stack ->
+ val list = stack.asIterable().toMutableList()
+ check(list.last() == Scenes.Lockscreen) {
+ "The bottommost/last SceneKey of the back stack isn't" +
+ " the Lockscreen scene like expected. The back" +
+ " stack is $stack."
+ }
+ list[list.size - 1] = Scenes.Gone
+ sceneStackOf(*list.toTypedArray())
+ }
+ }
+ targetScene to
"device was unlocked with primary bouncer showing," +
" from sceneKey=$prevScene"
}
diff --git a/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogImpl.java b/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogImpl.java
index 7786453814e0..db4f9ef13bd6 100644
--- a/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogImpl.java
@@ -1991,7 +1991,7 @@ public class VolumeDialogImpl implements VolumeDialog, Dumpable,
: R.drawable.ic_volume_media_bt;
}
} else if (isStreamMuted(ss)) {
- iconRes = (ss.muted && isTv()) ? R.drawable.ic_volume_media_off : row.iconMuteRes;
+ iconRes = row.iconMuteRes;
} else {
iconRes = mShowLowMediaVolumeIcon && ss.level * 2 < (ss.levelMax + ss.levelMin)
? R.drawable.ic_volume_media_low : row.iconRes;
diff --git a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardAbsKeyInputViewControllerTest.java b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardAbsKeyInputViewControllerTest.java
index c0d8be322cd6..4bb01ec1e1df 100644
--- a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardAbsKeyInputViewControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardAbsKeyInputViewControllerTest.java
@@ -43,6 +43,7 @@ import com.android.keyguard.KeyguardAbsKeyInputView.KeyDownListener;
import com.android.keyguard.KeyguardSecurityModel.SecurityMode;
import com.android.systemui.Flags;
import com.android.systemui.SysuiTestCase;
+import com.android.systemui.bouncer.ui.helper.BouncerHapticPlayer;
import com.android.systemui.classifier.FalsingCollector;
import com.android.systemui.classifier.FalsingCollectorFake;
import com.android.systemui.flags.FakeFeatureFlags;
@@ -96,6 +97,8 @@ public class KeyguardAbsKeyInputViewControllerTest extends SysuiTestCase {
private UserActivityNotifier mUserActivityNotifier;
private KeyguardAbsKeyInputViewController mKeyguardAbsKeyInputViewController;
private KosmosJavaAdapter mKosmosJavaAdapter = new KosmosJavaAdapter(this);
+ private final BouncerHapticPlayer mBouncerHapticPlayer =
+ mKosmosJavaAdapter.getBouncerHapticHelper();
private final FakeMSDLPlayer mMSDLPlayer = mKosmosJavaAdapter.getMsdlPlayer();
@Before
@@ -119,8 +122,8 @@ public class KeyguardAbsKeyInputViewControllerTest extends SysuiTestCase {
return new KeyguardAbsKeyInputViewController(mAbsKeyInputView,
mKeyguardUpdateMonitor, mSecurityMode, mLockPatternUtils, mKeyguardSecurityCallback,
mKeyguardMessageAreaControllerFactory, mLatencyTracker, mFalsingCollector,
- mEmergencyButtonController, mFeatureFlags, mSelectedUserInteractor, mMSDLPlayer,
- mUserActivityNotifier) {
+ mEmergencyButtonController, mFeatureFlags, mSelectedUserInteractor,
+ mBouncerHapticPlayer, mUserActivityNotifier) {
@Override
void resetState() {
}
diff --git a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardPinViewControllerTest.kt b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardPinViewControllerTest.kt
index 873bc2c92431..2c1dacdfae73 100644
--- a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardPinViewControllerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardPinViewControllerTest.kt
@@ -35,11 +35,13 @@ import com.android.systemui.classifier.FalsingCollector
import com.android.systemui.classifier.FalsingCollectorFake
import com.android.systemui.flags.FeatureFlags
import com.android.systemui.flags.Flags
+import com.android.systemui.haptics.msdl.bouncerHapticPlayer
import com.android.systemui.keyboard.data.repository.FakeKeyboardRepository
import com.android.systemui.res.R
import com.android.systemui.statusbar.policy.DevicePostureController
import com.android.systemui.statusbar.policy.DevicePostureController.DEVICE_POSTURE_HALF_OPENED
import com.android.systemui.statusbar.policy.DevicePostureController.DEVICE_POSTURE_OPENED
+import com.android.systemui.testKosmos
import com.android.systemui.user.domain.interactor.SelectedUserInteractor
import com.android.systemui.util.mockito.whenever
import com.google.common.truth.Truth.assertThat
@@ -107,6 +109,8 @@ class KeyguardPinViewControllerTest : SysuiTestCase() {
@Captor lateinit var postureCallbackCaptor: ArgumentCaptor<DevicePostureController.Callback>
+ private val kosmos = testKosmos()
+
@Before
fun setup() {
MockitoAnnotations.initMocks(this)
@@ -151,8 +155,8 @@ class KeyguardPinViewControllerTest : SysuiTestCase() {
mSelectedUserInteractor,
uiEventLogger,
keyguardKeyboardInteractor,
- null,
- mUserActivityNotifier
+ kosmos.bouncerHapticPlayer,
+ mUserActivityNotifier,
)
}
diff --git a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardSimPinViewControllerTest.kt b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardSimPinViewControllerTest.kt
index f141a4926149..9cd52153eff6 100644
--- a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardSimPinViewControllerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardSimPinViewControllerTest.kt
@@ -28,8 +28,10 @@ import com.android.systemui.Flags
import com.android.systemui.SysuiTestCase
import com.android.systemui.classifier.FalsingCollector
import com.android.systemui.flags.FakeFeatureFlags
+import com.android.systemui.haptics.msdl.bouncerHapticPlayer
import com.android.systemui.keyboard.data.repository.FakeKeyboardRepository
import com.android.systemui.res.R
+import com.android.systemui.testKosmos
import com.android.systemui.user.domain.interactor.SelectedUserInteractor
import com.android.systemui.util.mockito.any
import com.android.systemui.util.mockito.mock
@@ -73,6 +75,8 @@ class KeyguardSimPinViewControllerTest : SysuiTestCase() {
private val updateMonitorCallbackArgumentCaptor =
ArgumentCaptor.forClass(KeyguardUpdateMonitorCallback::class.java)
+ private val kosmos = testKosmos()
+
@Before
fun setup() {
MockitoAnnotations.initMocks(this)
@@ -103,8 +107,8 @@ class KeyguardSimPinViewControllerTest : SysuiTestCase() {
fakeFeatureFlags,
mSelectedUserInteractor,
keyguardKeyboardInteractor,
- null,
- mUserActivityNotifier
+ kosmos.bouncerHapticPlayer,
+ mUserActivityNotifier,
)
underTest.init()
underTest.onViewAttached()
@@ -162,14 +166,14 @@ class KeyguardSimPinViewControllerTest : SysuiTestCase() {
updateMonitorCallbackArgumentCaptor.value.onSimStateChanged(
/* subId= */ 0,
/* slotId= */ 0,
- TelephonyManager.SIM_STATE_PIN_REQUIRED
+ TelephonyManager.SIM_STATE_PIN_REQUIRED,
)
verify(keyguardSecurityCallback, never()).showCurrentSecurityScreen()
updateMonitorCallbackArgumentCaptor.value.onSimStateChanged(
/* subId= */ 0,
/* slotId= */ 0,
- TelephonyManager.SIM_STATE_PUK_REQUIRED
+ TelephonyManager.SIM_STATE_PUK_REQUIRED,
)
verify(keyguardSecurityCallback).showCurrentSecurityScreen()
diff --git a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardSimPukViewControllerTest.kt b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardSimPukViewControllerTest.kt
index a03c8391fa0f..3c229975eef5 100644
--- a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardSimPukViewControllerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardSimPukViewControllerTest.kt
@@ -29,8 +29,10 @@ import com.android.systemui.Flags
import com.android.systemui.SysuiTestCase
import com.android.systemui.classifier.FalsingCollector
import com.android.systemui.flags.FakeFeatureFlags
+import com.android.systemui.haptics.msdl.bouncerHapticPlayer
import com.android.systemui.keyboard.data.repository.FakeKeyboardRepository
import com.android.systemui.res.R
+import com.android.systemui.testKosmos
import com.android.systemui.user.domain.interactor.SelectedUserInteractor
import com.android.systemui.util.mockito.any
import org.junit.Before
@@ -65,6 +67,8 @@ class KeyguardSimPukViewControllerTest : SysuiTestCase() {
KeyguardMessageAreaController<BouncerKeyguardMessageArea>
@Mock private lateinit var mUserActivityNotifier: UserActivityNotifier
+ private val kosmos = testKosmos()
+
@Before
fun setup() {
MockitoAnnotations.initMocks(this)
@@ -98,8 +102,8 @@ class KeyguardSimPukViewControllerTest : SysuiTestCase() {
fakeFeatureFlags,
mSelectedUserInteractor,
keyguardKeyboardInteractor,
- null,
- mUserActivityNotifier
+ kosmos.bouncerHapticPlayer,
+ mUserActivityNotifier,
)
underTest.init()
}
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/classifier/FalsingCollectorKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/classifier/FalsingCollectorKosmos.kt
index d31491d22435..25c4bbb75aec 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/classifier/FalsingCollectorKosmos.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/classifier/FalsingCollectorKosmos.kt
@@ -18,4 +18,6 @@ package com.android.systemui.classifier
import com.android.systemui.kosmos.Kosmos
-var Kosmos.falsingCollector by Kosmos.Fixture<FalsingCollector> { FalsingCollectorFake() }
+var Kosmos.fakeFalsingCollector by Kosmos.Fixture { FalsingCollectorFake() }
+
+var Kosmos.falsingCollector by Kosmos.Fixture<FalsingCollector> { fakeFalsingCollector }
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/deviceentry/domain/interactor/DeviceEntryInteractorKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/deviceentry/domain/interactor/DeviceEntryInteractorKosmos.kt
index 13116e7fd46f..096022ce1507 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/deviceentry/domain/interactor/DeviceEntryInteractorKosmos.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/deviceentry/domain/interactor/DeviceEntryInteractorKosmos.kt
@@ -22,6 +22,7 @@ import com.android.systemui.deviceentry.data.repository.deviceEntryRepository
import com.android.systemui.keyguard.dismissCallbackRegistry
import com.android.systemui.kosmos.Kosmos
import com.android.systemui.kosmos.applicationCoroutineScope
+import com.android.systemui.scene.domain.interactor.sceneBackInteractor
import com.android.systemui.scene.domain.interactor.sceneInteractor
import kotlinx.coroutines.ExperimentalCoroutinesApi
@@ -36,5 +37,6 @@ val Kosmos.deviceEntryInteractor by
deviceUnlockedInteractor = deviceUnlockedInteractor,
alternateBouncerInteractor = alternateBouncerInteractor,
dismissCallbackRegistry = dismissCallbackRegistry,
+ sceneBackInteractor = sceneBackInteractor,
)
}
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/haptics/msdl/BouncerHapticHelperKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/haptics/msdl/BouncerHapticHelperKosmos.kt
new file mode 100644
index 000000000000..94982edcd5f3
--- /dev/null
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/haptics/msdl/BouncerHapticHelperKosmos.kt
@@ -0,0 +1,28 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.haptics.msdl
+
+import com.android.systemui.bouncer.ui.helper.BouncerHapticPlayer
+import com.android.systemui.kosmos.Kosmos
+import com.google.android.msdl.domain.MSDLPlayer
+import dagger.Lazy
+
+val Kosmos.bouncerHapticPlayer: BouncerHapticPlayer by
+ Kosmos.Fixture {
+ val lazyPlayer = Lazy<MSDLPlayer> { fakeMSDLPlayer }
+ BouncerHapticPlayer(lazyPlayer)
+ }
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/kosmos/KosmosJavaAdapter.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/kosmos/KosmosJavaAdapter.kt
index c60305e85b22..f97f30383398 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/kosmos/KosmosJavaAdapter.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/kosmos/KosmosJavaAdapter.kt
@@ -36,6 +36,7 @@ import com.android.systemui.deviceentry.domain.interactor.deviceEntryInteractor
import com.android.systemui.deviceentry.domain.interactor.deviceEntryUdfpsInteractor
import com.android.systemui.deviceentry.domain.interactor.deviceUnlockedInteractor
import com.android.systemui.globalactions.domain.interactor.globalActionsInteractor
+import com.android.systemui.haptics.msdl.bouncerHapticPlayer
import com.android.systemui.haptics.msdl.fakeMSDLPlayer
import com.android.systemui.haptics.qs.qsLongPressEffect
import com.android.systemui.jank.interactionJankMonitor
@@ -158,4 +159,5 @@ class KosmosJavaAdapter() {
val sceneContainerOcclusionInteractor by lazy { kosmos.sceneContainerOcclusionInteractor }
val msdlPlayer by lazy { kosmos.fakeMSDLPlayer }
val shadeModeInteractor by lazy { kosmos.shadeModeInteractor }
+ val bouncerHapticHelper by lazy { kosmos.bouncerHapticPlayer }
}
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/scene/domain/startable/SceneContainerStartableKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/scene/domain/startable/SceneContainerStartableKosmos.kt
index 9a5698cfb8ca..4228c3c0b110 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/scene/domain/startable/SceneContainerStartableKosmos.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/scene/domain/startable/SceneContainerStartableKosmos.kt
@@ -32,13 +32,11 @@ import com.android.systemui.haptics.vibratorHelper
import com.android.systemui.keyguard.dismissCallbackRegistry
import com.android.systemui.keyguard.domain.interactor.keyguardEnabledInteractor
import com.android.systemui.keyguard.domain.interactor.keyguardInteractor
-import com.android.systemui.keyguard.domain.interactor.keyguardTransitionInteractor
import com.android.systemui.keyguard.domain.interactor.windowManagerLockscreenVisibilityInteractor
import com.android.systemui.kosmos.Kosmos
import com.android.systemui.kosmos.Kosmos.Fixture
import com.android.systemui.kosmos.testScope
import com.android.systemui.model.sysUiState
-import com.android.systemui.plugins.statusbar.statusBarStateController
import com.android.systemui.power.domain.interactor.powerInteractor
import com.android.systemui.scene.domain.interactor.sceneBackInteractor
import com.android.systemui.scene.domain.interactor.sceneContainerOcclusionInteractor
@@ -62,7 +60,6 @@ val Kosmos.sceneContainerStartable by Fixture {
deviceUnlockedInteractor = deviceUnlockedInteractor,
bouncerInteractor = bouncerInteractor,
keyguardInteractor = keyguardInteractor,
- keyguardTransitionInteractor = keyguardTransitionInteractor,
sysUiState = sysUiState,
displayId = displayTracker.defaultDisplayId,
sceneLogger = sceneLogger,
diff --git a/services/core/java/com/android/server/power/hint/HintManagerService.java b/services/core/java/com/android/server/power/hint/HintManagerService.java
index f6c3d8ef1249..1346a294b7d8 100644
--- a/services/core/java/com/android/server/power/hint/HintManagerService.java
+++ b/services/core/java/com/android/server/power/hint/HintManagerService.java
@@ -160,6 +160,8 @@ public final class HintManagerService extends SystemService {
private static final String PROPERTY_SF_ENABLE_CPU_HINT = "debug.sf.enable_adpf_cpu_hint";
private static final String PROPERTY_HWUI_ENABLE_HINT_MANAGER = "debug.hwui.use_hint_manager";
+ private Boolean mFMQUsesIntegratedEventFlag = false;
+
@VisibleForTesting final IHintManager.Stub mService = new BinderService();
public HintManagerService(Context context) {
@@ -1032,7 +1034,7 @@ public final class HintManagerService extends SystemService {
@Override
public IHintSession createHintSessionWithConfig(@NonNull IBinder token,
@NonNull int[] tids, long durationNanos, @SessionTag int tag,
- @Nullable SessionConfig config) {
+ SessionConfig config) {
if (!isHalSupported()) {
throw new UnsupportedOperationException("PowerHAL is not supported!");
}
@@ -1070,7 +1072,7 @@ public final class HintManagerService extends SystemService {
default -> tag = SessionTag.APP;
}
}
-
+ config.id = -1;
Long halSessionPtr = null;
if (mConfigCreationSupport.get()) {
try {
@@ -1109,7 +1111,7 @@ public final class HintManagerService extends SystemService {
}
}
- final long sessionId = config != null ? config.id : halSessionPtr;
+ final long sessionId = config.id != -1 ? config.id : halSessionPtr;
logPerformanceHintSessionAtom(
callingUid, sessionId, durationNanos, tids, tag);
@@ -1144,14 +1146,23 @@ public final class HintManagerService extends SystemService {
}
@Override
- public ChannelConfig getSessionChannel(IBinder token) {
- if (mPowerHalVersion < 5 || !adpfUseFmqChannel()) {
+ public @Nullable ChannelConfig getSessionChannel(IBinder token) {
+ if (mPowerHalVersion < 5 || !adpfUseFmqChannel()
+ || mFMQUsesIntegratedEventFlag) {
return null;
}
java.util.Objects.requireNonNull(token);
final int callingTgid = Process.getThreadGroupLeader(Binder.getCallingPid());
final int callingUid = Binder.getCallingUid();
ChannelItem item = getOrCreateMappedChannelItem(callingTgid, callingUid, token);
+ // FMQ V1 requires a separate event flag to be passed, and the default no-op
+ // implmenentation in PowerHAL does not return such a shared flag. This helps
+ // avoid using the FMQ on a default impl that does not support it.
+ if (item.getConfig().eventFlagDescriptor == null) {
+ mFMQUsesIntegratedEventFlag = true;
+ closeSessionChannel();
+ return null;
+ }
return item.getConfig();
};
@@ -1270,8 +1281,14 @@ public final class HintManagerService extends SystemService {
@VisibleForTesting
boolean updateHintAllowedByProcState(boolean allowed) {
synchronized (this) {
- if (allowed && !mUpdateAllowedByProcState && !mShouldForcePause) resume();
- if (!allowed && mUpdateAllowedByProcState) pause();
+ if (allowed && !mUpdateAllowedByProcState && !mShouldForcePause) {
+ Slogf.e(TAG, "ADPF IS GETTING RESUMED? UID: " + mUid + " TAG: " + mTag);
+ resume();
+ }
+ if (!allowed && mUpdateAllowedByProcState) {
+ Slogf.e(TAG, "ADPF IS GETTING PAUSED? UID: " + mUid + " TAG: " + mTag);
+ pause();
+ }
mUpdateAllowedByProcState = allowed;
return mUpdateAllowedByProcState;
}
diff --git a/services/core/java/com/android/server/sensorprivacy/SensorPrivacyService.java b/services/core/java/com/android/server/sensorprivacy/SensorPrivacyService.java
index 06a2565da75a..81217014bafe 100644
--- a/services/core/java/com/android/server/sensorprivacy/SensorPrivacyService.java
+++ b/services/core/java/com/android/server/sensorprivacy/SensorPrivacyService.java
@@ -51,6 +51,7 @@ import static android.hardware.SensorPrivacyManager.StateTypes.ENABLED_EXCEPT_AL
import static android.hardware.SensorPrivacyManager.TOGGLE_TYPE_HARDWARE;
import static android.hardware.SensorPrivacyManager.TOGGLE_TYPE_SOFTWARE;
import static android.os.UserHandle.USER_NULL;
+import static android.os.UserHandle.getCallingUserId;
import static android.service.SensorPrivacyIndividualEnabledSensorProto.UNKNOWN;
import static com.android.internal.util.FrameworkStatsLog.PRIVACY_SENSOR_TOGGLE_INTERACTION;
@@ -187,6 +188,7 @@ public final class SensorPrivacyService extends SystemService {
private final TelephonyManager mTelephonyManager;
private final PackageManagerInternal mPackageManagerInternal;
private final NotificationManager mNotificationManager;
+ private final UserManager mUserManager;
private CameraPrivacyLightController mCameraPrivacyLightController;
@@ -214,6 +216,7 @@ public final class SensorPrivacyService extends SystemService {
mTelephonyManager = context.getSystemService(TelephonyManager.class);
mPackageManagerInternal = getLocalService(PackageManagerInternal.class);
mNotificationManager = mContext.getSystemService(NotificationManager.class);
+ mUserManager = context.getSystemService(UserManager.class);
mSensorPrivacyServiceImpl = new SensorPrivacyServiceImpl();
for (String entry : SystemConfig.getInstance().getCameraPrivacyAllowlist()) {
mCameraPrivacyAllowlist.add(entry);
@@ -379,14 +382,23 @@ public final class SensorPrivacyService extends SystemService {
public void onUserRestrictionsChanged(int userId, Bundle newRestrictions,
Bundle prevRestrictions) {
// Reset sensor privacy when restriction is added
+ // Note: isValidCallingUser needs to be called before resetting sensor privacy
+ // because DISALLOW_CAMERA_TOGGLE and DISALLOW_MICROPHONE_TOGGLE are applied on
+ // visible background users in Automotive's Multi Display configuration but we don't
+ // allow sensor privacy to be set on a visible background user.
if (!prevRestrictions.getBoolean(UserManager.DISALLOW_CAMERA_TOGGLE)
&& newRestrictions.getBoolean(UserManager.DISALLOW_CAMERA_TOGGLE)) {
- setToggleSensorPrivacyUnchecked(TOGGLE_TYPE_SOFTWARE, userId, OTHER, CAMERA, false);
+ if (isValidCallingUser(userId)) {
+ setToggleSensorPrivacyUnchecked(TOGGLE_TYPE_SOFTWARE, userId, OTHER, CAMERA,
+ false);
+ }
}
if (!prevRestrictions.getBoolean(UserManager.DISALLOW_MICROPHONE_TOGGLE)
&& newRestrictions.getBoolean(UserManager.DISALLOW_MICROPHONE_TOGGLE)) {
- setToggleSensorPrivacyUnchecked(TOGGLE_TYPE_SOFTWARE, userId, OTHER, MICROPHONE,
- false);
+ if (isValidCallingUser(userId)) {
+ setToggleSensorPrivacyUnchecked(TOGGLE_TYPE_SOFTWARE, userId, OTHER, MICROPHONE,
+ false);
+ }
}
}
@@ -779,6 +791,10 @@ public final class SensorPrivacyService extends SystemService {
@Override
public void setSensorPrivacy(boolean enable) {
enforceManageSensorPrivacyPermission();
+
+ // Enforce valid calling user on devices that enable visible background users.
+ enforceValidCallingUser(getCallingUserId());
+
mSensorPrivacyStateController.setAllSensorState(enable);
}
@@ -795,11 +811,15 @@ public final class SensorPrivacyService extends SystemService {
+ " enable=" + enable
+ ")");
}
+
enforceManageSensorPrivacyPermission();
if (userId == UserHandle.USER_CURRENT) {
userId = mCurrentUser;
}
+ // Enforce valid calling user on devices that enable visible background users.
+ enforceValidCallingUser(userId);
+
if (!canChangeToggleSensorPrivacy(userId, sensor)) {
return;
}
@@ -831,6 +851,9 @@ public final class SensorPrivacyService extends SystemService {
userId = mCurrentUser;
}
+ // Enforce valid calling user on devices that enable visible background users.
+ enforceValidCallingUser(userId);
+
if (!canChangeToggleSensorPrivacy(userId, sensor)) {
return;
}
@@ -1151,6 +1174,42 @@ public final class SensorPrivacyService extends SystemService {
});
}
+ // This method enforces valid calling user on devices that enable visible background users.
+ // Only system user or current user or the user that belongs to the same profile group
+ // as the current user is permitted to toggle sensor privacy.
+ // Visible background users are not permitted to toggle sensor privacy.
+ private void enforceValidCallingUser(@UserIdInt int userId) {
+ if (!isValidCallingUser(userId)) {
+ throw new SecurityException("User " + userId
+ + " is not permitted to toggle sensor privacy");
+ }
+ }
+
+ private boolean isValidCallingUser(@UserIdInt int userId) {
+ // Check whether visible background users are enabled.
+ // Visible background users are non current but can have UI access.
+ // The main use case for visible background users is the passenger in Automotive's
+ // Multi-Display configuration.
+ if (!UserManager.isVisibleBackgroundUsersEnabled()) {
+ return true;
+ }
+
+ if (userId == UserHandle.USER_SYSTEM || userId == mCurrentUser) {
+ return true;
+ }
+
+ final long ident = Binder.clearCallingIdentity();
+ try {
+ if (mUserManager.isSameProfileGroup(userId, mCurrentUser)) {
+ return true;
+ }
+ } finally {
+ Binder.restoreCallingIdentity(ident);
+ }
+
+ return false;
+ }
+
/**
* Enforces the caller contains the necessary permission to change the state of sensor
* privacy.
diff --git a/services/core/jni/com_android_server_hint_HintManagerService.cpp b/services/core/jni/com_android_server_hint_HintManagerService.cpp
index 2307aced6141..febfb9ff1def 100644
--- a/services/core/jni/com_android_server_hint_HintManagerService.cpp
+++ b/services/core/jni/com_android_server_hint_HintManagerService.cpp
@@ -109,7 +109,7 @@ static jlong createHintSessionWithConfig(JNIEnv* env, int32_t tgid, int32_t uid,
return session_ptr;
} else if (result.isUnsupported()) {
throwUnsupported(env, result.errorMessage());
- return -1;
+ return 0;
}
throwFailed(env, result.errorMessage());
return 0;
@@ -190,7 +190,7 @@ static jlong nativeCreateHintSessionWithConfig(JNIEnv* env, jclass /* clazz */,
hal::SessionConfig config;
jlong out = createHintSessionWithConfig(env, tgid, uid, std::move(threadIds), durationNanos,
sessionTag, config);
- if (out <= 0) {
+ if (out == 0) {
return out;
}
static jclass configClass = env->FindClass("android/hardware/power/SessionConfig");
diff --git a/services/tests/PackageManagerServiceTests/host/Android.bp b/services/tests/PackageManagerServiceTests/host/Android.bp
index 75db31679a88..b46a6fffbaa9 100644
--- a/services/tests/PackageManagerServiceTests/host/Android.bp
+++ b/services/tests/PackageManagerServiceTests/host/Android.bp
@@ -95,3 +95,10 @@ test_module_config_host {
test_suites: ["device-tests"],
include_filters: ["com.android.server.pm.test.OverlayActorVisibilityTest"],
}
+
+test_module_config_host {
+ name: "PackageManagerServiceHostTests_android_server_pm_Presubmit",
+ base: "PackageManagerServiceHostTests",
+ test_suites: ["device-tests"],
+ include_annotations: ["android.platform.test.annotations.Presubmit"],
+}
diff --git a/services/tests/PackageManagerServiceTests/server/Android.bp b/services/tests/PackageManagerServiceTests/server/Android.bp
index 24e931c3cbb3..f5b0015aff94 100644
--- a/services/tests/PackageManagerServiceTests/server/Android.bp
+++ b/services/tests/PackageManagerServiceTests/server/Android.bp
@@ -186,3 +186,13 @@ test_module_config {
include_filters: ["com.android.server.pm."],
include_annotations: ["android.platform.test.annotations.Postsubmit"],
}
+
+test_module_config {
+ name: "PackageManagerServiceServerTests_Presubmit",
+ base: "PackageManagerServiceServerTests",
+ test_suites: [
+ "automotive-tests",
+ "device-tests",
+ ],
+ include_annotations: ["android.platform.test.annotations.Presubmit"],
+}
diff --git a/services/tests/VpnTests/Android.bp b/services/tests/VpnTests/Android.bp
index ee20f1a105a4..0568892c3684 100644
--- a/services/tests/VpnTests/Android.bp
+++ b/services/tests/VpnTests/Android.bp
@@ -43,3 +43,10 @@ android_test {
"android.test.mock.stubs",
],
}
+
+test_module_config {
+ name: "FrameworksVpnTests_android_server_connectivity",
+ base: "FrameworksVpnTests",
+ test_suites: ["device-tests"],
+ exclude_annotations: ["com.android.testutils.SkipPresubmit"],
+}
diff --git a/services/tests/mockingservicestests/Android.bp b/services/tests/mockingservicestests/Android.bp
index 6fc80b836521..c81d6be43223 100644
--- a/services/tests/mockingservicestests/Android.bp
+++ b/services/tests/mockingservicestests/Android.bp
@@ -391,3 +391,13 @@ test_module_config {
],
include_filters: ["com.android.server.trust"],
}
+
+test_module_config {
+ name: "FrameworksMockingServicesTests_server_storagemanagerservicetest",
+ base: "FrameworksMockingServicesTests",
+ test_suites: [
+ "automotive-tests",
+ "device-tests",
+ ],
+ include_filters: ["com.android.server.StorageManagerServiceTest"],
+}
diff --git a/services/tests/performancehinttests/src/com/android/server/power/hint/HintManagerServiceTest.java b/services/tests/performancehinttests/src/com/android/server/power/hint/HintManagerServiceTest.java
index b2ca991a4aa8..639ae30c00b9 100644
--- a/services/tests/performancehinttests/src/com/android/server/power/hint/HintManagerServiceTest.java
+++ b/services/tests/performancehinttests/src/com/android/server/power/hint/HintManagerServiceTest.java
@@ -48,7 +48,9 @@ import android.app.ActivityManagerInternal;
import android.content.Context;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
+import android.hardware.common.fmq.MQDescriptor;
import android.hardware.power.ChannelConfig;
+import android.hardware.power.ChannelMessage;
import android.hardware.power.IPower;
import android.hardware.power.SessionConfig;
import android.hardware.power.SessionTag;
@@ -167,6 +169,8 @@ public class HintManagerServiceTest {
mConfig = new ChannelConfig();
mConfig.readFlagBitmask = 1;
mConfig.writeFlagBitmask = 2;
+ mConfig.channelDescriptor = new MQDescriptor<ChannelMessage, Byte>();
+ mConfig.eventFlagDescriptor = new MQDescriptor<Byte, Byte>();
ApplicationInfo applicationInfo = new ApplicationInfo();
applicationInfo.category = ApplicationInfo.CATEGORY_GAME;
when(mContext.getPackageManager()).thenReturn(mMockPackageManager);
diff --git a/services/tests/servicestests/Android.bp b/services/tests/servicestests/Android.bp
index 895cd1e44ca8..e55e0f27dfb4 100644
--- a/services/tests/servicestests/Android.bp
+++ b/services/tests/servicestests/Android.bp
@@ -278,14 +278,22 @@ java_genrule {
test_module_config {
name: "FrameworksServicesTests_contentprotection",
base: "FrameworksServicesTests",
- test_suites: ["device-tests"],
+ test_suites: [
+ "device-tests",
+ "automotive-tests",
+ ],
+
include_filters: ["com.android.server.contentprotection"],
}
test_module_config {
name: "FrameworksServicesTests_om",
base: "FrameworksServicesTests",
- test_suites: ["device-tests"],
+ test_suites: [
+ "device-tests",
+ "automotive-tests",
+ ],
+
include_filters: ["com.android.server.om."],
}
@@ -293,7 +301,11 @@ test_module_config {
test_module_config {
name: "FrameworksServicesTests_contexthub_presubmit",
base: "FrameworksServicesTests",
- test_suites: ["device-tests"],
+ test_suites: [
+ "device-tests",
+ "automotive-tests",
+ ],
+
include_filters: ["com.android.server.location.contexthub."],
// TODO(ron): are these right, does it run anything?
include_annotations: ["android.platform.test.annotations.Presubmit"],
@@ -302,7 +314,11 @@ test_module_config {
test_module_config {
name: "FrameworksServicesTests_contexthub_postsubmit",
base: "FrameworksServicesTests",
- test_suites: ["device-tests"],
+ test_suites: [
+ "device-tests",
+ "automotive-tests",
+ ],
+
include_filters: ["com.android.server.location.contexthub."],
// TODO(ron): are these right, does it run anything?
include_annotations: ["android.platform.test.annotations.Postsubmit"],
@@ -312,14 +328,22 @@ test_module_config {
test_module_config {
name: "FrameworksServicesTests_contentcapture",
base: "FrameworksServicesTests",
- test_suites: ["device-tests"],
+ test_suites: [
+ "device-tests",
+ "automotive-tests",
+ ],
+
include_filters: ["com.android.server.contentcapture"],
}
test_module_config {
name: "FrameworksServicesTests_recoverysystem",
base: "FrameworksServicesTests",
- test_suites: ["device-tests"],
+ test_suites: [
+ "device-tests",
+ "automotive-tests",
+ ],
+
include_filters: ["com.android.server.recoverysystem."],
}
@@ -327,7 +351,11 @@ test_module_config {
test_module_config {
name: "FrameworksServicesTests_pm_presubmit",
base: "FrameworksServicesTests",
- test_suites: ["device-tests"],
+ test_suites: [
+ "device-tests",
+ "automotive-tests",
+ ],
+
include_annotations: ["android.platform.test.annotations.Presubmit"],
include_filters: ["com.android.server.pm."],
}
@@ -335,7 +363,11 @@ test_module_config {
test_module_config {
name: "FrameworksServicesTests_pm_postsubmit",
base: "FrameworksServicesTests",
- test_suites: ["device-tests"],
+ test_suites: [
+ "device-tests",
+ "automotive-tests",
+ ],
+
include_annotations: ["android.platform.test.annotations.Postsubmit"],
include_filters: ["com.android.server.pm."],
}
@@ -344,21 +376,33 @@ test_module_config {
test_module_config {
name: "FrameworksServicesTests_os",
base: "FrameworksServicesTests",
- test_suites: ["device-tests"],
+ test_suites: [
+ "device-tests",
+ "automotive-tests",
+ ],
+
include_filters: ["com.android.server.os."],
}
test_module_config {
name: "FrameworksServicesTests_presubmit",
base: "FrameworksServicesTests",
- test_suites: ["device-tests"],
+ test_suites: [
+ "device-tests",
+ "automotive-tests",
+ ],
+
include_annotations: ["android.platform.test.annotations.Presubmit"],
}
test_module_config {
name: "FrameworksServicesTests_com_android_server_job_Presubmit",
base: "FrameworksServicesTests",
- test_suites: ["device-tests"],
+ test_suites: [
+ "device-tests",
+ "automotive-tests",
+ ],
+
include_filters: ["com.android.server.job"],
exclude_annotations: [
"androidx.test.filters.LargeTest",
@@ -369,49 +413,77 @@ test_module_config {
test_module_config {
name: "FrameworksServicesTests_com_android_server_job",
base: "FrameworksServicesTests",
- test_suites: ["device-tests"],
+ test_suites: [
+ "device-tests",
+ "automotive-tests",
+ ],
+
include_filters: ["com.android.server.job"],
}
test_module_config {
name: "FrameworksServicesTests_com_android_server_tare",
base: "FrameworksServicesTests",
- test_suites: ["device-tests"],
+ test_suites: [
+ "device-tests",
+ "automotive-tests",
+ ],
+
include_filters: ["com.android.server.tare"],
}
test_module_config {
name: "FrameworksServicesTests_com_android_server_usage",
base: "FrameworksServicesTests",
- test_suites: ["device-tests"],
+ test_suites: [
+ "device-tests",
+ "automotive-tests",
+ ],
+
include_filters: ["com.android.server.usage"],
}
test_module_config {
name: "FrameworksServicesTests_battery_stats",
base: "FrameworksServicesTests",
- test_suites: ["device-tests"],
+ test_suites: [
+ "device-tests",
+ "automotive-tests",
+ ],
+
include_filters: ["com.android.server.am.BatteryStatsServiceTest"],
}
test_module_config {
name: "FrameworksServicesTests_accessibility",
base: "FrameworksServicesTests",
- test_suites: ["device-tests"],
+ test_suites: [
+ "device-tests",
+ "automotive-tests",
+ ],
+
include_filters: ["com.android.server.accessibility"],
}
test_module_config {
name: "FrameworksServicesTests_binary_transparency",
base: "FrameworksServicesTests",
- test_suites: ["device-tests"],
+ test_suites: [
+ "device-tests",
+ "automotive-tests",
+ ],
+
include_filters: ["com.android.server.BinaryTransparencyServiceTest"],
}
test_module_config {
name: "FrameworksServicesTests_pinner_service",
base: "FrameworksServicesTests",
- test_suites: ["device-tests"],
+ test_suites: [
+ "device-tests",
+ "automotive-tests",
+ ],
+
include_filters: ["com.android.server.PinnerServiceTest"],
exclude_annotations: ["org.junit.Ignore"],
}
@@ -419,7 +491,11 @@ test_module_config {
test_module_config {
name: "FrameworksServicesTests_android_server_am_Presubmit",
base: "FrameworksServicesTests",
- test_suites: ["device-tests"],
+ test_suites: [
+ "device-tests",
+ "automotive-tests",
+ ],
+
include_filters: ["com.android.server.am."],
include_annotations: ["android.platform.test.annotations.Presubmit"],
}
@@ -427,21 +503,33 @@ test_module_config {
test_module_config {
name: "FrameworksServicesTests_android_server_am",
base: "FrameworksServicesTests",
- test_suites: ["device-tests"],
+ test_suites: [
+ "device-tests",
+ "automotive-tests",
+ ],
+
include_filters: ["com.android.server.am."],
}
test_module_config {
name: "FrameworksServicesTests_android_server_appop",
base: "FrameworksServicesTests",
- test_suites: ["device-tests"],
+ test_suites: [
+ "device-tests",
+ "automotive-tests",
+ ],
+
include_filters: ["com.android.server.appop"],
}
test_module_config {
name: "FrameworksServicesTests_android_server_audio",
base: "FrameworksServicesTests",
- test_suites: ["device-tests"],
+ test_suites: [
+ "device-tests",
+ "automotive-tests",
+ ],
+
include_filters: ["com.android.server.audio"],
include_annotations: ["android.platform.test.annotations.Presubmit"],
}
@@ -449,14 +537,22 @@ test_module_config {
test_module_config {
name: "FrameworksServicesTests_android_server_compat",
base: "FrameworksServicesTests",
- test_suites: ["device-tests"],
+ test_suites: [
+ "device-tests",
+ "automotive-tests",
+ ],
+
include_filters: ["com.android.server.compat"],
}
test_module_config {
name: "FrameworksServicesTests_android_server_hdmi_Presubmit",
base: "FrameworksServicesTests",
- test_suites: ["device-tests"],
+ test_suites: [
+ "device-tests",
+ "automotive-tests",
+ ],
+
include_filters: ["com.android.server.hdmi"],
include_annotations: ["android.platform.test.annotations.Presubmit"],
}
@@ -464,35 +560,55 @@ test_module_config {
test_module_config {
name: "FrameworksServicesTests_android_server_hdmi",
base: "FrameworksServicesTests",
- test_suites: ["device-tests"],
+ test_suites: [
+ "device-tests",
+ "automotive-tests",
+ ],
+
include_filters: ["com.android.server.hdmi"],
}
test_module_config {
name: "FrameworksServicesTests_android_server_integrity",
base: "FrameworksServicesTests",
- test_suites: ["device-tests"],
+ test_suites: [
+ "device-tests",
+ "automotive-tests",
+ ],
+
include_filters: ["com.android.server.integrity."],
}
test_module_config {
name: "FrameworksServicesTests_android_server_lights",
base: "FrameworksServicesTests",
- test_suites: ["device-tests"],
+ test_suites: [
+ "device-tests",
+ "automotive-tests",
+ ],
+
include_filters: ["com.android.server.lights"],
}
test_module_config {
name: "FrameworksServicesTests_android_server_locales",
base: "FrameworksServicesTests",
- test_suites: ["device-tests"],
+ test_suites: [
+ "device-tests",
+ "automotive-tests",
+ ],
+
include_filters: ["com.android.server.locales."],
}
test_module_config {
name: "FrameworksServicesTests_android_server_location_contexthub_Presubmit",
base: "FrameworksServicesTests",
- test_suites: ["device-tests"],
+ test_suites: [
+ "device-tests",
+ "automotive-tests",
+ ],
+
include_filters: ["com.android.server.location.contexthub."],
include_annotations: ["android.platform.test.annotations.Presubmit"],
}
@@ -500,21 +616,33 @@ test_module_config {
test_module_config {
name: "FrameworksServicesTests_android_server_locksettings",
base: "FrameworksServicesTests",
- test_suites: ["device-tests"],
+ test_suites: [
+ "device-tests",
+ "automotive-tests",
+ ],
+
include_filters: ["com.android.server.locksettings."],
}
test_module_config {
name: "FrameworksServicesTests_android_server_logcat",
base: "FrameworksServicesTests",
- test_suites: ["device-tests"],
+ test_suites: [
+ "device-tests",
+ "automotive-tests",
+ ],
+
include_filters: ["com.android.server.logcat"],
}
test_module_config {
name: "FrameworksServicesTests_android_server_net_Presubmit",
base: "FrameworksServicesTests",
- test_suites: ["device-tests"],
+ test_suites: [
+ "device-tests",
+ "automotive-tests",
+ ],
+
include_filters: ["com.android.server.net."],
include_annotations: ["android.platform.test.annotations.Presubmit"],
}
@@ -522,28 +650,44 @@ test_module_config {
test_module_config {
name: "FrameworksServicesTests_android_server_om",
base: "FrameworksServicesTests",
- test_suites: ["device-tests"],
+ test_suites: [
+ "device-tests",
+ "automotive-tests",
+ ],
+
include_filters: ["com.android.server.om."],
}
test_module_config {
name: "FrameworksServicesTests_android_server_pdb",
base: "FrameworksServicesTests",
- test_suites: ["device-tests"],
+ test_suites: [
+ "device-tests",
+ "automotive-tests",
+ ],
+
include_filters: ["com.android.server.pdb.PersistentDataBlockServiceTest"],
}
test_module_config {
name: "FrameworksServicesTests_android_server_pm_dex",
base: "FrameworksServicesTests",
- test_suites: ["device-tests"],
+ test_suites: [
+ "device-tests",
+ "automotive-tests",
+ ],
+
include_filters: ["com.android.server.pm.dex"],
}
test_module_config {
name: "FrameworksServicesTests_android_server_policy_Presubmit",
base: "FrameworksServicesTests",
- test_suites: ["device-tests"],
+ test_suites: [
+ "device-tests",
+ "automotive-tests",
+ ],
+
include_filters: ["com.android.server.policy."],
include_annotations: ["android.platform.test.annotations.Presubmit"],
}
@@ -551,49 +695,77 @@ test_module_config {
test_module_config {
name: "FrameworksServicesTests_android_server_policy",
base: "FrameworksServicesTests",
- test_suites: ["device-tests"],
+ test_suites: [
+ "device-tests",
+ "automotive-tests",
+ ],
+
include_filters: ["com.android.server.policy."],
}
test_module_config {
name: "FrameworksServicesTests_android_server_power",
base: "FrameworksServicesTests",
- test_suites: ["device-tests"],
+ test_suites: [
+ "device-tests",
+ "automotive-tests",
+ ],
+
include_filters: ["com.android.server.power"],
}
test_module_config {
name: "FrameworksServicesTests_android_server_power_hint",
base: "FrameworksServicesTests",
- test_suites: ["device-tests"],
+ test_suites: [
+ "device-tests",
+ "automotive-tests",
+ ],
+
include_filters: ["com.android.server.power.hint"],
}
test_module_config {
name: "FrameworksServicesTests_android_server_powerstats",
base: "FrameworksServicesTests",
- test_suites: ["device-tests"],
+ test_suites: [
+ "device-tests",
+ "automotive-tests",
+ ],
+
include_filters: ["com.android.server.powerstats"],
}
test_module_config {
name: "FrameworksServicesTests_android_server_rollback",
base: "FrameworksServicesTests",
- test_suites: ["device-tests"],
+ test_suites: [
+ "device-tests",
+ "automotive-tests",
+ ],
+
include_filters: ["com.android.server.rollback"],
}
test_module_config {
name: "FrameworksServicesTests_android_server_uri",
base: "FrameworksServicesTests",
- test_suites: ["device-tests"],
+ test_suites: [
+ "device-tests",
+ "automotive-tests",
+ ],
+
include_filters: ["com.android.server.uri."],
}
test_module_config {
name: "FrameworksServicesTests_com_android_server_location_contexthub",
base: "FrameworksServicesTests",
- test_suites: ["device-tests"],
+ test_suites: [
+ "device-tests",
+ "automotive-tests",
+ ],
+
include_filters: ["com.android.server.location.contexthub."],
include_annotations: ["android.platform.test.annotations.Postsubmit"],
}
@@ -601,7 +773,11 @@ test_module_config {
test_module_config {
name: "FrameworksServicesTests_android_server_usage",
base: "FrameworksServicesTests",
- test_suites: ["device-tests"],
+ test_suites: [
+ "device-tests",
+ "automotive-tests",
+ ],
+
include_filters: ["com.android.server.usage"],
exclude_filters: ["com.android.server.usage.StorageStatsServiceTest"],
}
@@ -609,14 +785,22 @@ test_module_config {
test_module_config {
name: "FrameworksServicesTests_android_server_soundtrigger_middleware",
base: "FrameworksServicesTests",
- test_suites: ["device-tests"],
+ test_suites: [
+ "device-tests",
+ "automotive-tests",
+ ],
+
include_filters: ["com.android.server.soundtrigger_middleware"],
}
test_module_config {
name: "FrameworksServicesTests_android_server_input",
base: "FrameworksServicesTests",
- test_suites: ["device-tests"],
+ test_suites: [
+ "device-tests",
+ "automotive-tests",
+ ],
+
include_filters: ["com.android.server.input"],
}
@@ -792,3 +976,23 @@ test_module_config {
],
include_filters: ["com.android.server.input"],
}
+
+test_module_config {
+ name: "FrameworksServicesTests_people_data",
+ base: "FrameworksServicesTests",
+ test_suites: [
+ "automotive-tests",
+ "device-tests",
+ ],
+ include_filters: ["com.android.server.people.data"],
+}
+
+test_module_config {
+ name: "FrameworksServicesTests_Presubmit",
+ base: "FrameworksServicesTests",
+ test_suites: [
+ "automotive-tests",
+ "device-tests",
+ ],
+ include_annotations: ["android.platform.test.annotations.Presubmit"],
+}
diff --git a/services/tests/uiservicestests/Android.bp b/services/tests/uiservicestests/Android.bp
index 850d2f7f36a5..a63a38da3740 100644
--- a/services/tests/uiservicestests/Android.bp
+++ b/services/tests/uiservicestests/Android.bp
@@ -92,3 +92,13 @@ android_test {
// Required for TestParameterInjector
javacflags: ["-parameters"],
}
+
+test_module_config {
+ name: "FrameworksUiServicesTests_notification",
+ base: "FrameworksUiServicesTests",
+ test_suites: [
+ "automotive-tests",
+ "device-tests",
+ ],
+ exclude_annotations: ["androidx.test.filters.LargeTest"],
+}
diff --git a/tests/permission/Android.bp b/tests/permission/Android.bp
index d80eaeb32c1e..1a08f998442d 100644
--- a/tests/permission/Android.bp
+++ b/tests/permission/Android.bp
@@ -25,3 +25,10 @@ android_test {
platform_apis: true,
test_suites: ["device-tests"],
}
+
+test_module_config {
+ name: "FrameworkPermissionTests_Presubmit",
+ base: "FrameworkPermissionTests",
+ test_suites: ["device-tests"],
+ include_annotations: ["android.platform.test.annotations.Presubmit"],
+}