Merge "Fix broken @link references in CompatModePackages" into main
diff --git a/AconfigFlags.bp b/AconfigFlags.bp
index c30164c..003b7f8 100644
--- a/AconfigFlags.bp
+++ b/AconfigFlags.bp
@@ -42,6 +42,7 @@
":android.credentials.flags-aconfig-java{.generated_srcjars}",
":android.view.contentprotection.flags-aconfig-java{.generated_srcjars}",
":android.service.voice.flags-aconfig-java{.generated_srcjars}",
+ ":android.service.autofill.flags-aconfig-java{.generated_srcjars}",
]
filegroup {
@@ -416,3 +417,19 @@
aconfig_declarations: "android.service.voice.flags-aconfig",
defaults: ["framework-minus-apex-aconfig-java-defaults"],
}
+
+// Autofill
+aconfig_declarations {
+ name: "android.service.autofill.flags-aconfig",
+ package: "android.service.autofill",
+ srcs: [
+ "services/autofill/bugfixes.aconfig",
+ "services/autofill/features.aconfig"
+ ],
+}
+
+java_aconfig_library {
+ name: "android.service.autofill.flags-aconfig-java",
+ aconfig_declarations: "android.service.autofill.flags-aconfig",
+ defaults: ["framework-minus-apex-aconfig-java-defaults"],
+}
diff --git a/apex/jobscheduler/service/Android.bp b/apex/jobscheduler/service/Android.bp
index a4a0b4b..887f7fe 100644
--- a/apex/jobscheduler/service/Android.bp
+++ b/apex/jobscheduler/service/Android.bp
@@ -13,6 +13,10 @@
name: "service-jobscheduler",
installable: true,
+ defaults: [
+ "service-jobscheduler-aconfig-libraries",
+ ],
+
srcs: [
"java/**/*.java",
":framework-jobscheduler-shared-srcs",
diff --git a/apex/jobscheduler/service/aconfig/Android.bp b/apex/jobscheduler/service/aconfig/Android.bp
new file mode 100644
index 0000000..24ecd3d
--- /dev/null
+++ b/apex/jobscheduler/service/aconfig/Android.bp
@@ -0,0 +1,29 @@
+// JobScheduler
+aconfig_declarations {
+ name: "service-job.flags-aconfig",
+ package: "com.android.server.job",
+ srcs: [
+ "job.aconfig",
+ ],
+}
+
+java_aconfig_library {
+ name: "service-jobscheduler-job.flags-aconfig-java",
+ aconfig_declarations: "service-job.flags-aconfig",
+ defaults: ["framework-minus-apex-aconfig-java-defaults"],
+ visibility: ["//frameworks/base:__subpackages__"],
+}
+
+service_jobscheduler_aconfig_srcjars = [
+ ":service-jobscheduler-job.flags-aconfig-java{.generated_srcjars}",
+]
+
+// Aconfig declarations and libraries for the core framework
+java_defaults {
+ name: "service-jobscheduler-aconfig-libraries",
+ // Add java_aconfig_libraries to here to add them to the core framework
+ srcs: service_jobscheduler_aconfig_srcjars,
+ // Add aconfig-annotations-lib as a dependency for the optimization
+ libs: ["aconfig-annotations-lib"],
+ visibility: ["//frameworks/base:__subpackages__"],
+}
diff --git a/apex/jobscheduler/service/aconfig/job.aconfig b/apex/jobscheduler/service/aconfig/job.aconfig
new file mode 100644
index 0000000..4e3cb7d
--- /dev/null
+++ b/apex/jobscheduler/service/aconfig/job.aconfig
@@ -0,0 +1,8 @@
+package: "com.android.server.job"
+
+flag {
+ name: "relax_prefetch_connectivity_constraint_only_on_charger"
+ namespace: "backstagepower"
+ description: "Only relax a prefetch job's connectivity constraint when the device is charging"
+ bug: "299329948"
+}
\ No newline at end of file
diff --git a/apex/jobscheduler/service/java/com/android/server/DeviceIdleController.java b/apex/jobscheduler/service/java/com/android/server/DeviceIdleController.java
index f252a0b..158d914 100644
--- a/apex/jobscheduler/service/java/com/android/server/DeviceIdleController.java
+++ b/apex/jobscheduler/service/java/com/android/server/DeviceIdleController.java
@@ -1030,6 +1030,12 @@
"light_idle_to_initial_flex";
private static final String KEY_LIGHT_IDLE_TIMEOUT_MAX_FLEX = "light_max_idle_to_flex";
private static final String KEY_LIGHT_IDLE_FACTOR = "light_idle_factor";
+ private static final String KEY_LIGHT_IDLE_INCREASE_LINEARLY =
+ "light_idle_increase_linearly";
+ private static final String KEY_LIGHT_IDLE_LINEAR_INCREASE_FACTOR_MS =
+ "light_idle_linear_increase_factor_ms";
+ private static final String KEY_LIGHT_IDLE_FLEX_LINEAR_INCREASE_FACTOR_MS =
+ "light_idle_flex_linear_increase_factor_ms";
private static final String KEY_LIGHT_MAX_IDLE_TIMEOUT = "light_max_idle_to";
private static final String KEY_LIGHT_IDLE_MAINTENANCE_MIN_BUDGET =
"light_idle_maintenance_min_budget";
@@ -1079,6 +1085,10 @@
private long mDefaultLightIdleTimeoutMaxFlex =
!COMPRESS_TIME ? 15 * 60 * 1000L : 60 * 1000L;
private float mDefaultLightIdleFactor = 2f;
+ private boolean mDefaultLightIdleIncreaseLinearly;
+ private long mDefaultLightIdleLinearIncreaseFactorMs = mDefaultLightIdleTimeout;
+ private long mDefaultLightIdleFlexLinearIncreaseFactorMs =
+ mDefaultLightIdleTimeoutInitialFlex;
private long mDefaultLightMaxIdleTimeout =
!COMPRESS_TIME ? 15 * 60 * 1000L : 60 * 1000L;
private long mDefaultLightIdleMaintenanceMinBudget =
@@ -1174,6 +1184,37 @@
public float LIGHT_IDLE_FACTOR = mDefaultLightIdleFactor;
/**
+ * Whether to increase the light idle mode time linearly or exponentially.
+ * If true, will increase linearly
+ * (i.e. {@link #LIGHT_IDLE_TIMEOUT} + x * {@link #LIGHT_IDLE_LINEAR_INCREASE_FACTOR_MS}).
+ * If false, will increase by exponentially
+ * (i.e. {@link #LIGHT_IDLE_TIMEOUT} * ({@link #LIGHT_IDLE_FACTOR} ^ x)).
+ * This will also impact how the light idle flex value
+ * ({@link #LIGHT_IDLE_TIMEOUT_INITIAL_FLEX}) is increased (using
+ * {@link #LIGHT_IDLE_FLEX_LINEAR_INCREASE_FACTOR_MS} for the linear increase)..
+ *
+ * @see #KEY_LIGHT_IDLE_INCREASE_LINEARLY
+ */
+ public boolean LIGHT_IDLE_INCREASE_LINEARLY = mDefaultLightIdleIncreaseLinearly;
+
+ /**
+ * Amount of time to increase the light idle time by, if increasing it linearly.
+ *
+ * @see #KEY_LIGHT_IDLE_LINEAR_INCREASE_FACTOR_MS
+ * @see #LIGHT_IDLE_INCREASE_LINEARLY
+ */
+ public long LIGHT_IDLE_LINEAR_INCREASE_FACTOR_MS = mDefaultLightIdleLinearIncreaseFactorMs;
+
+ /**
+ * Amount of time to increase the light idle flex time by, if increasing it linearly.
+ *
+ * @see #KEY_LIGHT_IDLE_LINEAR_INCREASE_FACTOR_MS
+ * @see #LIGHT_IDLE_INCREASE_LINEARLY
+ */
+ public long LIGHT_IDLE_FLEX_LINEAR_INCREASE_FACTOR_MS =
+ mDefaultLightIdleFlexLinearIncreaseFactorMs;
+
+ /**
* This is the maximum time we will stay in light idle mode.
*
* @see #KEY_LIGHT_MAX_IDLE_TIMEOUT
@@ -1409,6 +1450,16 @@
mDefaultLightIdleTimeoutMaxFlex);
mDefaultLightIdleFactor = res.getFloat(
com.android.internal.R.integer.device_idle_light_idle_factor);
+ mDefaultLightIdleIncreaseLinearly = res.getBoolean(
+ com.android.internal.R.bool.device_idle_light_idle_increase_linearly);
+ mDefaultLightIdleLinearIncreaseFactorMs = getTimeout(res.getInteger(
+ com.android.internal.R.integer
+ .device_idle_light_idle_linear_increase_factor_ms),
+ mDefaultLightIdleLinearIncreaseFactorMs);
+ mDefaultLightIdleFlexLinearIncreaseFactorMs = getTimeout(res.getInteger(
+ com.android.internal.R.integer
+ .device_idle_light_idle_flex_linear_increase_factor_ms),
+ mDefaultLightIdleFlexLinearIncreaseFactorMs);
mDefaultLightMaxIdleTimeout = getTimeout(
res.getInteger(com.android.internal.R.integer.device_idle_light_max_idle_to_ms),
mDefaultLightMaxIdleTimeout);
@@ -1487,6 +1538,9 @@
LIGHT_IDLE_TIMEOUT_INITIAL_FLEX = mDefaultLightIdleTimeoutInitialFlex;
LIGHT_IDLE_TIMEOUT_MAX_FLEX = mDefaultLightIdleTimeoutMaxFlex;
LIGHT_IDLE_FACTOR = mDefaultLightIdleFactor;
+ LIGHT_IDLE_INCREASE_LINEARLY = mDefaultLightIdleIncreaseLinearly;
+ LIGHT_IDLE_LINEAR_INCREASE_FACTOR_MS = mDefaultLightIdleLinearIncreaseFactorMs;
+ LIGHT_IDLE_FLEX_LINEAR_INCREASE_FACTOR_MS = mDefaultLightIdleFlexLinearIncreaseFactorMs;
LIGHT_MAX_IDLE_TIMEOUT = mDefaultLightMaxIdleTimeout;
LIGHT_IDLE_MAINTENANCE_MIN_BUDGET = mDefaultLightIdleMaintenanceMinBudget;
LIGHT_IDLE_MAINTENANCE_MAX_BUDGET = mDefaultLightIdleMaintenanceMaxBudget;
@@ -1556,6 +1610,21 @@
LIGHT_IDLE_FACTOR = Math.max(1, properties.getFloat(
KEY_LIGHT_IDLE_FACTOR, mDefaultLightIdleFactor));
break;
+ case KEY_LIGHT_IDLE_INCREASE_LINEARLY:
+ LIGHT_IDLE_INCREASE_LINEARLY = properties.getBoolean(
+ KEY_LIGHT_IDLE_INCREASE_LINEARLY,
+ mDefaultLightIdleIncreaseLinearly);
+ break;
+ case KEY_LIGHT_IDLE_LINEAR_INCREASE_FACTOR_MS:
+ LIGHT_IDLE_LINEAR_INCREASE_FACTOR_MS = properties.getLong(
+ KEY_LIGHT_IDLE_LINEAR_INCREASE_FACTOR_MS,
+ mDefaultLightIdleLinearIncreaseFactorMs);
+ break;
+ case KEY_LIGHT_IDLE_FLEX_LINEAR_INCREASE_FACTOR_MS:
+ LIGHT_IDLE_FLEX_LINEAR_INCREASE_FACTOR_MS = properties.getLong(
+ KEY_LIGHT_IDLE_FLEX_LINEAR_INCREASE_FACTOR_MS,
+ mDefaultLightIdleFlexLinearIncreaseFactorMs);
+ break;
case KEY_LIGHT_MAX_IDLE_TIMEOUT:
LIGHT_MAX_IDLE_TIMEOUT = properties.getLong(
KEY_LIGHT_MAX_IDLE_TIMEOUT, mDefaultLightMaxIdleTimeout);
@@ -1716,6 +1785,20 @@
pw.print(LIGHT_IDLE_FACTOR);
pw.println();
+ pw.print(" "); pw.print(KEY_LIGHT_IDLE_INCREASE_LINEARLY); pw.print("=");
+ pw.print(LIGHT_IDLE_INCREASE_LINEARLY);
+ pw.println();
+
+ pw.print(" "); pw.print(KEY_LIGHT_IDLE_LINEAR_INCREASE_FACTOR_MS);
+ pw.print("=");
+ pw.print(LIGHT_IDLE_LINEAR_INCREASE_FACTOR_MS);
+ pw.println();
+
+ pw.print(" "); pw.print(KEY_LIGHT_IDLE_FLEX_LINEAR_INCREASE_FACTOR_MS);
+ pw.print("=");
+ pw.print(LIGHT_IDLE_FLEX_LINEAR_INCREASE_FACTOR_MS);
+ pw.println();
+
pw.print(" "); pw.print(KEY_LIGHT_MAX_IDLE_TIMEOUT); pw.print("=");
TimeUtils.formatDuration(LIGHT_MAX_IDLE_TIMEOUT, pw);
pw.println();
@@ -3694,10 +3777,18 @@
}
mMaintenanceStartTime = 0;
scheduleLightAlarmLocked(mNextLightIdleDelay, mNextLightIdleDelayFlex, true);
- mNextLightIdleDelay = Math.min(mConstants.LIGHT_MAX_IDLE_TIMEOUT,
- (long) (mNextLightIdleDelay * mConstants.LIGHT_IDLE_FACTOR));
- mNextLightIdleDelayFlex = Math.min(mConstants.LIGHT_IDLE_TIMEOUT_MAX_FLEX,
- (long) (mNextLightIdleDelayFlex * mConstants.LIGHT_IDLE_FACTOR));
+ if (!mConstants.LIGHT_IDLE_INCREASE_LINEARLY) {
+ mNextLightIdleDelay = Math.min(mConstants.LIGHT_MAX_IDLE_TIMEOUT,
+ (long) (mNextLightIdleDelay * mConstants.LIGHT_IDLE_FACTOR));
+ mNextLightIdleDelayFlex = Math.min(mConstants.LIGHT_IDLE_TIMEOUT_MAX_FLEX,
+ (long) (mNextLightIdleDelayFlex * mConstants.LIGHT_IDLE_FACTOR));
+ } else {
+ mNextLightIdleDelay = Math.min(mConstants.LIGHT_MAX_IDLE_TIMEOUT,
+ mNextLightIdleDelay + mConstants.LIGHT_IDLE_LINEAR_INCREASE_FACTOR_MS);
+ mNextLightIdleDelayFlex = Math.min(mConstants.LIGHT_IDLE_TIMEOUT_MAX_FLEX,
+ mNextLightIdleDelayFlex
+ + mConstants.LIGHT_IDLE_FLEX_LINEAR_INCREASE_FACTOR_MS);
+ }
moveToLightStateLocked(LIGHT_STATE_IDLE, reason);
addEvent(EVENT_LIGHT_IDLE, null);
mGoingIdleWakeLock.acquire();
diff --git a/apex/jobscheduler/service/java/com/android/server/job/controllers/ConnectivityController.java b/apex/jobscheduler/service/java/com/android/server/job/controllers/ConnectivityController.java
index 6d938de..45f15db 100644
--- a/apex/jobscheduler/service/java/com/android/server/job/controllers/ConnectivityController.java
+++ b/apex/jobscheduler/service/java/com/android/server/job/controllers/ConnectivityController.java
@@ -22,6 +22,8 @@
import static com.android.server.job.JobSchedulerService.RESTRICTED_INDEX;
import static com.android.server.job.JobSchedulerService.sElapsedRealtimeClock;
+import static com.android.server.job.Flags.FLAG_RELAX_PREFETCH_CONNECTIVITY_CONSTRAINT_ONLY_ON_CHARGER;
+import static com.android.server.job.Flags.relaxPrefetchConnectivityConstraintOnlyOnCharger;
import android.annotation.NonNull;
import android.annotation.Nullable;
@@ -929,6 +931,11 @@
// Need to at least know the estimated download bytes for a prefetch job.
return false;
}
+ if (relaxPrefetchConnectivityConstraintOnlyOnCharger()) {
+ if (!mService.isBatteryCharging()) {
+ return false;
+ }
+ }
// See if we match after relaxing any unmetered request
final NetworkCapabilities.Builder builder =
@@ -1735,6 +1742,14 @@
Predicate<JobStatus> predicate) {
final long nowElapsed = sElapsedRealtimeClock.millis();
+ pw.println("Aconfig flags:");
+ pw.increaseIndent();
+ pw.print(FLAG_RELAX_PREFETCH_CONNECTIVITY_CONSTRAINT_ONLY_ON_CHARGER,
+ relaxPrefetchConnectivityConstraintOnlyOnCharger());
+ pw.println();
+ pw.decreaseIndent();
+ pw.println();
+
if (mRequestedWhitelistJobs.size() > 0) {
pw.print("Requested standby exceptions:");
for (int i = 0; i < mRequestedWhitelistJobs.size(); i++) {
diff --git a/api/Android.bp b/api/Android.bp
index 45e70719..222275f 100644
--- a/api/Android.bp
+++ b/api/Android.bp
@@ -82,7 +82,6 @@
"framework-media",
"framework-mediaprovider",
"framework-ondevicepersonalization",
- "framework-pdf",
"framework-permission",
"framework-permission-s",
"framework-scheduling",
diff --git a/core/api/current.txt b/core/api/current.txt
index 96a9595..d037c31 100644
--- a/core/api/current.txt
+++ b/core/api/current.txt
@@ -18539,8 +18539,10 @@
ctor public BiometricPrompt.CryptoObject(@NonNull javax.crypto.Mac);
ctor @Deprecated public BiometricPrompt.CryptoObject(@NonNull android.security.identity.IdentityCredential);
ctor public BiometricPrompt.CryptoObject(@NonNull android.security.identity.PresentationSession);
+ ctor @FlaggedApi("android.hardware.biometrics.add_key_agreement_crypto_object") public BiometricPrompt.CryptoObject(@NonNull javax.crypto.KeyAgreement);
method public javax.crypto.Cipher getCipher();
method @Deprecated @Nullable public android.security.identity.IdentityCredential getIdentityCredential();
+ method @FlaggedApi("android.hardware.biometrics.add_key_agreement_crypto_object") @Nullable public javax.crypto.KeyAgreement getKeyAgreement();
method public javax.crypto.Mac getMac();
method @Nullable public android.security.identity.PresentationSession getPresentationSession();
method public java.security.Signature getSignature();
diff --git a/core/api/system-current.txt b/core/api/system-current.txt
index 358c8e7..a99eeb0 100644
--- a/core/api/system-current.txt
+++ b/core/api/system-current.txt
@@ -3946,7 +3946,7 @@
field public static final int DELETE_FAILED_OWNER_BLOCKED = -4; // 0xfffffffc
field public static final int DELETE_KEEP_DATA = 1; // 0x1
field public static final int DELETE_SUCCEEDED = 1; // 0x1
- field public static final String EXTRA_REQUEST_PERMISSIONS_DEVICE_ID = "android.content.pm.extra.REQUEST_PERMISSIONS_DEVICE_ID";
+ field @FlaggedApi("android.permission.flags.device_aware_permission_apis") public static final String EXTRA_REQUEST_PERMISSIONS_DEVICE_ID = "android.content.pm.extra.REQUEST_PERMISSIONS_DEVICE_ID";
field public static final String EXTRA_REQUEST_PERMISSIONS_LEGACY_ACCESS_PERMISSION_NAMES = "android.content.pm.extra.REQUEST_PERMISSIONS_LEGACY_ACCESS_PERMISSION_NAMES";
field public static final String EXTRA_REQUEST_PERMISSIONS_NAMES = "android.content.pm.extra.REQUEST_PERMISSIONS_NAMES";
field public static final String EXTRA_REQUEST_PERMISSIONS_RESULTS = "android.content.pm.extra.REQUEST_PERMISSIONS_RESULTS";
diff --git a/core/java/android/app/ApplicationExitInfo.java b/core/java/android/app/ApplicationExitInfo.java
index 7b3d017..d15c79f 100644
--- a/core/java/android/app/ApplicationExitInfo.java
+++ b/core/java/android/app/ApplicationExitInfo.java
@@ -468,6 +468,15 @@
*/
public static final int SUBREASON_EXCESSIVE_BINDER_OBJECTS = 29;
+ /**
+ * The process was killed by the [kernel] Out-of-memory (OOM) killer; this
+ * would be set only when the reason is {@link #REASON_LOW_MEMORY}.
+ *
+ * For internal use only.
+ * @hide
+ */
+ public static final int SUBREASON_OOM_KILL = 30;
+
// If there is any OEM code which involves additional app kill reasons, it should
// be categorized in {@link #REASON_OTHER}, with subreason code starting from 1000.
@@ -644,6 +653,7 @@
SUBREASON_PACKAGE_UPDATE,
SUBREASON_UNDELIVERED_BROADCAST,
SUBREASON_EXCESSIVE_BINDER_OBJECTS,
+ SUBREASON_OOM_KILL,
})
@Retention(RetentionPolicy.SOURCE)
public @interface SubReason {}
@@ -1371,6 +1381,8 @@
return "UNDELIVERED BROADCAST";
case SUBREASON_EXCESSIVE_BINDER_OBJECTS:
return "EXCESSIVE BINDER OBJECTS";
+ case SUBREASON_OOM_KILL:
+ return "OOM KILL";
default:
return "UNKNOWN";
}
diff --git a/core/java/android/companion/CompanionDeviceManager.java b/core/java/android/companion/CompanionDeviceManager.java
index 2fb428b..a84845a 100644
--- a/core/java/android/companion/CompanionDeviceManager.java
+++ b/core/java/android/companion/CompanionDeviceManager.java
@@ -240,6 +240,12 @@
public static final int MESSAGE_REQUEST_PERMISSION_RESTORE = 0x63826983; // ?RES
/**
+ * The length limit of Association tag.
+ * @hide
+ */
+ private static final int ASSOCIATION_TAG_LENGTH_LIMIT = 100;
+
+ /**
* Callback for applications to receive updates about and the outcome of
* {@link AssociationRequest} issued via {@code associate()} call.
*
@@ -1409,7 +1415,7 @@
/**
* Sets the {@link AssociationInfo#getTag() tag} for this association.
*
- * <p>The length of the tag must be at most 20 characters.
+ * <p>The length of the tag must be at most 100 characters to save disk space.
*
* <p>This allows to store useful information about the associated devices.
*
@@ -1421,8 +1427,8 @@
public void setAssociationTag(int associationId, @NonNull String tag) {
Objects.requireNonNull(tag, "tag cannot be null");
- if (tag.length() > 20) {
- throw new IllegalArgumentException("Length of the tag must be at most 20 characters");
+ if (tag.length() > ASSOCIATION_TAG_LENGTH_LIMIT) {
+ throw new IllegalArgumentException("Length of the tag must be at most 100 characters");
}
try {
diff --git a/core/java/android/companion/virtualnative/OWNERS b/core/java/android/companion/virtualnative/OWNERS
new file mode 100644
index 0000000..2968104
--- /dev/null
+++ b/core/java/android/companion/virtualnative/OWNERS
@@ -0,0 +1 @@
+include /services/companion/java/com/android/server/companion/virtual/OWNERS
diff --git a/core/java/android/content/pm/PackageManager.java b/core/java/android/content/pm/PackageManager.java
index 3fc515d..8fbe50c3 100644
--- a/core/java/android/content/pm/PackageManager.java
+++ b/core/java/android/content/pm/PackageManager.java
@@ -4802,6 +4802,7 @@
* @hide
*/
@SystemApi
+ @FlaggedApi(android.permission.flags.Flags.FLAG_DEVICE_AWARE_PERMISSION_APIS)
public static final String EXTRA_REQUEST_PERMISSIONS_DEVICE_ID =
"android.content.pm.extra.REQUEST_PERMISSIONS_DEVICE_ID";
diff --git a/core/java/android/credentials/GetCandidateCredentialsResponse.java b/core/java/android/credentials/GetCandidateCredentialsResponse.java
index 231e4bc..1b130a9 100644
--- a/core/java/android/credentials/GetCandidateCredentialsResponse.java
+++ b/core/java/android/credentials/GetCandidateCredentialsResponse.java
@@ -53,6 +53,15 @@
mCandidateProviderDataList = new ArrayList<>(candidateProviderDataList);
}
+ /**
+ * Returns candidate provider data list.
+ *
+ * @hide
+ */
+ public List<GetCredentialProviderData> getCandidateProviderDataList() {
+ return mCandidateProviderDataList;
+ }
+
protected GetCandidateCredentialsResponse(Parcel in) {
List<GetCredentialProviderData> candidateProviderDataList = new ArrayList<>();
in.readTypedList(candidateProviderDataList, GetCredentialProviderData.CREATOR);
diff --git a/core/java/android/hardware/biometrics/BiometricPrompt.java b/core/java/android/hardware/biometrics/BiometricPrompt.java
index af448f0..490ff64 100644
--- a/core/java/android/hardware/biometrics/BiometricPrompt.java
+++ b/core/java/android/hardware/biometrics/BiometricPrompt.java
@@ -20,8 +20,10 @@
import static android.Manifest.permission.USE_BIOMETRIC;
import static android.Manifest.permission.USE_BIOMETRIC_INTERNAL;
import static android.hardware.biometrics.BiometricManager.Authenticators;
+import static android.hardware.biometrics.Flags.FLAG_ADD_KEY_AGREEMENT_CRYPTO_OBJECT;
import android.annotation.CallbackExecutor;
+import android.annotation.FlaggedApi;
import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.Nullable;
@@ -53,6 +55,7 @@
import java.util.concurrent.Executor;
import javax.crypto.Cipher;
+import javax.crypto.KeyAgreement;
import javax.crypto.Mac;
/**
@@ -748,7 +751,7 @@
* A wrapper class for the cryptographic operations supported by BiometricPrompt.
*
* <p>Currently the framework supports {@link Signature}, {@link Cipher}, {@link Mac},
- * {@link IdentityCredential}, and {@link PresentationSession}.
+ * {@link IdentityCredential}, {@link PresentationSession} and {@link KeyAgreement}.
*
* <p>Cryptographic operations in Android can be split into two categories: auth-per-use and
* time-based. This is specified during key creation via the timeout parameter of the
@@ -793,6 +796,11 @@
super(session);
}
+ @FlaggedApi(FLAG_ADD_KEY_AGREEMENT_CRYPTO_OBJECT)
+ public CryptoObject(@NonNull KeyAgreement keyAgreement) {
+ super(keyAgreement);
+ }
+
/**
* Get {@link Signature} object.
* @return {@link Signature} object or null if this doesn't contain one.
@@ -834,6 +842,15 @@
public @Nullable PresentationSession getPresentationSession() {
return super.getPresentationSession();
}
+
+ /**
+ * Get {@link KeyAgreement} object.
+ * @return {@link KeyAgreement} object or null if this doesn't contain one.
+ */
+ @FlaggedApi(FLAG_ADD_KEY_AGREEMENT_CRYPTO_OBJECT)
+ public @Nullable KeyAgreement getKeyAgreement() {
+ return super.getKeyAgreement();
+ }
}
/**
diff --git a/core/java/android/hardware/biometrics/CryptoObject.java b/core/java/android/hardware/biometrics/CryptoObject.java
index 267ef36..151f819 100644
--- a/core/java/android/hardware/biometrics/CryptoObject.java
+++ b/core/java/android/hardware/biometrics/CryptoObject.java
@@ -16,6 +16,9 @@
package android.hardware.biometrics;
+import static android.hardware.biometrics.Flags.FLAG_ADD_KEY_AGREEMENT_CRYPTO_OBJECT;
+
+import android.annotation.FlaggedApi;
import android.annotation.NonNull;
import android.security.identity.IdentityCredential;
import android.security.identity.PresentationSession;
@@ -24,6 +27,7 @@
import java.security.Signature;
import javax.crypto.Cipher;
+import javax.crypto.KeyAgreement;
import javax.crypto.Mac;
/**
@@ -62,6 +66,11 @@
mCrypto = session;
}
+ @FlaggedApi(FLAG_ADD_KEY_AGREEMENT_CRYPTO_OBJECT)
+ public CryptoObject(@NonNull KeyAgreement keyAgreement) {
+ mCrypto = keyAgreement;
+ }
+
/**
* Get {@link Signature} object.
* @return {@link Signature} object or null if this doesn't contain one.
@@ -105,6 +114,15 @@
}
/**
+ * Get {@link PresentationSession} object.
+ * @return {@link PresentationSession} object or null if this doesn't contain one.
+ */
+ @FlaggedApi(FLAG_ADD_KEY_AGREEMENT_CRYPTO_OBJECT)
+ public KeyAgreement getKeyAgreement() {
+ return mCrypto instanceof KeyAgreement ? (KeyAgreement) mCrypto : null;
+ }
+
+ /**
* @hide
* @return the opId associated with this object or 0 if none
*/
diff --git a/core/java/android/hardware/fingerprint/FingerprintManager.java b/core/java/android/hardware/fingerprint/FingerprintManager.java
index f594377..5bfda70 100644
--- a/core/java/android/hardware/fingerprint/FingerprintManager.java
+++ b/core/java/android/hardware/fingerprint/FingerprintManager.java
@@ -24,12 +24,14 @@
import static android.Manifest.permission.USE_BIOMETRIC_INTERNAL;
import static android.Manifest.permission.USE_FINGERPRINT;
import static android.hardware.biometrics.BiometricConstants.BIOMETRIC_LOCKOUT_NONE;
+import static android.hardware.biometrics.Flags.FLAG_ADD_KEY_AGREEMENT_CRYPTO_OBJECT;
import static android.hardware.fingerprint.FingerprintSensorProperties.TYPE_POWER_BUTTON;
import static com.android.internal.util.FrameworkStatsLog.AUTH_DEPRECATED_APIUSED__DEPRECATED_API__API_FINGERPRINT_MANAGER_AUTHENTICATE;
import static com.android.internal.util.FrameworkStatsLog.AUTH_DEPRECATED_APIUSED__DEPRECATED_API__API_FINGERPRINT_MANAGER_HAS_ENROLLED_FINGERPRINTS;
import static com.android.internal.util.FrameworkStatsLog.AUTH_DEPRECATED_APIUSED__DEPRECATED_API__API_FINGERPRINT_MANAGER_IS_HARDWARE_DETECTED;
+import android.annotation.FlaggedApi;
import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.Nullable;
@@ -76,6 +78,7 @@
import java.util.concurrent.Executor;
import javax.crypto.Cipher;
+import javax.crypto.KeyAgreement;
import javax.crypto.Mac;
/**
@@ -312,6 +315,16 @@
public PresentationSession getPresentationSession() {
return super.getPresentationSession();
}
+
+ /**
+ * Get {@link KeyAgreement} object.
+ * @return {@link KeyAgreement} object or null if this doesn't contain one.
+ * @hide
+ */
+ @FlaggedApi(FLAG_ADD_KEY_AGREEMENT_CRYPTO_OBJECT)
+ public KeyAgreement getKeyAgreement() {
+ return super.getKeyAgreement();
+ }
}
/**
diff --git a/core/java/android/os/OomKillRecord.java b/core/java/android/os/OomKillRecord.java
new file mode 100644
index 0000000..151a65f
--- /dev/null
+++ b/core/java/android/os/OomKillRecord.java
@@ -0,0 +1,63 @@
+/*
+ * Copyright (C) 2023 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;
+
+
+/**
+ * Expected data to get back from the OOM event's file.
+ * Note that this should be equivalent to the struct <b>OomKill</b> inside
+ * <pre>
+ * system/memory/libmeminfo/libmemevents/include/memevents.h
+ * </pre>
+ *
+ * @hide
+ */
+public final class OomKillRecord {
+ private long mTimeStampInMillis;
+ private int mPid;
+ private int mUid;
+ private String mProcessName;
+ private short mOomScoreAdj;
+
+ public OomKillRecord(long timeStampInMillis, int pid, int uid,
+ String processName, short oomScoreAdj) {
+ this.mTimeStampInMillis = timeStampInMillis;
+ this.mPid = pid;
+ this.mUid = uid;
+ this.mProcessName = processName;
+ this.mOomScoreAdj = oomScoreAdj;
+ }
+
+ public long getTimestampMilli() {
+ return mTimeStampInMillis;
+ }
+
+ public int getPid() {
+ return mPid;
+ }
+
+ public int getUid() {
+ return mUid;
+ }
+
+ public String getProcessName() {
+ return mProcessName;
+ }
+
+ public short getOomScoreAdj() {
+ return mOomScoreAdj;
+ }
+}
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index b414ed4..36d3180 100644
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -11607,6 +11607,45 @@
"accessibility_magnification_joystick_enabled";
/**
+ * Controls magnification enable gesture. Accessibility magnification can have one or more
+ * enable gestures.
+ *
+ * @see #ACCESSIBILITY_MAGNIFICATION_GESTURE_NONE
+ * @see #ACCESSIBILITY_MAGNIFICATION_GESTURE_SINGLE_FINGER_TRIPLE_TAP
+ * @see #ACCESSIBILITY_MAGNIFICATION_GESTURE_TWO_FINGER_TRIPLE_TAP
+ * @hide
+ */
+ public static final String ACCESSIBILITY_MAGNIFICATION_GESTURE =
+ "accessibility_magnification_gesture";
+
+ /**
+ * Magnification enable gesture value that is a default value.
+ * @hide
+ */
+ public static final int ACCESSIBILITY_MAGNIFICATION_GESTURE_NONE = 0x0;
+
+ /**
+ * Magnification enable gesture value is single finger triple tap.
+ * @hide
+ */
+ public static final int ACCESSIBILITY_MAGNIFICATION_GESTURE_SINGLE_FINGER_TRIPLE_TAP = 0x1;
+
+ /**
+ * Magnification enable gesture value is two finger triple tap.
+ * @hide
+ */
+ public static final int ACCESSIBILITY_MAGNIFICATION_GESTURE_TWO_FINGER_TRIPLE_TAP = 0x2;
+
+ /**
+ * Magnification enable gesture values include single finger triple tap and two finger
+ * triple tap.
+ * @hide
+ */
+ public static final int ACCESSIBILITY_MAGNIFICATION_GESTURE_ALL =
+ ACCESSIBILITY_MAGNIFICATION_GESTURE_SINGLE_FINGER_TRIPLE_TAP
+ | ACCESSIBILITY_MAGNIFICATION_GESTURE_TWO_FINGER_TRIPLE_TAP;
+
+ /**
* Controls magnification capability. Accessibility magnification is capable of at least one
* of the magnification modes.
*
diff --git a/core/java/android/service/credentials/CredentialProviderService.java b/core/java/android/service/credentials/CredentialProviderService.java
index be7b722..a2b0a66 100644
--- a/core/java/android/service/credentials/CredentialProviderService.java
+++ b/core/java/android/service/credentials/CredentialProviderService.java
@@ -153,6 +153,18 @@
public static final String EXTRA_BEGIN_GET_CREDENTIAL_REQUEST =
"android.service.credentials.extra.BEGIN_GET_CREDENTIAL_REQUEST";
+ /**
+ * The key to autofillId associated with the requested credential option and the corresponding
+ * credential entry. The associated autofillId will be contained inside the candidate query
+ * bundle of {@link android.credentials.CredentialOption} if requested through the
+ * {@link com.android.credentialmanager.autofill.CredentialAutofillService}. The resulting
+ * credential entry will contain the autofillId inside its framework extras intent.
+ *
+ * @hide
+ */
+ public static final String EXTRA_AUTOFILL_ID =
+ "android.service.credentials.extra.AUTOFILL_ID";
+
private static final String TAG = "CredProviderService";
/**
diff --git a/core/java/android/view/IRecentsAnimationController.aidl b/core/java/android/view/IRecentsAnimationController.aidl
index c4d3070..a150187 100644
--- a/core/java/android/view/IRecentsAnimationController.aidl
+++ b/core/java/android/view/IRecentsAnimationController.aidl
@@ -23,6 +23,8 @@
import android.window.PictureInPictureSurfaceTransaction;
import android.window.TaskSnapshot;
+import com.android.internal.os.IResultReceiver;
+
/**
* Passed to the {@link IRecentsAnimationRunner} in order for the runner to control to let the
* runner control certain aspects of the recents animation, and to notify window manager when the
@@ -58,7 +60,7 @@
* top resumed app, false otherwise.
*/
@UnsupportedAppUsage
- void finish(boolean moveHomeToTop, boolean sendUserLeaveHint);
+ void finish(boolean moveHomeToTop, boolean sendUserLeaveHint, in IResultReceiver finishCb);
/**
* Called by the handler to indicate that the recents animation input consumer should be
diff --git a/core/java/android/view/InputWindowHandle.java b/core/java/android/view/InputWindowHandle.java
index 2761aae..45b3fdd 100644
--- a/core/java/android/view/InputWindowHandle.java
+++ b/core/java/android/view/InputWindowHandle.java
@@ -16,6 +16,8 @@
package android.view;
+import static com.android.window.flags.Flags.surfaceTrustedOverlay;
+
import android.annotation.IntDef;
import android.annotation.Nullable;
import android.graphics.Matrix;
@@ -35,7 +37,6 @@
* @hide
*/
public final class InputWindowHandle {
-
/**
* An internal annotation for all the {@link android.os.InputConfig} flags that can be
* specified to {@link #inputConfig} to control the behavior of an input window. Only the
@@ -59,7 +60,6 @@
InputConfig.DUPLICATE_TOUCH_TO_WALLPAPER,
InputConfig.IS_WALLPAPER,
InputConfig.PAUSE_DISPATCHING,
- InputConfig.TRUSTED_OVERLAY,
InputConfig.WATCH_OUTSIDE_TOUCH,
InputConfig.SLIPPERY,
InputConfig.DISABLE_USER_ACTIVITY,
@@ -272,4 +272,13 @@
}
this.inputConfig &= ~inputConfig;
}
+
+ public void setTrustedOverlay(SurfaceControl.Transaction t, SurfaceControl sc,
+ boolean isTrusted) {
+ if (surfaceTrustedOverlay()) {
+ t.setTrustedOverlay(sc, isTrusted);
+ } else if (isTrusted) {
+ inputConfig |= InputConfig.TRUSTED_OVERLAY;
+ }
+ }
}
diff --git a/core/java/android/view/SurfaceControlViewHost.java b/core/java/android/view/SurfaceControlViewHost.java
index effc127..57b19a8 100644
--- a/core/java/android/view/SurfaceControlViewHost.java
+++ b/core/java/android/view/SurfaceControlViewHost.java
@@ -407,7 +407,7 @@
public @Nullable SurfacePackage getSurfacePackage() {
if (mSurfaceControl != null && mAccessibilityEmbeddedConnection != null) {
return new SurfacePackage(new SurfaceControl(mSurfaceControl, "getSurfacePackage"),
- mAccessibilityEmbeddedConnection, getFocusGrantToken(), mRemoteInterface);
+ mAccessibilityEmbeddedConnection, getInputTransferToken(), mRemoteInterface);
} else {
return null;
}
@@ -526,10 +526,12 @@
}
/**
+ * Returns an input token used which can be used to request focus on the embedded surface.
+ *
* @hide
*/
- public IBinder getFocusGrantToken() {
- return mWm.getFocusGrantToken(getWindowToken().asBinder());
+ public IBinder getInputTransferToken() {
+ return mWm.getInputTransferToken(getWindowToken().asBinder());
}
private void addWindowToken(WindowManager.LayoutParams attrs) {
diff --git a/core/java/android/view/WindowManager.java b/core/java/android/view/WindowManager.java
index e64274e..2f4bea0 100644
--- a/core/java/android/view/WindowManager.java
+++ b/core/java/android/view/WindowManager.java
@@ -1850,6 +1850,8 @@
to = "PHONE"),
@ViewDebug.IntToString(from = TYPE_SYSTEM_ALERT,
to = "SYSTEM_ALERT"),
+ @ViewDebug.IntToString(from = TYPE_KEYGUARD,
+ to = "KEYGUARD"),
@ViewDebug.IntToString(from = TYPE_TOAST,
to = "TOAST"),
@ViewDebug.IntToString(from = TYPE_SYSTEM_OVERLAY,
@@ -1898,6 +1900,8 @@
to = "PRIVATE_PRESENTATION"),
@ViewDebug.IntToString(from = TYPE_VOICE_INTERACTION,
to = "VOICE_INTERACTION"),
+ @ViewDebug.IntToString(from = TYPE_ACCESSIBILITY_OVERLAY,
+ to = "ACCESSIBILITY_OVERLAY"),
@ViewDebug.IntToString(from = TYPE_VOICE_INTERACTION_STARTING,
to = "VOICE_INTERACTION_STARTING"),
@ViewDebug.IntToString(from = TYPE_DOCK_DIVIDER,
@@ -1907,7 +1911,13 @@
@ViewDebug.IntToString(from = TYPE_SCREENSHOT,
to = "SCREENSHOT"),
@ViewDebug.IntToString(from = TYPE_APPLICATION_OVERLAY,
- to = "APPLICATION_OVERLAY")
+ to = "APPLICATION_OVERLAY"),
+ @ViewDebug.IntToString(from = TYPE_ACCESSIBILITY_MAGNIFICATION_OVERLAY,
+ to = "ACCESSIBILITY_MAGNIFICATION_OVERLAY"),
+ @ViewDebug.IntToString(from = TYPE_NOTIFICATION_SHADE,
+ to = "NOTIFICATION_SHADE"),
+ @ViewDebug.IntToString(from = TYPE_STATUS_BAR_ADDITIONAL,
+ to = "STATUS_BAR_ADDITIONAL")
})
@WindowType
public int type;
diff --git a/core/java/android/view/WindowlessWindowManager.java b/core/java/android/view/WindowlessWindowManager.java
index 7d3d283..8fe9b7b 100644
--- a/core/java/android/view/WindowlessWindowManager.java
+++ b/core/java/android/view/WindowlessWindowManager.java
@@ -58,7 +58,7 @@
SurfaceControl mLeash;
Rect mFrame;
Rect mAttachedFrame;
- IBinder mFocusGrantToken;
+ IBinder mInputTransferToken;
State(SurfaceControl sc, WindowManager.LayoutParams p, int displayId, IWindow client,
SurfaceControl leash, Rect frame) {
@@ -89,7 +89,7 @@
private final Configuration mConfiguration;
private final IWindowSession mRealWm;
private final IBinder mHostInputToken;
- private final IBinder mFocusGrantToken = new Binder();
+ private final IBinder mInputTransferToken = new Binder();
private InsetsState mInsetsState;
private final ClientWindowFrames mTmpFrames = new ClientWindowFrames();
private final MergedConfiguration mTmpConfig = new MergedConfiguration();
@@ -109,17 +109,17 @@
mConfiguration.setTo(configuration);
}
- IBinder getFocusGrantToken(IBinder window) {
+ IBinder getInputTransferToken(IBinder window) {
synchronized (this) {
// This can only happen if someone requested the focusGrantToken before setView was
// called for the SCVH. In that case, use the root focusGrantToken since this will be
// the same token sent to WMS for the root window once setView is called.
if (mStateForWindow.isEmpty()) {
- return mFocusGrantToken;
+ return mInputTransferToken;
}
State state = mStateForWindow.get(window);
if (state != null) {
- return state.mFocusGrantToken;
+ return state.mInputTransferToken;
}
}
@@ -207,9 +207,9 @@
// Give the first window the mFocusGrantToken since that's the token the host can use
// to give focus to the embedded.
if (mStateForWindow.isEmpty()) {
- state.mFocusGrantToken = mFocusGrantToken;
+ state.mInputTransferToken = mInputTransferToken;
} else {
- state.mFocusGrantToken = new Binder();
+ state.mInputTransferToken = new Binder();
}
mStateForWindow.put(window.asBinder(), state);
@@ -230,12 +230,13 @@
new SurfaceControl(sc, "WindowlessWindowManager.addToDisplay"),
window, mHostInputToken, attrs.flags, attrs.privateFlags,
attrs.inputFeatures, attrs.type,
- attrs.token, state.mFocusGrantToken, attrs.getTitle().toString(),
+ attrs.token, state.mInputTransferToken, attrs.getTitle().toString(),
outInputChannel);
} else {
mRealWm.grantInputChannel(displayId, sc, window, mHostInputToken, attrs.flags,
attrs.privateFlags, attrs.inputFeatures, attrs.type, attrs.token,
- state.mFocusGrantToken, attrs.getTitle().toString(), outInputChannel);
+ state.mInputTransferToken, attrs.getTitle().toString(),
+ outInputChannel);
}
state.mInputChannelToken =
outInputChannel != null ? outInputChannel.getToken() : null;
diff --git a/core/java/android/view/accessibility/flags/accessibility_flags.aconfig b/core/java/android/view/accessibility/flags/accessibility_flags.aconfig
index a0d5800..e31ad82 100644
--- a/core/java/android/view/accessibility/flags/accessibility_flags.aconfig
+++ b/core/java/android/view/accessibility/flags/accessibility_flags.aconfig
@@ -4,5 +4,5 @@
namespace: "accessibility"
name: "force_invert_color"
description: "Enable force force-dark for smart inversion and dark theme everywhere"
- bug: "239594271"
+ bug: "282821643"
}
\ No newline at end of file
diff --git a/core/java/android/window/flags/window_surfaces.aconfig b/core/java/android/window/flags/window_surfaces.aconfig
new file mode 100644
index 0000000..1b98806
--- /dev/null
+++ b/core/java/android/window/flags/window_surfaces.aconfig
@@ -0,0 +1,11 @@
+package: "com.android.window.flags"
+
+# Project link: https://gantry.corp.google.com/projects/android_platform_window_surfaces/changes
+
+flag {
+ namespace: "window_surfaces"
+ name: "surface_trusted_overlay"
+ description: "Whether to add trusted overlay flag on the SurfaceControl or the InputWindow"
+ is_fixed_read_only: true
+ bug: "292032926"
+}
diff --git a/core/java/com/android/internal/jank/InteractionJankMonitor.java b/core/java/com/android/internal/jank/InteractionJankMonitor.java
index 1bfb51c..6e836e0 100644
--- a/core/java/com/android/internal/jank/InteractionJankMonitor.java
+++ b/core/java/com/android/internal/jank/InteractionJankMonitor.java
@@ -837,25 +837,41 @@
@WorkerThread
private void updateProperties(DeviceConfig.Properties properties) {
- mSamplingInterval = properties.getInt(SETTINGS_SAMPLING_INTERVAL_KEY,
- DEFAULT_SAMPLING_INTERVAL);
- mTraceThresholdMissedFrames = properties.getInt(SETTINGS_THRESHOLD_MISSED_FRAMES_KEY,
- DEFAULT_TRACE_THRESHOLD_MISSED_FRAMES);
- mTraceThresholdFrameTimeMillis = properties.getInt(
- SETTINGS_THRESHOLD_FRAME_TIME_MILLIS_KEY,
- DEFAULT_TRACE_THRESHOLD_FRAME_TIME_MILLIS);
- // Never allow the debug overlay to be used on user builds
- boolean debugOverlayEnabled = Build.IS_DEBUGGABLE && properties.getBoolean(
- SETTINGS_DEBUG_OVERLAY_ENABLED_KEY,
- DEFAULT_DEBUG_OVERLAY_ENABLED);
- if (debugOverlayEnabled && mDebugOverlay == null) {
- mDebugOverlay = new InteractionMonitorDebugOverlay(mLock, mDebugBgColor, mDebugYOffset);
- } else if (!debugOverlayEnabled && mDebugOverlay != null) {
- mDebugOverlay.dispose();
- mDebugOverlay = null;
+ for (String property : properties.getKeyset()) {
+ switch (property) {
+ case SETTINGS_SAMPLING_INTERVAL_KEY:
+ mSamplingInterval = properties.getInt(property, DEFAULT_SAMPLING_INTERVAL);
+ break;
+ case SETTINGS_THRESHOLD_MISSED_FRAMES_KEY:
+ mTraceThresholdMissedFrames =
+ properties.getInt(property, DEFAULT_TRACE_THRESHOLD_MISSED_FRAMES);
+ break;
+ case SETTINGS_THRESHOLD_FRAME_TIME_MILLIS_KEY:
+ mTraceThresholdFrameTimeMillis =
+ properties.getInt(property, DEFAULT_TRACE_THRESHOLD_FRAME_TIME_MILLIS);
+ break;
+ case SETTINGS_ENABLED_KEY:
+ mEnabled = properties.getBoolean(property, DEFAULT_ENABLED);
+ break;
+ case SETTINGS_DEBUG_OVERLAY_ENABLED_KEY:
+ // Never allow the debug overlay to be used on user builds
+ boolean debugOverlayEnabled = Build.IS_DEBUGGABLE
+ && properties.getBoolean(property, DEFAULT_DEBUG_OVERLAY_ENABLED);
+ if (debugOverlayEnabled && mDebugOverlay == null) {
+ mDebugOverlay = new InteractionMonitorDebugOverlay(
+ mLock, mDebugBgColor, mDebugYOffset);
+ } else if (!debugOverlayEnabled && mDebugOverlay != null) {
+ mDebugOverlay.dispose();
+ mDebugOverlay = null;
+ }
+ break;
+ default:
+ if (DEBUG) {
+ Log.d(TAG, "Got a change event for an unknown property: "
+ + property + " => " + properties.getString(property, ""));
+ }
+ }
}
- // The memory visibility is powered by the volatile field, mEnabled.
- mEnabled = properties.getBoolean(SETTINGS_ENABLED_KEY, DEFAULT_ENABLED);
}
@VisibleForTesting
diff --git a/core/java/com/android/internal/view/FloatingActionMode.java b/core/java/com/android/internal/view/FloatingActionMode.java
index 06e69f2..fd435d0 100644
--- a/core/java/com/android/internal/view/FloatingActionMode.java
+++ b/core/java/com/android/internal/view/FloatingActionMode.java
@@ -222,6 +222,7 @@
private boolean isContentRectWithinBounds() {
mContext.getDisplayNoVerify().getRealSize(mDisplaySize);
mScreenRect.set(0, 0, mDisplaySize.x, mDisplaySize.y);
+ mScreenRect.offset(mRootViewPositionOnScreen[0], mRootViewPositionOnScreen[1]);
return intersectsClosed(mContentRectOnScreen, mScreenRect)
&& intersectsClosed(mContentRectOnScreen, mViewRectOnScreen);
diff --git a/core/proto/android/providers/settings/secure.proto b/core/proto/android/providers/settings/secure.proto
index 6c93680..4732702 100644
--- a/core/proto/android/providers/settings/secure.proto
+++ b/core/proto/android/providers/settings/secure.proto
@@ -98,6 +98,7 @@
// Settings for font scaling
optional SettingProto accessibility_font_scaling_has_been_changed = 51 [ (android.privacy).dest = DEST_AUTOMATIC ];
optional SettingProto accessibility_force_invert_color_enabled = 52 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto accessibility_magnification_gesture = 53 [ (android.privacy).dest = DEST_AUTOMATIC ];
}
optional Accessibility accessibility = 2;
diff --git a/core/res/res/layout/autofill_save.xml b/core/res/res/layout/autofill_save.xml
index 8b6c901..27f8138 100644
--- a/core/res/res/layout/autofill_save.xml
+++ b/core/res/res/layout/autofill_save.xml
@@ -60,10 +60,11 @@
android:gravity="center"
android:textAppearance="@style/AutofillSaveUiTitle">
</TextView>
- <LinearLayout
+ <FrameLayout
android:id="@+id/autofill_save_custom_subtitle"
android:layout_width="match_parent"
android:layout_height="wrap_content"
+ android:minHeight="0dp"
android:visibility="gone"/>
</LinearLayout>
diff --git a/core/res/res/values-watch/dimens_material.xml b/core/res/res/values-watch/dimens_material.xml
index 2ab2d91..8becb08 100644
--- a/core/res/res/values-watch/dimens_material.xml
+++ b/core/res/res/values-watch/dimens_material.xml
@@ -47,11 +47,12 @@
<dimen name="progress_bar_height">24dp</dimen>
<!-- Progress bar message dimens -->
- <dimen name="message_progress_dialog_text_size">18sp</dimen>
+ <dimen name="message_progress_dialog_text_size">14sp</dimen>
<dimen name="message_progress_dialog_bottom_padding">80px</dimen>
<dimen name="message_progress_dialog_top_padding">0dp</dimen>
<dimen name="message_progress_dialog_start_padding">0dp</dimen>
<dimen name="message_progress_dialog_end_padding">0dp</dimen>
+ <item name="message_progress_dialog_letter_spacing" format="float" type="dimen">0.021</item>
<!-- fallback for screen percentage widths -->
<dimen name="screen_percentage_05">0dp</dimen>
diff --git a/core/res/res/values-watch/styles_material.xml b/core/res/res/values-watch/styles_material.xml
index 8698e86..f3e412d 100644
--- a/core/res/res/values-watch/styles_material.xml
+++ b/core/res/res/values-watch/styles_material.xml
@@ -100,7 +100,9 @@
<style name="ProgressDialogMessage">
<item name="android:textAlignment">center</item>
- <item name="textAppearance">@android:style/TextAppearance.DeviceDefault.Medium</item>
+ <item name="android:fontFamily">google-sans-text</item>
+ <item name="android:letterSpacing">@dimen/message_progress_dialog_letter_spacing</item>
+ <item name="textColor">?attr/textColorPrimary</item>
<item name="textSize">@dimen/message_progress_dialog_text_size</item>
<item name="paddingBottom">@dimen/message_progress_dialog_bottom_padding</item>
<item name="paddingEnd">@dimen/message_progress_dialog_end_padding</item>
diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml
index 3c296de..4360c5a 100644
--- a/core/res/res/values/config.xml
+++ b/core/res/res/values/config.xml
@@ -5394,6 +5394,7 @@
<item>1,1,1.0,.4,1</item>
<item>1,1,1.0,.15,15</item>
<item>0,0,0.7,0,1</item>
+ <item>0,0,0.83333,0,1</item>
</string-array>
<!-- The integer index of the selected option in config_udfps_touch_detection_options -->
diff --git a/core/res/res/values/config_device_idle.xml b/core/res/res/values/config_device_idle.xml
index 98a5ff9..bc9ca3d 100644
--- a/core/res/res/values/config_device_idle.xml
+++ b/core/res/res/values/config_device_idle.xml
@@ -42,6 +42,15 @@
<!-- Default for DeviceIdleController.Constants.LIGHT_IDLE_FACTOR -->
<item name="device_idle_light_idle_factor" format="float" type="integer">2.0</item>
+ <!-- Default for DeviceIdleController.Constants.LIGHT_IDLE_INCREASE_LINEARLY -->
+ <bool name="device_idle_light_idle_increase_linearly">false</bool>
+
+ <!-- Default for DeviceIdleController.Constants.LIGHT_IDLE_LINEAR_INCREASE_FACTOR_MS -->
+ <integer name="device_idle_light_idle_linear_increase_factor_ms">300000</integer>
+
+ <!-- Default for DeviceIdleController.Constants.LIGHT_IDLE_FLEX_LINEAR_INCREASE_FACTOR_MS -->
+ <integer name="device_idle_light_idle_flex_linear_increase_factor_ms">60000</integer>
+
<!-- Default for DeviceIdleController.Constants.LIGHT_MAX_IDLE_TIMEOUT -->
<integer name="device_idle_light_max_idle_to_ms">900000</integer>
diff --git a/core/res/res/values/config_telephony.xml b/core/res/res/values/config_telephony.xml
index 71d696e..3ba150b 100644
--- a/core/res/res/values/config_telephony.xml
+++ b/core/res/res/values/config_telephony.xml
@@ -73,7 +73,7 @@
CarrierConfigManager#KEY_AUTO_DATA_SWITCH_RAT_SIGNAL_SCORE_STRING_ARRAY.
If 0, the device always switch to the higher score SIM.
If < 0, the network type and signal strength based auto switch is disabled. -->
- <integer name="auto_data_switch_score_tolerance">-1</integer>
+ <integer name="auto_data_switch_score_tolerance">4000</integer>
<java-symbol type="integer" name="auto_data_switch_score_tolerance" />
<!-- Boolean indicating whether the Iwlan data service supports persistence of iwlan ipsec
@@ -219,4 +219,8 @@
<bool name="telephony_analytics_switch">true</bool>
<java-symbol type="bool" name="telephony_analytics_switch" />
+ <!-- Whether to enable modem on boot if behavior is not defined -->
+ <bool name="config_enable_cellular_on_boot_default">true</bool>
+ <java-symbol type="bool" name="config_enable_cellular_on_boot_default" />
+
</resources>
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index 193f3ad..7f30695 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -4537,7 +4537,10 @@
<java-symbol type="integer" name="device_idle_light_idle_to_init_flex_ms" />
<java-symbol type="integer" name="device_idle_light_idle_to_max_flex_ms" />
<java-symbol type="integer" name="device_idle_light_idle_factor" />
+ <java-symbol type="bool" name="device_idle_light_idle_increase_linearly" />
<java-symbol type="integer" name="device_idle_light_max_idle_to_ms" />
+ <java-symbol type="integer" name="device_idle_light_idle_linear_increase_factor_ms" />
+ <java-symbol type="integer" name="device_idle_light_idle_flex_linear_increase_factor_ms" />
<java-symbol type="integer" name="device_idle_light_idle_maintenance_min_budget_ms" />
<java-symbol type="integer" name="device_idle_light_idle_maintenance_max_budget_ms" />
<java-symbol type="integer" name="device_idle_min_light_maintenance_time_ms" />
diff --git a/core/tests/BroadcastRadioTests/Android.bp b/core/tests/BroadcastRadioTests/Android.bp
index 85d54e0..054d10c 100644
--- a/core/tests/BroadcastRadioTests/Android.bp
+++ b/core/tests/BroadcastRadioTests/Android.bp
@@ -38,7 +38,7 @@
static_libs: [
"services.core",
"androidx.test.rules",
- "truth-prebuilt",
+ "truth",
"testng",
"mockito-target-extended",
],
diff --git a/core/tests/BroadcastRadioTests/src/com/android/server/broadcastradio/aidl/TunerSessionTest.java b/core/tests/BroadcastRadioTests/src/com/android/server/broadcastradio/aidl/TunerSessionTest.java
index a195228..824f591 100644
--- a/core/tests/BroadcastRadioTests/src/com/android/server/broadcastradio/aidl/TunerSessionTest.java
+++ b/core/tests/BroadcastRadioTests/src/com/android/server/broadcastradio/aidl/TunerSessionTest.java
@@ -16,20 +16,20 @@
package com.android.server.broadcastradio.aidl;
+import static com.android.dx.mockito.inline.extended.ExtendedMockito.after;
+import static com.android.dx.mockito.inline.extended.ExtendedMockito.any;
+import static com.android.dx.mockito.inline.extended.ExtendedMockito.anyBoolean;
+import static com.android.dx.mockito.inline.extended.ExtendedMockito.anyInt;
+import static com.android.dx.mockito.inline.extended.ExtendedMockito.doAnswer;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.doReturn;
+import static com.android.dx.mockito.inline.extended.ExtendedMockito.doThrow;
+import static com.android.dx.mockito.inline.extended.ExtendedMockito.eq;
+import static com.android.dx.mockito.inline.extended.ExtendedMockito.mock;
+import static com.android.dx.mockito.inline.extended.ExtendedMockito.never;
+import static com.android.dx.mockito.inline.extended.ExtendedMockito.timeout;
+import static com.android.dx.mockito.inline.extended.ExtendedMockito.verify;
import static org.junit.Assert.assertThrows;
-import static org.mockito.ArgumentMatchers.any;
-import static org.mockito.ArgumentMatchers.anyBoolean;
-import static org.mockito.ArgumentMatchers.anyInt;
-import static org.mockito.ArgumentMatchers.eq;
-import static org.mockito.Mockito.doAnswer;
-import static org.mockito.Mockito.doThrow;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.never;
-import static org.mockito.Mockito.timeout;
-import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.when;
import android.app.compat.CompatChanges;
import android.graphics.Bitmap;
@@ -81,8 +81,8 @@
private static final int USER_ID_1 = 11;
private static final int USER_ID_2 = 12;
- private static final VerificationWithTimeout CALLBACK_TIMEOUT =
- timeout(/* millis= */ 200);
+ private static final int CALLBACK_TIMEOUT_MS = 200;
+ private static final VerificationWithTimeout CALLBACK_TIMEOUT = timeout(CALLBACK_TIMEOUT_MS);
private static final int SIGNAL_QUALITY = 90;
private static final long AM_FM_FREQUENCY_SPACING = 500;
private static final long[] AM_FM_FREQUENCY_LIST = {97_500, 98_100, 99_100};
@@ -166,12 +166,12 @@
@Before
public void setup() throws Exception {
- when(mUserHandleMock.getIdentifier()).thenReturn(USER_ID_1);
doReturn(true).when(() -> CompatChanges.isChangeEnabled(
eq(ConversionUtils.RADIO_U_VERSION_REQUIRED), anyInt()));
+ doReturn(USER_ID_1).when(mUserHandleMock).getIdentifier();
+ doReturn(mUserHandleMock).when(() -> Binder.getCallingUserHandle());
doReturn(true).when(() -> RadioServiceUserController.isCurrentOrSystemUser());
doReturn(USER_ID_1).when(() -> RadioServiceUserController.getCurrentUser());
- doReturn(mUserHandleMock).when(() -> Binder.getCallingUserHandle());
mRadioModule = new RadioModule(mBroadcastRadioMock,
AidlTestUtils.makeDefaultModuleProperties());
@@ -222,7 +222,7 @@
return Result.OK;
}).when(mBroadcastRadioMock).seek(anyBoolean(), anyBoolean());
- when(mBroadcastRadioMock.getImage(anyInt())).thenReturn(null);
+ doReturn(null).when(mBroadcastRadioMock).getImage(anyInt());
doAnswer(invocation -> {
int configFlag = (int) invocation.getArguments()[0];
@@ -275,7 +275,7 @@
mTunerSessions[0].setConfiguration(FM_BAND_CONFIG);
- verify(mAidlTunerCallbackMocks[0], CALLBACK_TIMEOUT.times(0))
+ verify(mAidlTunerCallbackMocks[0], after(CALLBACK_TIMEOUT_MS).times(0))
.onConfigurationChanged(FM_BAND_CONFIG);
}
@@ -446,26 +446,11 @@
mTunerSessions[0].tune(initialSel);
- verify(mAidlTunerCallbackMocks[0], CALLBACK_TIMEOUT.times(0))
+ verify(mAidlTunerCallbackMocks[0], after(CALLBACK_TIMEOUT_MS).times(0))
.onCurrentProgramInfoChanged(tuneInfo);
}
@Test
- public void tune_forSystemUser() throws Exception {
- when(mUserHandleMock.getIdentifier()).thenReturn(UserHandle.USER_SYSTEM);
- doReturn(mUserHandleMock).when(() -> Binder.getCallingUserHandle());
- doReturn(true).when(() -> RadioServiceUserController.isCurrentOrSystemUser());
- ProgramSelector initialSel = AidlTestUtils.makeFmSelector(AM_FM_FREQUENCY_LIST[1]);
- RadioManager.ProgramInfo tuneInfo =
- AidlTestUtils.makeProgramInfo(initialSel, SIGNAL_QUALITY);
- openAidlClients(/* numClients= */ 1);
-
- mTunerSessions[0].tune(initialSel);
-
- verify(mAidlTunerCallbackMocks[0], CALLBACK_TIMEOUT).onCurrentProgramInfoChanged(tuneInfo);
- }
-
- @Test
public void tune_withUnknownErrorFromHal_fails() throws Exception {
openAidlClients(/* numClients= */ 1);
ProgramSelector sel = AidlTestUtils.makeFmSelector(AM_FM_FREQUENCY_LIST[1]);
@@ -525,7 +510,7 @@
mTunerSessions[0].step(/* directionDown= */ true, /* skipSubChannel= */ false);
- verify(mAidlTunerCallbackMocks[0], CALLBACK_TIMEOUT.times(0))
+ verify(mAidlTunerCallbackMocks[0], after(CALLBACK_TIMEOUT_MS).times(0))
.onCurrentProgramInfoChanged(any());
}
@@ -604,7 +589,7 @@
mTunerSessions[0].seek(/* directionDown= */ true, /* skipSubChannel= */ false);
- verify(mAidlTunerCallbackMocks[0], CALLBACK_TIMEOUT.times(0))
+ verify(mAidlTunerCallbackMocks[0], after(CALLBACK_TIMEOUT_MS).times(0))
.onCurrentProgramInfoChanged(seekUpInfo);
}
@@ -638,6 +623,7 @@
openAidlClients(/* numClients= */ 1);
ProgramSelector initialSel = AidlTestUtils.makeFmSelector(AM_FM_FREQUENCY_LIST[1]);
mTunerSessions[0].tune(initialSel);
+ verify(mAidlTunerCallbackMocks[0], CALLBACK_TIMEOUT).onCurrentProgramInfoChanged(any());
doReturn(false).when(() -> RadioServiceUserController.isCurrentOrSystemUser());
mTunerSessions[0].cancel();
@@ -686,8 +672,8 @@
public void getImage_whenHalThrowsException_fails() throws Exception {
openAidlClients(/* numClients= */ 1);
String exceptionMessage = "HAL service died.";
- when(mBroadcastRadioMock.getImage(anyInt()))
- .thenThrow(new RemoteException(exceptionMessage));
+ doThrow(new RemoteException(exceptionMessage)).when(mBroadcastRadioMock)
+ .getImage(anyInt());
RuntimeException thrown = assertThrows(RuntimeException.class, () -> {
mTunerSessions[0].getImage(/* id= */ 1);
@@ -713,7 +699,8 @@
mTunerSessions[0].startBackgroundScan();
- verify(mAidlTunerCallbackMocks[0], CALLBACK_TIMEOUT.times(0)).onBackgroundScanComplete();
+ verify(mAidlTunerCallbackMocks[0], after(CALLBACK_TIMEOUT_MS).times(0))
+ .onBackgroundScanComplete();
}
@Test
@@ -905,7 +892,8 @@
mHalTunerCallback.onProgramListUpdated(AidlTestUtils.makeHalChunk(/* purge= */ false,
/* complete= */ true, List.of(TEST_FM_INFO), new ArrayList<>()));
- verify(mAidlTunerCallbackMocks[0], CALLBACK_TIMEOUT.times(0)).onProgramListUpdated(any());
+ verify(mAidlTunerCallbackMocks[0], after(CALLBACK_TIMEOUT_MS).times(0))
+ .onProgramListUpdated(any());
}
@Test
@@ -1160,8 +1148,8 @@
Map<String, String> parametersSet = Map.of("mockParam1", "mockValue1",
"mockParam2", "mockValue2");
String exceptionMessage = "HAL service died.";
- when(mBroadcastRadioMock.setParameters(any()))
- .thenThrow(new RemoteException(exceptionMessage));
+ doThrow(new RemoteException(exceptionMessage)).when(mBroadcastRadioMock)
+ .setParameters(any());
RuntimeException thrown = assertThrows(RuntimeException.class, () -> {
mTunerSessions[0].setParameters(parametersSet);
@@ -1186,8 +1174,8 @@
openAidlClients(/* numClients= */ 1);
List<String> parameterKeys = List.of("mockKey1", "mockKey2");
String exceptionMessage = "HAL service died.";
- when(mBroadcastRadioMock.getParameters(any()))
- .thenThrow(new RemoteException(exceptionMessage));
+ doThrow(new RemoteException(exceptionMessage)).when(mBroadcastRadioMock)
+ .getParameters(any());
RuntimeException thrown = assertThrows(RuntimeException.class, () -> {
mTunerSessions[0].getParameters(parameterKeys);
@@ -1198,7 +1186,7 @@
}
@Test
- public void onCurrentProgramInfoChanged_withNoncurrentUser_doesNotInvokeCallback()
+ public void onCurrentProgramInfoChanged_withNonCurrentUser_doesNotInvokeCallback()
throws Exception {
openAidlClients(1);
doReturn(USER_ID_2).when(() -> RadioServiceUserController.getCurrentUser());
@@ -1206,7 +1194,7 @@
mHalTunerCallback.onCurrentProgramInfoChanged(AidlTestUtils.makeHalProgramInfo(
AidlTestUtils.makeHalFmSelector(AM_FM_FREQUENCY_LIST[1]), SIGNAL_QUALITY));
- verify(mAidlTunerCallbackMocks[0], CALLBACK_TIMEOUT.times(0))
+ verify(mAidlTunerCallbackMocks[0], after(CALLBACK_TIMEOUT_MS).times(0))
.onCurrentProgramInfoChanged(any());
}
diff --git a/core/tests/BroadcastRadioTests/src/com/android/server/broadcastradio/hal2/TunerSessionHidlTest.java b/core/tests/BroadcastRadioTests/src/com/android/server/broadcastradio/hal2/TunerSessionHidlTest.java
index fac9eaa..3b9d7ba 100644
--- a/core/tests/BroadcastRadioTests/src/com/android/server/broadcastradio/hal2/TunerSessionHidlTest.java
+++ b/core/tests/BroadcastRadioTests/src/com/android/server/broadcastradio/hal2/TunerSessionHidlTest.java
@@ -16,22 +16,22 @@
package com.android.server.broadcastradio.hal2;
+import static com.android.dx.mockito.inline.extended.ExtendedMockito.after;
+import static com.android.dx.mockito.inline.extended.ExtendedMockito.any;
+import static com.android.dx.mockito.inline.extended.ExtendedMockito.anyBoolean;
+import static com.android.dx.mockito.inline.extended.ExtendedMockito.anyInt;
+import static com.android.dx.mockito.inline.extended.ExtendedMockito.doAnswer;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.doReturn;
+import static com.android.dx.mockito.inline.extended.ExtendedMockito.doThrow;
+import static com.android.dx.mockito.inline.extended.ExtendedMockito.eq;
+import static com.android.dx.mockito.inline.extended.ExtendedMockito.mock;
+import static com.android.dx.mockito.inline.extended.ExtendedMockito.never;
+import static com.android.dx.mockito.inline.extended.ExtendedMockito.timeout;
+import static com.android.dx.mockito.inline.extended.ExtendedMockito.verify;
import static com.google.common.truth.Truth.assertWithMessage;
import static org.junit.Assert.assertThrows;
-import static org.mockito.ArgumentMatchers.any;
-import static org.mockito.ArgumentMatchers.anyBoolean;
-import static org.mockito.ArgumentMatchers.anyInt;
-import static org.mockito.ArgumentMatchers.eq;
-import static org.mockito.Mockito.doAnswer;
-import static org.mockito.Mockito.doThrow;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.never;
-import static org.mockito.Mockito.timeout;
-import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.when;
import android.graphics.Bitmap;
import android.hardware.broadcastradio.V2_0.Constants;
@@ -78,8 +78,8 @@
private static final int USER_ID_1 = 11;
private static final int USER_ID_2 = 12;
- private static final VerificationWithTimeout CALLBACK_TIMEOUT =
- timeout(/* millis= */ 200);
+ private static final int CALLBACK_TIMEOUT_MS = 200;
+ private static final VerificationWithTimeout CALLBACK_TIMEOUT = timeout(CALLBACK_TIMEOUT_MS);
private static final int SIGNAL_QUALITY = 1;
private static final long AM_FM_FREQUENCY_SPACING = 500;
private static final long[] AM_FM_FREQUENCY_LIST = {97_500, 98_100, 99_100};
@@ -113,7 +113,7 @@
@Before
public void setup() throws Exception {
- when(mUserHandleMock.getIdentifier()).thenReturn(USER_ID_1);
+ doReturn(USER_ID_1).when(mUserHandleMock).getIdentifier();
doReturn(mUserHandleMock).when(() -> Binder.getCallingUserHandle());
doReturn(true).when(() -> RadioServiceUserController.isCurrentOrSystemUser());
doReturn(USER_ID_1).when(() -> RadioServiceUserController.getCurrentUser());
@@ -170,7 +170,7 @@
return Result.OK;
}).when(mHalTunerSessionMock).scan(anyBoolean(), anyBoolean());
- when(mBroadcastRadioMock.getImage(anyInt())).thenReturn(new ArrayList<Byte>(0));
+ doReturn(new ArrayList<Byte>(0)).when(mBroadcastRadioMock).getImage(anyInt());
doAnswer(invocation -> {
int configFlag = (int) invocation.getArguments()[0];
@@ -227,7 +227,7 @@
mTunerSessions[0].setConfiguration(FM_BAND_CONFIG);
- verify(mAidlTunerCallbackMocks[0], CALLBACK_TIMEOUT.times(0))
+ verify(mAidlTunerCallbackMocks[0], after(CALLBACK_TIMEOUT_MS).times(0))
.onConfigurationChanged(FM_BAND_CONFIG);
}
@@ -379,7 +379,7 @@
mTunerSessions[0].tune(initialSel);
- verify(mAidlTunerCallbackMocks[0], CALLBACK_TIMEOUT.times(0))
+ verify(mAidlTunerCallbackMocks[0], after(CALLBACK_TIMEOUT_MS).times(0))
.onCurrentProgramInfoChanged(tuneInfo);
}
@@ -398,20 +398,6 @@
}
@Test
- public void tune_forSystemUser() throws Exception {
- when(mUserHandleMock.getIdentifier()).thenReturn(UserHandle.USER_SYSTEM);
- doReturn(mUserHandleMock).when(() -> Binder.getCallingUserHandle());
- doReturn(true).when(() -> RadioServiceUserController.isCurrentOrSystemUser());
- ProgramSelector initialSel = TestUtils.makeFmSelector(AM_FM_FREQUENCY_LIST[1]);
- RadioManager.ProgramInfo tuneInfo = TestUtils.makeProgramInfo(initialSel, SIGNAL_QUALITY);
- openAidlClients(/* numClients= */ 1);
-
- mTunerSessions[0].tune(initialSel);
-
- verify(mAidlTunerCallbackMocks[0], CALLBACK_TIMEOUT).onCurrentProgramInfoChanged(tuneInfo);
- }
-
- @Test
public void step_withDirectionUp() throws Exception {
long initFreq = AM_FM_FREQUENCY_LIST[1];
ProgramSelector initialSel = TestUtils.makeFmSelector(initFreq);
@@ -455,7 +441,7 @@
mTunerSessions[0].step(/* directionDown= */ true, /* skipSubChannel= */ false);
- verify(mAidlTunerCallbackMocks[0], CALLBACK_TIMEOUT.times(0))
+ verify(mAidlTunerCallbackMocks[0], after(CALLBACK_TIMEOUT_MS).times(0))
.onCurrentProgramInfoChanged(any());
}
@@ -533,7 +519,7 @@
mTunerSessions[0].seek(/* directionDown= */ true, /* skipSubChannel= */ false);
- verify(mAidlTunerCallbackMocks[0], CALLBACK_TIMEOUT.times(0))
+ verify(mAidlTunerCallbackMocks[0], after(CALLBACK_TIMEOUT_MS).times(0))
.onCurrentProgramInfoChanged(seekUpInfo);
}
@@ -563,18 +549,6 @@
}
@Test
- public void cancel_forNonCurrentUser() throws Exception {
- openAidlClients(/* numClients= */ 1);
- ProgramSelector initialSel = TestUtils.makeFmSelector(AM_FM_FREQUENCY_LIST[1]);
- mTunerSessions[0].tune(initialSel);
- doReturn(false).when(() -> RadioServiceUserController.isCurrentOrSystemUser());
-
- mTunerSessions[0].cancel();
-
- verify(mHalTunerSessionMock, never()).cancel();
- }
-
- @Test
public void cancel_forNonCurrentUser_doesNotCancel() throws Exception {
openAidlClients(/* numClients= */ 1);
ProgramSelector initialSel = TestUtils.makeFmSelector(AM_FM_FREQUENCY_LIST[1]);
@@ -627,8 +601,7 @@
public void getImage_whenHalThrowsException_fails() throws Exception {
openAidlClients(/* numClients= */ 1);
String exceptionMessage = "HAL service died.";
- when(mBroadcastRadioMock.getImage(anyInt()))
- .thenThrow(new RemoteException(exceptionMessage));
+ doThrow(new RemoteException(exceptionMessage)).when(mBroadcastRadioMock).getImage(anyInt());
RuntimeException thrown = assertThrows(RuntimeException.class, () -> {
mTunerSessions[0].getImage(/* id= */ 1);
@@ -654,7 +627,8 @@
mTunerSessions[0].startBackgroundScan();
- verify(mAidlTunerCallbackMocks[0], CALLBACK_TIMEOUT.times(0)).onBackgroundScanComplete();
+ verify(mAidlTunerCallbackMocks[0], after(CALLBACK_TIMEOUT_MS).times(0))
+ .onBackgroundScanComplete();
}
@Test
@@ -845,8 +819,8 @@
Map<String, String> parametersSet = Map.of("mockParam1", "mockValue1",
"mockParam2", "mockValue2");
String exceptionMessage = "HAL service died.";
- when(mHalTunerSessionMock.setParameters(any()))
- .thenThrow(new RemoteException(exceptionMessage));
+ doThrow(new RemoteException(exceptionMessage)).when(mHalTunerSessionMock)
+ .setParameters(any());
RuntimeException thrown = assertThrows(RuntimeException.class, () -> {
mTunerSessions[0].setParameters(parametersSet);
@@ -871,8 +845,8 @@
openAidlClients(/* numClients= */ 1);
List<String> parameterKeys = List.of("mockKey1", "mockKey2");
String exceptionMessage = "HAL service died.";
- when(mHalTunerSessionMock.getParameters(any()))
- .thenThrow(new RemoteException(exceptionMessage));
+ doThrow(new RemoteException(exceptionMessage)).when(mHalTunerSessionMock)
+ .getParameters(any());
RuntimeException thrown = assertThrows(RuntimeException.class, () -> {
mTunerSessions[0].getParameters(parameterKeys);
@@ -883,7 +857,7 @@
}
@Test
- public void onCurrentProgramInfoChanged_withNoncurrentUser_doesNotInvokeCallback()
+ public void onCurrentProgramInfoChanged_withNonCurrentUser_doesNotInvokeCallback()
throws Exception {
openAidlClients(1);
doReturn(USER_ID_2).when(() -> RadioServiceUserController.getCurrentUser());
@@ -891,7 +865,7 @@
mHalTunerCallback.onCurrentProgramInfoChanged(TestUtils.makeHalProgramInfo(
TestUtils.makeHalFmSelector(/* freq= */ 97300), SIGNAL_QUALITY));
- verify(mAidlTunerCallbackMocks[0], CALLBACK_TIMEOUT.times(0))
+ verify(mAidlTunerCallbackMocks[0], after(CALLBACK_TIMEOUT_MS).times(0))
.onCurrentProgramInfoChanged(any());
}
diff --git a/core/tests/GameManagerTests/Android.bp b/core/tests/GameManagerTests/Android.bp
index 8c5d6d5..0e3bc65 100644
--- a/core/tests/GameManagerTests/Android.bp
+++ b/core/tests/GameManagerTests/Android.bp
@@ -30,7 +30,7 @@
"frameworks-base-testutils",
"junit",
"platform-test-annotations",
- "truth-prebuilt",
+ "truth",
],
libs: ["android.test.runner"],
platform_apis: true,
diff --git a/core/tests/PackageInstallerSessions/Android.bp b/core/tests/PackageInstallerSessions/Android.bp
index 6f2366e..b631df1 100644
--- a/core/tests/PackageInstallerSessions/Android.bp
+++ b/core/tests/PackageInstallerSessions/Android.bp
@@ -35,7 +35,7 @@
"frameworks-base-testutils",
"platform-test-annotations",
"testng",
- "truth-prebuilt",
+ "truth",
],
libs: [
diff --git a/core/tests/batterystatstests/BatteryUsageStatsProtoTests/Android.bp b/core/tests/batterystatstests/BatteryUsageStatsProtoTests/Android.bp
index 5260835..1fb5f2c 100644
--- a/core/tests/batterystatstests/BatteryUsageStatsProtoTests/Android.bp
+++ b/core/tests/batterystatstests/BatteryUsageStatsProtoTests/Android.bp
@@ -18,7 +18,7 @@
"platform-test-annotations",
"platformprotosnano",
"statsdprotolite",
- "truth-prebuilt",
+ "truth",
],
libs: ["android.test.runner"],
diff --git a/core/tests/bugreports/Android.bp b/core/tests/bugreports/Android.bp
index 2b34ee2..7c1ac48 100644
--- a/core/tests/bugreports/Android.bp
+++ b/core/tests/bugreports/Android.bp
@@ -32,7 +32,7 @@
static_libs: [
"androidx.test.rules",
"androidx.test.uiautomator_uiautomator",
- "truth-prebuilt",
+ "truth",
],
test_suites: ["general-tests"],
sdk_version: "test_current",
diff --git a/core/tests/coretests/Android.bp b/core/tests/coretests/Android.bp
index 04622fd..81dab08 100644
--- a/core/tests/coretests/Android.bp
+++ b/core/tests/coretests/Android.bp
@@ -58,7 +58,7 @@
"androidx.test.uiautomator_uiautomator",
"platform-test-annotations",
"platform-compat-test-rules",
- "truth-prebuilt",
+ "truth",
"print-test-util-lib",
"testng",
"servicestests-utils",
@@ -149,7 +149,7 @@
"androidx.test.runner",
"androidx.test.rules",
"mockito-target-minus-junit4",
- "truth-prebuilt",
+ "truth",
],
libs: [
diff --git a/core/tests/hdmitests/Android.bp b/core/tests/hdmitests/Android.bp
index 3d04937..5f6eaf9 100644
--- a/core/tests/hdmitests/Android.bp
+++ b/core/tests/hdmitests/Android.bp
@@ -30,7 +30,7 @@
"frameworks-base-testutils",
"guava-android-testlib",
"platform-test-annotations",
- "truth-prebuilt",
+ "truth",
],
libs: ["android.test.runner"],
platform_apis: true,
diff --git a/core/tests/mockingcoretests/Android.bp b/core/tests/mockingcoretests/Android.bp
index fde7c08..2d778b1 100644
--- a/core/tests/mockingcoretests/Android.bp
+++ b/core/tests/mockingcoretests/Android.bp
@@ -38,7 +38,7 @@
"androidx.test.ext.junit",
"mockito-target-extended-minus-junit4",
"platform-test-annotations",
- "truth-prebuilt",
+ "truth",
"testables",
],
diff --git a/core/tests/nfctests/Android.bp b/core/tests/nfctests/Android.bp
index c74600b..f81be49 100644
--- a/core/tests/nfctests/Android.bp
+++ b/core/tests/nfctests/Android.bp
@@ -27,7 +27,7 @@
"androidx.test.ext.junit",
"androidx.test.rules",
"mockito-target-minus-junit4",
- "truth-prebuilt",
+ "truth",
],
libs: [
"android.test.runner",
diff --git a/core/tests/overlaytests/device_self_targeting/Android.bp b/core/tests/overlaytests/device_self_targeting/Android.bp
index 063c569..931eac5 100644
--- a/core/tests/overlaytests/device_self_targeting/Android.bp
+++ b/core/tests/overlaytests/device_self_targeting/Android.bp
@@ -30,7 +30,7 @@
"androidx.test.runner",
"androidx.test.ext.junit",
"mockito-target-minus-junit4",
- "truth-prebuilt",
+ "truth",
],
optimize: {
diff --git a/core/tests/packagemonitortests/Android.bp b/core/tests/packagemonitortests/Android.bp
index 7b5d7df..b08850e 100644
--- a/core/tests/packagemonitortests/Android.bp
+++ b/core/tests/packagemonitortests/Android.bp
@@ -32,7 +32,7 @@
"compatibility-device-util-axt",
"frameworks-base-testutils",
"mockito-target-minus-junit4",
- "truth-prebuilt",
+ "truth",
],
libs: ["android.test.runner"],
platform_apis: true,
diff --git a/core/tests/privacytests/Android.bp b/core/tests/privacytests/Android.bp
index bc3dd81..4e24cd5 100644
--- a/core/tests/privacytests/Android.bp
+++ b/core/tests/privacytests/Android.bp
@@ -14,7 +14,7 @@
"junit",
"rappor-tests",
"androidx.test.rules",
- "truth-prebuilt",
+ "truth",
],
libs: ["android.test.runner"],
platform_apis: true,
diff --git a/core/tests/utiltests/Android.bp b/core/tests/utiltests/Android.bp
index 3798da5..580e73c 100644
--- a/core/tests/utiltests/Android.bp
+++ b/core/tests/utiltests/Android.bp
@@ -33,7 +33,7 @@
"frameworks-base-testutils",
"mockito-target-minus-junit4",
"androidx.test.ext.junit",
- "truth-prebuilt",
+ "truth",
"servicestests-utils",
],
diff --git a/core/tests/vibrator/Android.bp b/core/tests/vibrator/Android.bp
index 829409a..09608e9 100644
--- a/core/tests/vibrator/Android.bp
+++ b/core/tests/vibrator/Android.bp
@@ -18,7 +18,7 @@
"androidx.test.runner",
"androidx.test.rules",
"mockito-target-minus-junit4",
- "truth-prebuilt",
+ "truth",
"testng",
],
diff --git a/errorprone/Android.bp b/errorprone/Android.bp
index ad08026..c1d2235 100644
--- a/errorprone/Android.bp
+++ b/errorprone/Android.bp
@@ -41,7 +41,7 @@
java_resource_dirs: ["tests/res"],
java_resources: [":error_prone_android_framework_testdata"],
static_libs: [
- "truth-prebuilt",
+ "truth",
"kxml2-2.3.0",
"compile-testing-prebuilt",
"error_prone_android_framework_lib",
diff --git a/keystore/java/android/security/keystore2/AndroidKeyStoreProvider.java b/keystore/java/android/security/keystore2/AndroidKeyStoreProvider.java
index c55a781..11278e8 100644
--- a/keystore/java/android/security/keystore2/AndroidKeyStoreProvider.java
+++ b/keystore/java/android/security/keystore2/AndroidKeyStoreProvider.java
@@ -43,6 +43,7 @@
import java.security.interfaces.RSAPublicKey;
import javax.crypto.Cipher;
+import javax.crypto.KeyAgreement;
import javax.crypto.Mac;
import javax.crypto.SecretKey;
@@ -181,6 +182,8 @@
spi = ((Mac) cryptoPrimitive).getCurrentSpi();
} else if (cryptoPrimitive instanceof Cipher) {
spi = ((Cipher) cryptoPrimitive).getCurrentSpi();
+ } else if (cryptoPrimitive instanceof KeyAgreement) {
+ spi = ((KeyAgreement) cryptoPrimitive).getCurrentSpi();
} else {
throw new IllegalArgumentException("Unsupported crypto primitive: " + cryptoPrimitive
+ ". Supported: Signature, Mac, Cipher");
diff --git a/libs/WindowManager/Jetpack/tests/unittest/Android.bp b/libs/WindowManager/Jetpack/tests/unittest/Android.bp
index b6e743a..ed2ff2d 100644
--- a/libs/WindowManager/Jetpack/tests/unittest/Android.bp
+++ b/libs/WindowManager/Jetpack/tests/unittest/Android.bp
@@ -37,7 +37,7 @@
"androidx.test.rules",
"androidx.test.ext.junit",
"mockito-target-extended-minus-junit4",
- "truth-prebuilt",
+ "truth",
"testables",
"platform-test-annotations",
],
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BadgedImageView.java b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BadgedImageView.java
index f1ee8fa..a67821b 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BadgedImageView.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BadgedImageView.java
@@ -318,7 +318,7 @@
/**
* Animates the dot to the given scale, running the optional callback when the animation ends.
*/
- private void animateDotScale(float toScale, @Nullable Runnable after) {
+ public void animateDotScale(float toScale, @Nullable Runnable after) {
mDotIsAnimating = true;
// Don't restart the animation if we're already animating to the given value.
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleOverflow.kt b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleOverflow.kt
index df19757..dc099d9 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleOverflow.kt
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleOverflow.kt
@@ -27,6 +27,7 @@
import android.graphics.drawable.InsetDrawable
import android.util.PathParser
import android.view.LayoutInflater
+import android.view.View.VISIBLE
import android.widget.FrameLayout
import com.android.launcher3.icons.BubbleIconFactory
import com.android.wm.shell.R
@@ -156,7 +157,9 @@
fun setShowDot(show: Boolean) {
showDot = show
- overflowBtn?.updateDotVisibility(true /* animate */)
+ if (overflowBtn?.visibility == VISIBLE) {
+ overflowBtn?.updateDotVisibility(true /* animate */)
+ }
}
/** Creates the expanded view for bubbles showing in the stack view. */
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleStackView.java b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleStackView.java
index c124b53..2241c34 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleStackView.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleStackView.java
@@ -1864,6 +1864,14 @@
: GONE);
}
+ private void updateOverflowDotVisibility(boolean expanding) {
+ if (mBubbleOverflow.showDot()) {
+ mBubbleOverflow.getIconView().animateDotScale(expanding ? 1 : 0f, () -> {
+ mBubbleOverflow.setVisible(expanding ? VISIBLE : GONE);
+ });
+ }
+ }
+
// via BubbleData.Listener
void updateBubble(Bubble bubble) {
animateInFlyoutForBubble(bubble);
@@ -2274,6 +2282,7 @@
if (mIsExpanded && mExpandedBubble.getExpandedView() != null) {
maybeShowManageEdu();
}
+ updateOverflowDotVisibility(true /* expanding */);
} /* after */);
int index;
if (mExpandedBubble != null && BubbleOverflow.KEY.equals(mExpandedBubble.getKey())) {
@@ -2405,11 +2414,15 @@
// since we're about to animate collapsed.
mExpandedAnimationController.notifyPreparingToCollapse();
+ updateOverflowDotVisibility(false /* expanding */);
final Runnable collapseBackToStack = () -> mExpandedAnimationController.collapseBackToStack(
mStackAnimationController
.getStackPositionAlongNearestHorizontalEdge()
/* collapseTo */,
- () -> mBubbleContainer.setActiveController(mStackAnimationController));
+ () -> {
+ mBubbleContainer.setActiveController(mStackAnimationController);
+ updateOverflowVisibility();
+ });
final Runnable after = () -> {
final BubbleViewProvider previouslySelected = mExpandedBubble;
@@ -2424,7 +2437,6 @@
Log.d(TAG, BubbleDebugConfig.formatBubblesString(getBubblesOnScreen(),
mExpandedBubble));
}
- updateOverflowVisibility();
updateZOrder();
updateBadges(true /* setBadgeForCollapsedStack */);
afterExpandedViewAnimation();
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/animation/ExpandedAnimationController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/animation/ExpandedAnimationController.java
index 4d7042b..738c94e 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/animation/ExpandedAnimationController.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/animation/ExpandedAnimationController.java
@@ -34,6 +34,8 @@
import com.android.wm.shell.R;
import com.android.wm.shell.animation.Interpolators;
import com.android.wm.shell.animation.PhysicsAnimator;
+import com.android.wm.shell.bubbles.BadgedImageView;
+import com.android.wm.shell.bubbles.BubbleOverflow;
import com.android.wm.shell.bubbles.BubblePositioner;
import com.android.wm.shell.bubbles.BubbleStackView;
import com.android.wm.shell.common.magnetictarget.MagnetizedObject;
@@ -63,6 +65,12 @@
/** Damping ratio for expand/collapse spring. */
private static final float DAMPING_RATIO_MEDIUM_LOW_BOUNCY = 0.65f;
+ /**
+ * Damping ratio for the overflow bubble spring; this is less bouncy so it doesn't bounce behind
+ * the top bubble when it goes to disappear.
+ */
+ private static final float DAMPING_RATIO_OVERFLOW_BOUNCY = 0.90f;
+
/** Stiffness for the expand/collapse path-following animation. */
private static final int EXPAND_COLLAPSE_ANIM_STIFFNESS = 400;
@@ -274,9 +282,14 @@
// of the screen where the bubble will be stacked.
path.lineTo(stackedX, p.y);
+ // The overflow should animate to the collapse point, so 0 offset.
+ final boolean isOverflow = bubble instanceof BadgedImageView
+ && BubbleOverflow.KEY.equals(((BadgedImageView) bubble).getKey());
+ final float offsetY = isOverflow
+ ? 0
+ : Math.min(index, NUM_VISIBLE_WHEN_RESTING - 1) * mStackOffsetPx;
// Then, draw a line down to the stack position.
- path.lineTo(stackedX, mCollapsePoint.y
- + Math.min(index, NUM_VISIBLE_WHEN_RESTING - 1) * mStackOffsetPx);
+ path.lineTo(stackedX, mCollapsePoint.y + offsetY);
}
// The lead bubble should be the bubble with the longest distance to travel when we're
@@ -505,8 +518,12 @@
@Override
SpringForce getSpringForce(DynamicAnimation.ViewProperty property, View view) {
+ boolean isOverflow = (view instanceof BadgedImageView)
+ && BubbleOverflow.KEY.equals(((BadgedImageView) view).getKey());
return new SpringForce()
- .setDampingRatio(DAMPING_RATIO_MEDIUM_LOW_BOUNCY)
+ .setDampingRatio(isOverflow
+ ? DAMPING_RATIO_OVERFLOW_BOUNCY
+ : DAMPING_RATIO_MEDIUM_LOW_BOUNCY)
.setStiffness(SpringForce.STIFFNESS_LOW);
}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/common/SystemWindows.java b/libs/WindowManager/Shell/src/com/android/wm/shell/common/SystemWindows.java
index 5e42782..e9344ff 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/common/SystemWindows.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/common/SystemWindows.java
@@ -203,7 +203,7 @@
+ "SystemWindow:" + view);
return null;
}
- return root.getFocusGrantToken();
+ return root.getInputTransferToken();
}
private class PerDisplay {
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/dagger/WMShellModule.java b/libs/WindowManager/Shell/src/com/android/wm/shell/dagger/WMShellModule.java
index 11aa0546..5dfba5e 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/dagger/WMShellModule.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/dagger/WMShellModule.java
@@ -494,13 +494,14 @@
ToggleResizeDesktopTaskTransitionHandler toggleResizeDesktopTaskTransitionHandler,
@DynamicOverride DesktopModeTaskRepository desktopModeTaskRepository,
LaunchAdjacentController launchAdjacentController,
+ RecentsTransitionHandler recentsTransitionHandler,
@ShellMainThread ShellExecutor mainExecutor
) {
return new DesktopTasksController(context, shellInit, shellCommandHandler, shellController,
displayController, shellTaskOrganizer, syncQueue, rootTaskDisplayAreaOrganizer,
transitions, enterDesktopTransitionHandler, exitDesktopTransitionHandler,
toggleResizeDesktopTaskTransitionHandler, desktopModeTaskRepository,
- launchAdjacentController, mainExecutor);
+ launchAdjacentController, recentsTransitionHandler, mainExecutor);
}
@WMSingleton
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopTasksController.kt b/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopTasksController.kt
index 09ba4f7..412a5b5 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopTasksController.kt
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopTasksController.kt
@@ -60,6 +60,8 @@
import com.android.wm.shell.desktopmode.DesktopModeTaskRepository.VisibleTasksListener
import com.android.wm.shell.desktopmode.DesktopModeVisualIndicator.TO_DESKTOP_INDICATOR
import com.android.wm.shell.protolog.ShellProtoLogGroup.WM_SHELL_DESKTOP_MODE
+import com.android.wm.shell.recents.RecentsTransitionHandler
+import com.android.wm.shell.recents.RecentsTransitionStateListener
import com.android.wm.shell.splitscreen.SplitScreenController
import com.android.wm.shell.splitscreen.SplitScreenController.EXIT_REASON_ENTER_DESKTOP
import com.android.wm.shell.sysui.ShellCommandHandler
@@ -68,7 +70,6 @@
import com.android.wm.shell.sysui.ShellSharedConstants
import com.android.wm.shell.transition.OneShotRemoteHandler
import com.android.wm.shell.transition.Transitions
-import com.android.wm.shell.transition.Transitions.TransitionHandler
import com.android.wm.shell.util.KtProtoLog
import com.android.wm.shell.windowdecor.DesktopModeWindowDecoration
import com.android.wm.shell.windowdecor.MoveToDesktopAnimator
@@ -93,6 +94,7 @@
ToggleResizeDesktopTaskTransitionHandler,
private val desktopModeTaskRepository: DesktopModeTaskRepository,
private val launchAdjacentController: LaunchAdjacentController,
+ private val recentsTransitionHandler: RecentsTransitionHandler,
@ShellMainThread private val mainExecutor: ShellExecutor
) : RemoteCallable<DesktopTasksController>, Transitions.TransitionHandler {
@@ -119,6 +121,8 @@
com.android.wm.shell.R.dimen.desktop_mode_transition_area_width
)
+ private var recentsAnimationRunning = false
+
// This is public to avoid cyclic dependency; it is set by SplitScreenController
lateinit var splitScreenController: SplitScreenController
@@ -139,6 +143,19 @@
)
transitions.addHandler(this)
desktopModeTaskRepository.addVisibleTasksListener(taskVisibilityListener, mainExecutor)
+
+ recentsTransitionHandler.addTransitionStateListener(
+ object : RecentsTransitionStateListener {
+ override fun onAnimationStateChanged(running: Boolean) {
+ KtProtoLog.v(
+ WM_SHELL_DESKTOP_MODE,
+ "DesktopTasksController: recents animation state changed running=%b",
+ running
+ )
+ recentsAnimationRunning = running
+ }
+ }
+ )
}
/** Show all tasks, that are part of the desktop, on top of launcher */
@@ -644,6 +661,10 @@
val triggerTask = request.triggerTask
val shouldHandleRequest =
when {
+ recentsAnimationRunning -> {
+ reason = "recents animation is running"
+ false
+ }
// Only handle open or to front transitions
request.type != TRANSIT_OPEN && request.type != TRANSIT_TO_FRONT -> {
reason = "transition type not handled (${request.type})"
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/recents/RecentsTransitionHandler.java b/libs/WindowManager/Shell/src/com/android/wm/shell/recents/RecentsTransitionHandler.java
index ead2f9c..d31476c 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/recents/RecentsTransitionHandler.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/recents/RecentsTransitionHandler.java
@@ -54,6 +54,7 @@
import android.window.WindowContainerTransaction;
import com.android.internal.annotations.VisibleForTesting;
+import com.android.internal.os.IResultReceiver;
import com.android.internal.protolog.common.ProtoLog;
import com.android.wm.shell.common.ShellExecutor;
import com.android.wm.shell.protolog.ShellProtoLogGroup;
@@ -279,7 +280,7 @@
mDeathHandler = () -> {
ProtoLog.v(ShellProtoLogGroup.WM_SHELL_RECENTS_TRANSITION,
"[%d] RecentsController.DeathRecipient: binder died", mInstanceId);
- finish(mWillFinishToHome, false /* leaveHint */);
+ finish(mWillFinishToHome, false /* leaveHint */, null /* finishCb */);
};
try {
mListener.asBinder().linkToDeath(mDeathHandler, 0 /* flags */);
@@ -313,7 +314,7 @@
}
}
if (mFinishCB != null) {
- finishInner(toHome, false /* userLeave */);
+ finishInner(toHome, false /* userLeave */, null /* finishCb */);
} else {
cleanUp();
}
@@ -670,7 +671,8 @@
// now and let it do its animation (since recents is going to be occluded).
sendCancelWithSnapshots();
mExecutor.executeDelayed(
- () -> finishInner(true /* toHome */, false /* userLeaveHint */), 0);
+ () -> finishInner(true /* toHome */, false /* userLeaveHint */,
+ null /* finishCb */), 0);
return;
}
if (recentsOpening != null) {
@@ -899,11 +901,12 @@
@Override
@SuppressLint("NewApi")
- public void finish(boolean toHome, boolean sendUserLeaveHint) {
- mExecutor.execute(() -> finishInner(toHome, sendUserLeaveHint));
+ public void finish(boolean toHome, boolean sendUserLeaveHint, IResultReceiver finishCb) {
+ mExecutor.execute(() -> finishInner(toHome, sendUserLeaveHint, finishCb));
}
- private void finishInner(boolean toHome, boolean sendUserLeaveHint) {
+ private void finishInner(boolean toHome, boolean sendUserLeaveHint,
+ IResultReceiver runnerFinishCb) {
if (mFinishCB == null) {
Slog.e(TAG, "Duplicate call to finish");
return;
@@ -993,6 +996,16 @@
}
cleanUp();
finishCB.onTransitionFinished(wct.isEmpty() ? null : wct);
+ if (runnerFinishCb != null) {
+ try {
+ ProtoLog.v(ShellProtoLogGroup.WM_SHELL_RECENTS_TRANSITION,
+ "[%d] RecentsController.finishInner: calling finish callback",
+ mInstanceId);
+ runnerFinishCb.send(0, null);
+ } catch (RemoteException e) {
+ Slog.e(TAG, "Failed to report transition finished", e);
+ }
+ }
}
@Override
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/transition/DefaultMixedHandler.java b/libs/WindowManager/Shell/src/com/android/wm/shell/transition/DefaultMixedHandler.java
index 83dc7fa..e828eed 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/transition/DefaultMixedHandler.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/transition/DefaultMixedHandler.java
@@ -23,6 +23,7 @@
import static android.view.WindowManager.TRANSIT_CHANGE;
import static android.view.WindowManager.TRANSIT_TO_BACK;
import static android.window.TransitionInfo.FLAG_IS_WALLPAPER;
+
import static com.android.wm.shell.common.split.SplitScreenConstants.FLAG_IS_DIVIDER_BAR;
import static com.android.wm.shell.common.split.SplitScreenConstants.SPLIT_POSITION_UNDEFINED;
import static com.android.wm.shell.pip.PipAnimationController.ANIM_TYPE_ALPHA;
@@ -693,9 +694,19 @@
@NonNull SurfaceControl.Transaction startTransaction,
@NonNull SurfaceControl.Transaction finishTransaction,
@NonNull Transitions.TransitionFinishCallback finishCallback) {
+ Transitions.TransitionFinishCallback finishCB = wct -> {
+ mixed.mInFlightSubAnimations--;
+ if (mixed.mInFlightSubAnimations == 0) {
+ mActiveTransitions.remove(mixed);
+ finishCallback.onTransitionFinished(wct);
+ }
+ };
+
+ mixed.mInFlightSubAnimations++;
boolean consumed = mRecentsHandler.startAnimation(
- mixed.mTransition, info, startTransaction, finishTransaction, finishCallback);
+ mixed.mTransition, info, startTransaction, finishTransaction, finishCB);
if (!consumed) {
+ mixed.mInFlightSubAnimations--;
return false;
}
if (mDesktopTasksController != null) {
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/transition/DefaultTransitionHandler.java b/libs/WindowManager/Shell/src/com/android/wm/shell/transition/DefaultTransitionHandler.java
index e0635ac..de03f58 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/transition/DefaultTransitionHandler.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/transition/DefaultTransitionHandler.java
@@ -322,7 +322,6 @@
final Runnable onAnimFinish = () -> {
if (!animations.isEmpty()) return;
mAnimations.remove(transition);
- info.releaseAllSurfaces();
finishCallback.onTransitionFinished(null /* wct */);
};
diff --git a/libs/WindowManager/Shell/tests/unittest/Android.bp b/libs/WindowManager/Shell/tests/unittest/Android.bp
index 54f9498..d09a90c 100644
--- a/libs/WindowManager/Shell/tests/unittest/Android.bp
+++ b/libs/WindowManager/Shell/tests/unittest/Android.bp
@@ -45,7 +45,7 @@
"kotlinx-coroutines-core",
"mockito-kotlin2",
"mockito-target-extended-minus-junit4",
- "truth-prebuilt",
+ "truth",
"testables",
"platform-test-annotations",
"servicestests-utils",
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DesktopTasksControllerTest.kt b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DesktopTasksControllerTest.kt
index dea1617..ebcb640 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DesktopTasksControllerTest.kt
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DesktopTasksControllerTest.kt
@@ -54,6 +54,8 @@
import com.android.wm.shell.desktopmode.DesktopTestHelpers.Companion.createFullscreenTask
import com.android.wm.shell.desktopmode.DesktopTestHelpers.Companion.createHomeTask
import com.android.wm.shell.desktopmode.DesktopTestHelpers.Companion.createSplitScreenTask
+import com.android.wm.shell.recents.RecentsTransitionHandler
+import com.android.wm.shell.recents.RecentsTransitionStateListener
import com.android.wm.shell.splitscreen.SplitScreenController
import com.android.wm.shell.sysui.ShellCommandHandler
import com.android.wm.shell.sysui.ShellController
@@ -101,11 +103,13 @@
@Mock lateinit var launchAdjacentController: LaunchAdjacentController
@Mock lateinit var desktopModeWindowDecoration: DesktopModeWindowDecoration
@Mock lateinit var splitScreenController: SplitScreenController
+ @Mock lateinit var recentsTransitionHandler: RecentsTransitionHandler
private lateinit var mockitoSession: StaticMockitoSession
private lateinit var controller: DesktopTasksController
private lateinit var shellInit: ShellInit
private lateinit var desktopModeTaskRepository: DesktopModeTaskRepository
+ private lateinit var recentsTransitionStateListener: RecentsTransitionStateListener
private val shellExecutor = TestShellExecutor()
// Mock running tasks are registered here so we can get the list from mock shell task organizer
@@ -126,6 +130,10 @@
controller.splitScreenController = splitScreenController
shellInit.init()
+
+ val captor = ArgumentCaptor.forClass(RecentsTransitionStateListener::class.java)
+ verify(recentsTransitionHandler).addTransitionStateListener(captor.capture())
+ recentsTransitionStateListener = captor.value
}
private fun createController(): DesktopTasksController {
@@ -144,6 +152,7 @@
mToggleResizeDesktopTaskTransitionHandler,
desktopModeTaskRepository,
launchAdjacentController,
+ recentsTransitionHandler,
shellExecutor
)
}
@@ -355,7 +364,7 @@
@Test
fun moveToDesktop_splitTaskExitsSplit() {
- var task = setUpSplitScreenTask()
+ val task = setUpSplitScreenTask()
controller.moveToDesktop(desktopModeWindowDecoration, task)
val wct = getLatestMoveToDesktopWct()
assertThat(wct.changes[task.token.asBinder()]?.windowingMode)
@@ -367,7 +376,7 @@
@Test
fun moveToDesktop_fullscreenTaskDoesNotExitSplit() {
- var task = setUpFullscreenTask()
+ val task = setUpFullscreenTask()
controller.moveToDesktop(desktopModeWindowDecoration, task)
val wct = getLatestMoveToDesktopWct()
assertThat(wct.changes[task.token.asBinder()]?.windowingMode)
@@ -666,6 +675,20 @@
}
@Test
+ fun handleRequest_recentsAnimationRunning_returnNull() {
+ // Set up a visible freeform task so a fullscreen task should be converted to freeform
+ val freeformTask = setUpFreeformTask()
+ markTaskVisible(freeformTask)
+
+ // Mark recents animation running
+ recentsTransitionStateListener.onAnimationStateChanged(true)
+
+ // Open a fullscreen task, check that it does not result in a WCT with changes to it
+ val fullscreenTask = createFullscreenTask()
+ assertThat(controller.handleRequest(Binder(), createTransition(fullscreenTask))).isNull()
+ }
+
+ @Test
fun stashDesktopApps_stateUpdates() {
whenever(DesktopModeStatus.isStashingEnabled()).thenReturn(true)
diff --git a/libs/dream/lowlight/tests/Android.bp b/libs/dream/lowlight/tests/Android.bp
index 64b53cb..4dafd0a 100644
--- a/libs/dream/lowlight/tests/Android.bp
+++ b/libs/dream/lowlight/tests/Android.bp
@@ -34,7 +34,7 @@
"mockito-target-extended-minus-junit4",
"platform-test-annotations",
"testables",
- "truth-prebuilt",
+ "truth",
],
libs: [
"android.test.mock",
diff --git a/libs/securebox/tests/Android.bp b/libs/securebox/tests/Android.bp
index 7df546a..80b501d 100644
--- a/libs/securebox/tests/Android.bp
+++ b/libs/securebox/tests/Android.bp
@@ -32,7 +32,7 @@
"platform-test-annotations",
"testables",
"testng",
- "truth-prebuilt",
+ "truth",
],
libs: [
"android.test.mock",
diff --git a/media/tests/MediaFrameworkTest/Android.bp b/media/tests/MediaFrameworkTest/Android.bp
index ca20225e..bdd7afe 100644
--- a/media/tests/MediaFrameworkTest/Android.bp
+++ b/media/tests/MediaFrameworkTest/Android.bp
@@ -22,7 +22,7 @@
"android-ex-camera2",
"testables",
"testng",
- "truth-prebuilt",
+ "truth",
],
jni_libs: [
"libdexmakerjvmtiagent",
diff --git a/media/tests/MediaRouter/Android.bp b/media/tests/MediaRouter/Android.bp
index 4cccf89..61b18c8 100644
--- a/media/tests/MediaRouter/Android.bp
+++ b/media/tests/MediaRouter/Android.bp
@@ -24,7 +24,7 @@
"compatibility-device-util-axt",
"mockito-target-minus-junit4",
"testng",
- "truth-prebuilt",
+ "truth",
],
test_suites: ["general-tests"],
platform_apis: true,
diff --git a/media/tests/projection/Android.bp b/media/tests/projection/Android.bp
index e313c46..48cd8b6 100644
--- a/media/tests/projection/Android.bp
+++ b/media/tests/projection/Android.bp
@@ -30,7 +30,7 @@
"platform-test-annotations",
"testng",
"testables",
- "truth-prebuilt",
+ "truth",
"platform-compat-test-rules",
],
diff --git a/packages/CredentialManager/src/com/android/credentialmanager/autofill/CredentialAutofillService.kt b/packages/CredentialManager/src/com/android/credentialmanager/autofill/CredentialAutofillService.kt
index ba88484..2318bb9 100644
--- a/packages/CredentialManager/src/com/android/credentialmanager/autofill/CredentialAutofillService.kt
+++ b/packages/CredentialManager/src/com/android/credentialmanager/autofill/CredentialAutofillService.kt
@@ -18,21 +18,23 @@
import android.app.assist.AssistStructure
import android.content.Context
-import android.credentials.GetCredentialRequest
import android.credentials.CredentialManager
-import android.credentials.GetCandidateCredentialsResponse
import android.credentials.CredentialOption
import android.credentials.GetCandidateCredentialsException
+import android.credentials.GetCandidateCredentialsResponse
+import android.credentials.GetCredentialRequest
import android.os.Bundle
import android.os.CancellationSignal
import android.os.OutcomeReceiver
-import android.service.autofill.FillRequest
import android.service.autofill.AutofillService
-import android.service.autofill.FillResponse
import android.service.autofill.FillCallback
-import android.service.autofill.SaveRequest
+import android.service.autofill.FillRequest
+import android.service.autofill.FillResponse
import android.service.autofill.SaveCallback
+import android.service.autofill.SaveRequest
+import android.service.credentials.CredentialProviderService
import android.util.Log
+import android.view.autofill.AutofillId
import org.json.JSONObject
import java.util.concurrent.Executors
@@ -129,27 +131,31 @@
}
private fun traverseNode(
- viewNode: AssistStructure.ViewNode?,
+ viewNode: AssistStructure.ViewNode,
cmRequests: MutableList<CredentialOption>
) {
- val options = getCredentialOptionsFromViewNode(viewNode)
- cmRequests.addAll(options)
+ viewNode.autofillId?.let {
+ val options = getCredentialOptionsFromViewNode(viewNode, it)
+ cmRequests.addAll(options)
+ }
- val children: List<AssistStructure.ViewNode>? =
- viewNode?.run {
+ val children: List<AssistStructure.ViewNode> =
+ viewNode.run {
(0 until childCount).map { getChildAt(it) }
}
- children?.forEach { childNode: AssistStructure.ViewNode ->
+ children.forEach { childNode: AssistStructure.ViewNode ->
traverseNode(childNode, cmRequests)
}
}
- private fun getCredentialOptionsFromViewNode(viewNode: AssistStructure.ViewNode?):
- List<CredentialOption> {
+ private fun getCredentialOptionsFromViewNode(
+ viewNode: AssistStructure.ViewNode,
+ autofillId: AutofillId
+ ): List<CredentialOption> {
// TODO(b/293945193) Replace with isCredential check from viewNode
val credentialHints: MutableList<String> = mutableListOf()
- if (viewNode != null && viewNode.autofillHints != null) {
+ if (viewNode.autofillHints != null) {
for (hint in viewNode.autofillHints!!) {
if (hint.startsWith(CRED_HINT_PREFIX)) {
credentialHints.add(hint.substringAfter(CRED_HINT_PREFIX))
@@ -159,12 +165,14 @@
val credentialOptions: MutableList<CredentialOption> = mutableListOf()
for (credentialHint in credentialHints) {
- convertJsonToCredentialOption(credentialHint).let { credentialOptions.addAll(it) }
+ convertJsonToCredentialOption(credentialHint, autofillId)
+ .let { credentialOptions.addAll(it) }
}
return credentialOptions
}
- private fun convertJsonToCredentialOption(jsonString: String): List<CredentialOption> {
+ private fun convertJsonToCredentialOption(jsonString: String, autofillId: AutofillId):
+ List<CredentialOption> {
// TODO(b/302000646) Move this logic to jetpack so that is consistent
// with building the json
val credentialOptions: MutableList<CredentialOption> = mutableListOf()
@@ -173,11 +181,14 @@
val options = json.getJSONArray(CRED_OPTIONS_KEY)
for (i in 0 until options.length()) {
val option = options.getJSONObject(i)
-
+ val candidateBundle = convertJsonToBundle(option.getJSONObject(CANDIDATE_DATA_KEY))
+ candidateBundle.putParcelable(
+ CredentialProviderService.EXTRA_AUTOFILL_ID,
+ autofillId)
credentialOptions.add(CredentialOption(
option.getString(TYPE_KEY),
convertJsonToBundle(option.getJSONObject(REQUEST_DATA_KEY)),
- convertJsonToBundle(option.getJSONObject(CANDIDATE_DATA_KEY)),
+ candidateBundle,
option.getBoolean(SYS_PROVIDER_REQ_KEY),
))
}
diff --git a/packages/ExternalStorageProvider/tests/Android.bp b/packages/ExternalStorageProvider/tests/Android.bp
index 633f186..86c62ef 100644
--- a/packages/ExternalStorageProvider/tests/Android.bp
+++ b/packages/ExternalStorageProvider/tests/Android.bp
@@ -25,7 +25,7 @@
static_libs: [
"androidx.test.rules",
"mockito-target",
- "truth-prebuilt",
+ "truth",
],
certificate: "platform",
diff --git a/packages/FusedLocation/Android.bp b/packages/FusedLocation/Android.bp
index 64b4c54..61a8270 100644
--- a/packages/FusedLocation/Android.bp
+++ b/packages/FusedLocation/Android.bp
@@ -47,7 +47,7 @@
test_config: "test/AndroidTest.xml",
srcs: [
"test/src/**/*.java",
- "src/**/*.java", // include real sources because we're forced to test this directly
+ "src/**/*.java", // include real sources because we're forced to test this directly
],
libs: [
"android.test.base",
@@ -60,9 +60,9 @@
"androidx.test.ext.junit",
"androidx.test.ext.truth",
"mockito-target-minus-junit4",
- "truth-prebuilt",
+ "truth",
],
platform_apis: true,
certificate: "platform",
- test_suites: ["device-tests"]
+ test_suites: ["device-tests"],
}
diff --git a/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/widget/editor/SettingsTextFieldPassword.kt b/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/widget/editor/SettingsTextFieldPassword.kt
index d0a6188..0757df3 100644
--- a/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/widget/editor/SettingsTextFieldPassword.kt
+++ b/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/widget/editor/SettingsTextFieldPassword.kt
@@ -29,8 +29,8 @@
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
-import androidx.compose.runtime.remember
import androidx.compose.runtime.mutableStateOf
+import androidx.compose.runtime.remember
import androidx.compose.runtime.setValue
import androidx.compose.ui.Modifier
import androidx.compose.ui.platform.testTag
@@ -46,6 +46,7 @@
fun SettingsTextFieldPassword(
value: String,
label: String,
+ enabled: Boolean = true,
onTextChange: (String) -> Unit,
) {
var visibility by remember { mutableStateOf(false) }
@@ -60,6 +61,7 @@
keyboardType = KeyboardType.Password,
imeAction = ImeAction.Send
),
+ enabled = enabled,
trailingIcon = {
Icon(
imageVector = if (visibility) Icons.Outlined.VisibilityOff
diff --git a/packages/SettingsLib/Spa/testutils/Android.bp b/packages/SettingsLib/Spa/testutils/Android.bp
index 4031cd7..639d1a7 100644
--- a/packages/SettingsLib/Spa/testutils/Android.bp
+++ b/packages/SettingsLib/Spa/testutils/Android.bp
@@ -31,7 +31,7 @@
"androidx.compose.ui_ui-test-manifest",
"androidx.lifecycle_lifecycle-runtime-testing",
"mockito-kotlin2",
- "truth-prebuilt",
+ "truth",
],
kotlincflags: [
"-Xjvm-default=all",
diff --git a/packages/SettingsLib/src/com/android/settingslib/enterprise/SupervisedDeviceActionDisabledByAdminController.java b/packages/SettingsLib/src/com/android/settingslib/enterprise/SupervisedDeviceActionDisabledByAdminController.java
index 815293e9..09f34b3 100644
--- a/packages/SettingsLib/src/com/android/settingslib/enterprise/SupervisedDeviceActionDisabledByAdminController.java
+++ b/packages/SettingsLib/src/com/android/settingslib/enterprise/SupervisedDeviceActionDisabledByAdminController.java
@@ -16,17 +16,20 @@
package com.android.settingslib.enterprise;
+
import android.content.ComponentName;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.net.Uri;
import android.provider.Settings;
-import android.util.Log;
+import android.text.TextUtils;
+
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
import com.android.settingslib.RestrictedLockUtils;
-import org.jetbrains.annotations.Nullable;
final class SupervisedDeviceActionDisabledByAdminController
extends BaseActionDisabledByAdminController {
@@ -57,8 +60,13 @@
@Nullable
@Override
- public DialogInterface.OnClickListener getPositiveButtonListener(Context context,
- RestrictedLockUtils.EnforcedAdmin enforcedAdmin) {
+ public DialogInterface.OnClickListener getPositiveButtonListener(@NonNull Context context,
+ @NonNull RestrictedLockUtils.EnforcedAdmin enforcedAdmin) {
+ if (enforcedAdmin.component == null
+ || TextUtils.isEmpty(enforcedAdmin.component.getPackageName())) {
+ return null;
+ }
+
final Intent intent = new Intent(Settings.ACTION_MANAGE_SUPERVISOR_RESTRICTED_SETTING)
.setData(new Uri.Builder()
.scheme("policy")
@@ -72,7 +80,6 @@
return null;
}
return (dialog, which) -> {
- Log.d(TAG, "Positive button clicked, component: " + enforcedAdmin.component);
context.startActivity(intent);
};
}
diff --git a/packages/SettingsLib/tests/integ/Android.bp b/packages/SettingsLib/tests/integ/Android.bp
index b03c43c..4b4caf5 100644
--- a/packages/SettingsLib/tests/integ/Android.bp
+++ b/packages/SettingsLib/tests/integ/Android.bp
@@ -52,7 +52,7 @@
"flag-junit",
"mockito-target-minus-junit4",
"platform-test-annotations",
- "truth-prebuilt",
+ "truth",
"SettingsLibDeviceStateRotationLock",
"SettingsLibSettingsSpinner",
"SettingsLibUsageProgressBarPreference",
diff --git a/packages/SettingsLib/tests/robotests/Android.bp b/packages/SettingsLib/tests/robotests/Android.bp
index dd9cb9c..2d875cf 100644
--- a/packages/SettingsLib/tests/robotests/Android.bp
+++ b/packages/SettingsLib/tests/robotests/Android.bp
@@ -96,6 +96,6 @@
libs: [
"Robolectric_all-target_upstream",
"mockito-robolectric-prebuilt",
- "truth-prebuilt",
+ "truth",
],
}
diff --git a/packages/SettingsLib/tests/unit/Android.bp b/packages/SettingsLib/tests/unit/Android.bp
index 19ab1c6..6d6e2ff 100644
--- a/packages/SettingsLib/tests/unit/Android.bp
+++ b/packages/SettingsLib/tests/unit/Android.bp
@@ -31,6 +31,6 @@
"SettingsLib",
"androidx.test.ext.junit",
"androidx.test.runner",
- "truth-prebuilt",
+ "truth",
],
}
diff --git a/packages/SettingsProvider/Android.bp b/packages/SettingsProvider/Android.bp
index 92ebe09..f4ca260 100644
--- a/packages/SettingsProvider/Android.bp
+++ b/packages/SettingsProvider/Android.bp
@@ -64,7 +64,7 @@
"SettingsLibDeviceStateRotationLock",
"SettingsLibDisplayUtils",
"platform-test-annotations",
- "truth-prebuilt",
+ "truth",
],
libs: [
"android.test.base",
diff --git a/packages/SettingsProvider/src/android/provider/settings/backup/SecureSettings.java b/packages/SettingsProvider/src/android/provider/settings/backup/SecureSettings.java
index 91d2d1b..ba4ad36 100644
--- a/packages/SettingsProvider/src/android/provider/settings/backup/SecureSettings.java
+++ b/packages/SettingsProvider/src/android/provider/settings/backup/SecureSettings.java
@@ -218,6 +218,7 @@
Settings.Secure.ACCESSIBILITY_FORCE_INVERT_COLOR_ENABLED,
Settings.Secure.ACCESSIBILITY_MAGNIFICATION_ALWAYS_ON_ENABLED,
Settings.Secure.ACCESSIBILITY_MAGNIFICATION_JOYSTICK_ENABLED,
+ Settings.Secure.ACCESSIBILITY_MAGNIFICATION_GESTURE,
Settings.Secure.ODI_CAPTIONS_VOLUME_UI_ENABLED,
Settings.Secure.NOTIFICATION_BUBBLES,
Settings.Secure.LOCATION_TIME_ZONE_DETECTION_ENABLED,
diff --git a/packages/SettingsProvider/src/android/provider/settings/validators/SecureSettingsValidators.java b/packages/SettingsProvider/src/android/provider/settings/validators/SecureSettingsValidators.java
index bec1447..19fde75 100644
--- a/packages/SettingsProvider/src/android/provider/settings/validators/SecureSettingsValidators.java
+++ b/packages/SettingsProvider/src/android/provider/settings/validators/SecureSettingsValidators.java
@@ -308,6 +308,10 @@
VALIDATORS.put(Secure.ACCESSIBILITY_MAGNIFICATION_FOLLOW_TYPING_ENABLED, BOOLEAN_VALIDATOR);
VALIDATORS.put(Secure.ACCESSIBILITY_MAGNIFICATION_ALWAYS_ON_ENABLED, BOOLEAN_VALIDATOR);
VALIDATORS.put(Secure.ACCESSIBILITY_MAGNIFICATION_JOYSTICK_ENABLED, BOOLEAN_VALIDATOR);
+ VALIDATORS.put(Secure.ACCESSIBILITY_MAGNIFICATION_GESTURE,
+ new InclusiveIntegerRangeValidator(
+ Secure.ACCESSIBILITY_MAGNIFICATION_GESTURE_NONE,
+ Secure.ACCESSIBILITY_MAGNIFICATION_GESTURE_ALL));
VALIDATORS.put(
Secure.ACCESSIBILITY_BUTTON_TARGETS,
ACCESSIBILITY_SHORTCUT_TARGET_LIST_VALIDATOR);
diff --git a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java
index 3c8d4bc..f06b31c 100644
--- a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java
+++ b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java
@@ -1850,6 +1850,10 @@
SecureSettingsProto.Accessibility
.ACCESSIBILITY_MAGNIFICATION_JOYSTICK_ENABLED);
dumpSetting(s, p,
+ Settings.Secure.ACCESSIBILITY_MAGNIFICATION_GESTURE,
+ SecureSettingsProto.Accessibility
+ .ACCESSIBILITY_MAGNIFICATION_GESTURE);
+ dumpSetting(s, p,
Settings.Secure.HEARING_AID_RINGTONE_ROUTING,
SecureSettingsProto.Accessibility.HEARING_AID_RINGTONE_ROUTING);
dumpSetting(s, p,
diff --git a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java
index 40f7ba6..34d3d44 100644
--- a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java
+++ b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java
@@ -2054,12 +2054,14 @@
final Uri ringtoneUri = Uri.parse(value);
// Stream selected ringtone into cache, so it's available for playback
// when CE storage is still locked
- try (InputStream in = openRingtone(getContext(), ringtoneUri);
- OutputStream out = new FileOutputStream(cacheFile)) {
- FileUtils.copy(in, out);
- } catch (IOException e) {
- Slog.w(LOG_TAG, "Failed to cache ringtone: " + e);
- }
+ Binder.withCleanCallingIdentity(() -> {
+ try (InputStream in = openRingtone(getContext(), ringtoneUri);
+ OutputStream out = new FileOutputStream(cacheFile)) {
+ FileUtils.copy(in, out);
+ } catch (IOException e) {
+ Slog.w(LOG_TAG, "Failed to cache ringtone: " + e);
+ }
+ });
}
return true;
}
diff --git a/packages/SystemUI/Android.bp b/packages/SystemUI/Android.bp
index ee05f2d..e40fcb2 100644
--- a/packages/SystemUI/Android.bp
+++ b/packages/SystemUI/Android.bp
@@ -319,6 +319,8 @@
"tests/src/com/android/systemui/statusbar/pipeline/wifi/data/repository/prod/WifiRepositoryImplTest.kt",
"tests/src/com/android/systemui/statusbar/pipeline/wifi/domain/interactor/WifiInteractorImplTest.kt",
"tests/src/com/android/systemui/statusbar/pipeline/wifi/ui/viewmodel/WifiViewModelTest.kt",
+ "tests/src/com/android/systemui/statusbar/pipeline/mobile/domain/interactor/FakeMobileIconsInteractor.kt",
+ "tests/src/com/android/systemui/statusbar/pipeline/mobile/domain/interactor/FakeMobileIconInteractor.kt",
/* Bouncer UI tests */
"tests/src/com/android/keyguard/KeyguardPasswordViewControllerTest.kt",
@@ -365,6 +367,42 @@
"tests/src/com/android/systemui/qs/pipeline/shared/TileSpecTest.kt",
"tests/src/com/android/systemui/qs/tiles/base/**/*.kt",
"tests/src/com/android/systemui/qs/tiles/viewmodel/**/*.kt",
+
+ /* Authentication */
+ "tests/src/com/android/systemui/authentication/data/repository/AuthenticationRepositoryTest.kt",
+ "tests/src/com/android/systemui/authentication/domain/interactor/AuthenticationInteractorTest.kt",
+
+ /* Device entry */
+ "tests/src/com/android/systemui/deviceentry/data/repository/DeviceEntryRepositoryTest.kt",
+ "tests/src/com/android/systemui/deviceentry/domain/interactor/DeviceEntryInteractorTest.kt",
+
+ /* Bouncer scene */
+ "tests/src/com/android/systemui/bouncer/domain/interactor/BouncerInteractorTest.kt",
+ "tests/src/com/android/systemui/bouncer/ui/viewmodel/AuthMethodBouncerViewModelTest.kt",
+ "tests/src/com/android/systemui/bouncer/ui/viewmodel/BouncerViewModelTest.kt",
+ "tests/src/com/android/systemui/bouncer/ui/viewmodel/PasswordBouncerViewModelTest.kt",
+ "tests/src/com/android/systemui/bouncer/ui/viewmodel/PatternBouncerViewModelTest.kt",
+ "tests/src/com/android/systemui/bouncer/ui/viewmodel/PinBouncerViewModelTest.kt",
+ "tests/src/com/android/systemui/bouncer/ui/viewmodel/PinInputViewModelTest.kt",
+
+ /* Lockscreen scene */
+ "tests/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenSceneViewModelTest.kt",
+
+ /* Shade scene */
+ "tests/src/com/android/systemui/shade/ui/viewmodel/ShadeSceneViewModelTest.kt",
+ "tests/src/com/android/systemui/shade/ui/viewmodel/ShadeHeaderViewModelTest.kt",
+
+ /* Quick Settings scene */
+ "tests/src/com/android/systemui/qs/ui/viewmodel/QuickSettingsSceneViewModelTest.kt",
+
+ /* Flexiglass / Scene framework tests */
+ "tests/src/com/android/systemui/scene/SceneFrameworkIntegrationTest.kt",
+ "tests/src/com/android/systemui/scene/data/repository/SceneContainerRepositoryTest.kt",
+ "tests/src/com/android/systemui/scene/data/repository/WindowRootViewVisibilityRepositoryTest.kt",
+ "tests/src/com/android/systemui/scene/domain/interactor/SceneInteractorTest.kt",
+ "tests/src/com/android/systemui/scene/domain/interactor/WindowRootViewVisibilityInteractorTest.kt",
+ "tests/src/com/android/systemui/scene/domain/startable/SceneContainerStartableTest.kt",
+ "tests/src/com/android/systemui/scene/ui/viewmodel/SceneContainerViewModelTest.kt",
],
path: "tests/src",
}
@@ -428,7 +466,7 @@
"hamcrest-library",
"androidx.test.rules",
"testables",
- "truth-prebuilt",
+ "truth",
"monet",
"libmonet",
"dagger2",
@@ -545,7 +583,7 @@
"android.test.runner",
"android.test.base",
"android.test.mock",
- "truth-prebuilt",
+ "truth",
],
upstream: true,
diff --git a/packages/SystemUI/accessibility/accessibilitymenu/src/com/android/systemui/accessibility/accessibilitymenu/AccessibilityMenuService.java b/packages/SystemUI/accessibility/accessibilitymenu/src/com/android/systemui/accessibility/accessibilitymenu/AccessibilityMenuService.java
index 008732e..96e1e3f 100644
--- a/packages/SystemUI/accessibility/accessibilitymenu/src/com/android/systemui/accessibility/accessibilitymenu/AccessibilityMenuService.java
+++ b/packages/SystemUI/accessibility/accessibilitymenu/src/com/android/systemui/accessibility/accessibilitymenu/AccessibilityMenuService.java
@@ -63,6 +63,7 @@
private static final String TAG = "A11yMenuService";
private static final long BUFFER_MILLISECONDS_TO_PREVENT_UPDATE_FAILURE = 100L;
+ private static final long TAKE_SCREENSHOT_DELAY_MS = 100L;
private static final int BRIGHTNESS_UP_INCREMENT_GAMMA =
(int) Math.ceil(BrightnessUtils.GAMMA_SPACE_MAX * 0.11f);
@@ -301,7 +302,14 @@
} else if (viewTag == ShortcutId.ID_NOTIFICATION_VALUE.ordinal()) {
performGlobalActionInternal(GLOBAL_ACTION_NOTIFICATIONS);
} else if (viewTag == ShortcutId.ID_SCREENSHOT_VALUE.ordinal()) {
- performGlobalActionInternal(GLOBAL_ACTION_TAKE_SCREENSHOT);
+ if (Flags.a11yMenuHideBeforeTakingAction()) {
+ // Delay before taking a screenshot to give time for the UI to close.
+ mHandler.postDelayed(
+ () -> performGlobalActionInternal(GLOBAL_ACTION_TAKE_SCREENSHOT),
+ TAKE_SCREENSHOT_DELAY_MS);
+ } else {
+ performGlobalActionInternal(GLOBAL_ACTION_TAKE_SCREENSHOT);
+ }
}
if (!Flags.a11yMenuHideBeforeTakingAction()) {
diff --git a/packages/SystemUI/accessibility/accessibilitymenu/tests/Android.bp b/packages/SystemUI/accessibility/accessibilitymenu/tests/Android.bp
index 538ecb3..3fc351c 100644
--- a/packages/SystemUI/accessibility/accessibilitymenu/tests/Android.bp
+++ b/packages/SystemUI/accessibility/accessibilitymenu/tests/Android.bp
@@ -32,7 +32,7 @@
"androidx.test.ext.junit",
"compatibility-device-util-axt",
"platform-test-annotations",
- "truth-prebuilt",
+ "truth",
],
srcs: [
"src/**/*.java",
diff --git a/packages/SystemUI/aconfig/systemui.aconfig b/packages/SystemUI/aconfig/systemui.aconfig
index 437f8af..18117a8 100644
--- a/packages/SystemUI/aconfig/systemui.aconfig
+++ b/packages/SystemUI/aconfig/systemui.aconfig
@@ -13,3 +13,11 @@
description: "Enables all the sysui classic flags that are marked as being in teamfood"
bug: "302578396"
}
+
+flag {
+ name: "notifications_footer_view_refactor"
+ namespace: "systemui"
+ description: "Enables the refactored version of the footer view in the notification shade "
+ "(containing the \"Clear all\" button). Should not bring any behavior changes"
+ bug: "293167744"
+}
diff --git a/packages/SystemUI/animation/src/com/android/systemui/animation/ActivityLaunchAnimator.kt b/packages/SystemUI/animation/src/com/android/systemui/animation/ActivityLaunchAnimator.kt
index 0f2e4ba..4aac279 100644
--- a/packages/SystemUI/animation/src/com/android/systemui/animation/ActivityLaunchAnimator.kt
+++ b/packages/SystemUI/animation/src/com/android/systemui/animation/ActivityLaunchAnimator.kt
@@ -39,6 +39,7 @@
import android.view.WindowManager
import android.view.animation.Interpolator
import android.view.animation.PathInterpolator
+import androidx.annotation.AnyThread
import androidx.annotation.BinderThread
import androidx.annotation.UiThread
import com.android.app.animation.Interpolators
@@ -149,6 +150,10 @@
override fun onLaunchAnimationProgress(linearProgress: Float) {
listeners.forEach { it.onLaunchAnimationProgress(linearProgress) }
}
+
+ override fun onLaunchAnimationCancelled() {
+ listeners.forEach { it.onLaunchAnimationCancelled() }
+ }
}
/**
@@ -191,6 +196,7 @@
"ActivityLaunchAnimator.callback must be set before using this animator"
)
val runner = createRunner(controller)
+ val runnerDelegate = runner.delegate!!
val hideKeyguardWithAnimation = callback.isOnKeyguard() && !showOverLockscreen
// Pass the RemoteAnimationAdapter to the intent starter only if we are not hiding the
@@ -241,12 +247,15 @@
// If we expect an animation, post a timeout to cancel it in case the remote animation is
// never started.
if (willAnimate) {
- runner.delegate.postTimeout()
+ runnerDelegate.postTimeout()
// Hide the keyguard using the launch animation instead of the default unlock animation.
if (hideKeyguardWithAnimation) {
callback.hideKeyguardWithAnimation(runner)
}
+ } else {
+ // We need to make sure delegate references are dropped to avoid memory leaks.
+ runner.dispose()
}
}
@@ -344,6 +353,13 @@
*/
fun onLaunchAnimationEnd() {}
+ /**
+ * The animation was cancelled. Note that [onLaunchAnimationEnd] will still be called after
+ * this if the animation was already started, i.e. if [onLaunchAnimationStart] was called
+ * before the cancellation.
+ */
+ fun onLaunchAnimationCancelled() {}
+
/** Called when an activity launch animation made progress. */
fun onLaunchAnimationProgress(linearProgress: Float) {}
}
@@ -426,6 +442,39 @@
fun onLaunchAnimationCancelled(newKeyguardOccludedState: Boolean? = null) {}
}
+ /**
+ * Invokes [onAnimationComplete] when animation is either cancelled or completed. Delegates all
+ * events to the passed [delegate].
+ */
+ @VisibleForTesting
+ inner class DelegatingAnimationCompletionListener(
+ private val delegate: Listener?,
+ private val onAnimationComplete: () -> Unit
+ ) : Listener {
+ var cancelled = false
+
+ override fun onLaunchAnimationStart() {
+ delegate?.onLaunchAnimationStart()
+ }
+
+ override fun onLaunchAnimationProgress(linearProgress: Float) {
+ delegate?.onLaunchAnimationProgress(linearProgress)
+ }
+
+ override fun onLaunchAnimationEnd() {
+ delegate?.onLaunchAnimationEnd()
+ if (!cancelled) {
+ onAnimationComplete.invoke()
+ }
+ }
+
+ override fun onLaunchAnimationCancelled() {
+ cancelled = true
+ delegate?.onLaunchAnimationCancelled()
+ onAnimationComplete.invoke()
+ }
+ }
+
@VisibleForTesting
inner class Runner(
controller: Controller,
@@ -436,11 +485,21 @@
listener: Listener? = null
) : IRemoteAnimationRunner.Stub() {
private val context = controller.launchContainer.context
- internal val delegate: AnimationDelegate
+
+ // This is being passed across IPC boundaries and cycles (through PendingIntentRecords,
+ // etc.) are possible. So we need to make sure we drop any references that might
+ // transitively cause leaks when we're done with animation.
+ @VisibleForTesting var delegate: AnimationDelegate?
init {
delegate =
- AnimationDelegate(controller, callback, listener, launchAnimator, disableWmTimeout)
+ AnimationDelegate(
+ controller,
+ callback,
+ DelegatingAnimationCompletionListener(listener, this::dispose),
+ launchAnimator,
+ disableWmTimeout
+ )
}
@BinderThread
@@ -451,14 +510,33 @@
nonApps: Array<out RemoteAnimationTarget>?,
finishedCallback: IRemoteAnimationFinishedCallback?
) {
+ val delegate = delegate
context.mainExecutor.execute {
- delegate.onAnimationStart(transit, apps, wallpapers, nonApps, finishedCallback)
+ if (delegate == null) {
+ Log.i(TAG, "onAnimationStart called after completion")
+ // Animation started too late and timed out already. We need to still
+ // signal back that we're done with it.
+ finishedCallback?.onAnimationFinished()
+ } else {
+ delegate.onAnimationStart(transit, apps, wallpapers, nonApps, finishedCallback)
+ }
}
}
@BinderThread
override fun onAnimationCancelled() {
- context.mainExecutor.execute { delegate.onAnimationCancelled() }
+ val delegate = delegate
+ context.mainExecutor.execute {
+ delegate ?: Log.wtf(TAG, "onAnimationCancelled called after completion")
+ delegate?.onAnimationCancelled()
+ }
+ }
+
+ @AnyThread
+ fun dispose() {
+ // Drop references to animation controller once we're done with the animation
+ // to avoid leaking.
+ context.mainExecutor.execute { delegate = null }
}
}
@@ -584,6 +662,7 @@
)
}
controller.onLaunchAnimationCancelled()
+ listener?.onLaunchAnimationCancelled()
return
}
@@ -821,6 +900,7 @@
Log.d(TAG, "Calling controller.onLaunchAnimationCancelled() [animation timed out]")
}
controller.onLaunchAnimationCancelled()
+ listener?.onLaunchAnimationCancelled()
}
@UiThread
@@ -842,6 +922,7 @@
)
}
controller.onLaunchAnimationCancelled()
+ listener?.onLaunchAnimationCancelled()
}
private fun IRemoteAnimationFinishedCallback.invoke() {
diff --git a/packages/SystemUI/compose/core/src/com/android/compose/animation/scene/AnimateToScene.kt b/packages/SystemUI/compose/core/src/com/android/compose/animation/scene/AnimateToScene.kt
index 88944f10..60c3fd3 100644
--- a/packages/SystemUI/compose/core/src/com/android/compose/animation/scene/AnimateToScene.kt
+++ b/packages/SystemUI/compose/core/src/com/android/compose/animation/scene/AnimateToScene.kt
@@ -108,7 +108,7 @@
) {
val fromScene = layoutImpl.state.transitionState.currentScene
val isUserInput =
- (layoutImpl.state.transitionState as? TransitionState.Transition)?.isUserInputDriven
+ (layoutImpl.state.transitionState as? TransitionState.Transition)?.isInitiatedByUserInput
?: false
val animationSpec = layoutImpl.transitions.transitionSpec(fromScene, target).spec
@@ -119,9 +119,23 @@
val targetProgress = if (reversed) 0f else 1f
val transition =
if (reversed) {
- OneOffTransition(target, fromScene, currentScene = target, isUserInput, animatable)
+ OneOffTransition(
+ fromScene = target,
+ toScene = fromScene,
+ currentScene = target,
+ isUserInput,
+ isUserInputOngoing = false,
+ animatable,
+ )
} else {
- OneOffTransition(fromScene, target, currentScene = target, isUserInput, animatable)
+ OneOffTransition(
+ fromScene = fromScene,
+ toScene = target,
+ currentScene = target,
+ isUserInput,
+ isUserInputOngoing = false,
+ animatable,
+ )
}
// Change the current layout state to use this new transition.
@@ -142,7 +156,8 @@
override val fromScene: SceneKey,
override val toScene: SceneKey,
override val currentScene: SceneKey,
- override val isUserInputDriven: Boolean,
+ override val isInitiatedByUserInput: Boolean,
+ override val isUserInputOngoing: Boolean,
private val animatable: Animatable<Float, AnimationVector1D>,
) : TransitionState.Transition {
override val progress: Float
diff --git a/packages/SystemUI/compose/core/src/com/android/compose/animation/scene/ObservableTransitionState.kt b/packages/SystemUI/compose/core/src/com/android/compose/animation/scene/ObservableTransitionState.kt
index ccdec6e..1b79dbd 100644
--- a/packages/SystemUI/compose/core/src/com/android/compose/animation/scene/ObservableTransitionState.kt
+++ b/packages/SystemUI/compose/core/src/com/android/compose/animation/scene/ObservableTransitionState.kt
@@ -52,7 +52,14 @@
* scene, this value will remain true after the pointer is no longer touching the screen and
* will be true in any transition created to animate back to the original position.
*/
- val isUserInputDriven: Boolean,
+ val isInitiatedByUserInput: Boolean,
+
+ /**
+ * Whether user input is currently driving the transition. For example, if a user is
+ * dragging a pointer, this emits true. Once they lift their finger, this emits false while
+ * the transition completes/settles.
+ */
+ val isUserInputOngoing: Flow<Boolean>,
) : ObservableTransitionState()
}
@@ -73,7 +80,8 @@
fromScene = state.fromScene,
toScene = state.toScene,
progress = snapshotFlow { state.progress },
- isUserInputDriven = state.isUserInputDriven,
+ isInitiatedByUserInput = state.isInitiatedByUserInput,
+ isUserInputOngoing = snapshotFlow { state.isUserInputOngoing },
)
}
}
diff --git a/packages/SystemUI/compose/core/src/com/android/compose/animation/scene/SceneTransitionLayoutState.kt b/packages/SystemUI/compose/core/src/com/android/compose/animation/scene/SceneTransitionLayoutState.kt
index 7a21211..b9f83c5 100644
--- a/packages/SystemUI/compose/core/src/com/android/compose/animation/scene/SceneTransitionLayoutState.kt
+++ b/packages/SystemUI/compose/core/src/com/android/compose/animation/scene/SceneTransitionLayoutState.kt
@@ -70,6 +70,9 @@
val progress: Float
/** Whether the transition was triggered by user input rather than being programmatic. */
- val isUserInputDriven: Boolean
+ val isInitiatedByUserInput: Boolean
+
+ /** Whether user input is currently driving the transition. */
+ val isUserInputOngoing: Boolean
}
}
diff --git a/packages/SystemUI/compose/core/src/com/android/compose/animation/scene/SwipeToScene.kt b/packages/SystemUI/compose/core/src/com/android/compose/animation/scene/SwipeToScene.kt
index 1cbfe30..e275fca 100644
--- a/packages/SystemUI/compose/core/src/com/android/compose/animation/scene/SwipeToScene.kt
+++ b/packages/SystemUI/compose/core/src/com/android/compose/animation/scene/SwipeToScene.kt
@@ -66,7 +66,7 @@
// swipe in the other direction.
val startDragImmediately =
state == transition &&
- transition.isAnimatingOffset &&
+ !transition.isUserInputOngoing &&
!currentScene.shouldEnableSwipes(orientation.opposite())
// The velocity threshold at which the intent of the user is to swipe up or down. It is the same
@@ -126,7 +126,7 @@
override val progress: Float
get() {
- val offset = if (isAnimatingOffset) offsetAnimatable.value else dragOffset
+ val offset = if (isUserInputOngoing) dragOffset else offsetAnimatable.value
if (distance == 0f) {
// This can happen only if fromScene == toScene.
error(
@@ -137,16 +137,15 @@
return offset / distance
}
- override val isUserInputDriven = true
+ override val isInitiatedByUserInput = true
+
+ var _isUserInputOngoing by mutableStateOf(false)
+ override val isUserInputOngoing: Boolean
+ get() = _isUserInputOngoing
/** The current offset caused by the drag gesture. */
var dragOffset by mutableFloatStateOf(0f)
- /**
- * Whether the offset is animated (the user lifted their finger) or if it is driven by gesture.
- */
- var isAnimatingOffset by mutableStateOf(false)
-
/** The animatable used to animate the offset once the user lifted its finger. */
val offsetAnimatable = Animatable(0f, visibilityThreshold = OffsetVisibilityThreshold)
@@ -209,9 +208,11 @@
transition: SwipeTransition,
orientation: Orientation,
) {
+ transition._isUserInputOngoing = true
+
if (layoutImpl.state.transitionState == transition) {
// This [transition] was already driving the animation: simply take over it.
- if (transition.isAnimatingOffset) {
+ if (!transition.isUserInputOngoing) {
// Stop animating and start from where the current offset. Setting the animation job to
// `null` will effectively cancel the animation.
transition.stopOffsetAnimation()
@@ -456,30 +457,29 @@
) {
transition.startOffsetAnimation {
launch {
- if (!transition.isAnimatingOffset) {
- transition.offsetAnimatable.snapTo(transition.dragOffset)
- }
- transition.isAnimatingOffset = true
-
- transition.offsetAnimatable.animateTo(
- targetOffset,
- // TODO(b/290184746): Make this spring spec configurable.
- spring(
- stiffness = Spring.StiffnessMediumLow,
- visibilityThreshold = OffsetVisibilityThreshold
- ),
- initialVelocity = initialVelocity,
- )
-
- // Now that the animation is done, the state should be idle. Note that if the state
- // was changed since this animation started, some external code changed it and we
- // shouldn't do anything here. Note also that this job will be cancelled in the case
- // where the user intercepts this swipe.
- if (layoutImpl.state.transitionState == transition) {
- layoutImpl.state.transitionState = TransitionState.Idle(targetScene)
- }
+ if (transition.isUserInputOngoing) {
+ transition.offsetAnimatable.snapTo(transition.dragOffset)
}
- .also { it.invokeOnCompletion { transition.isAnimatingOffset = false } }
+ transition._isUserInputOngoing = false
+
+ transition.offsetAnimatable.animateTo(
+ targetOffset,
+ // TODO(b/290184746): Make this spring spec configurable.
+ spring(
+ stiffness = Spring.StiffnessMediumLow,
+ visibilityThreshold = OffsetVisibilityThreshold
+ ),
+ initialVelocity = initialVelocity,
+ )
+
+ // Now that the animation is done, the state should be idle. Note that if the state
+ // was changed since this animation started, some external code changed it and we
+ // shouldn't do anything here. Note also that this job will be cancelled in the case
+ // where the user intercepts this swipe.
+ if (layoutImpl.state.transitionState == transition) {
+ layoutImpl.state.transitionState = TransitionState.Idle(targetScene)
+ }
+ }
}
}
diff --git a/packages/SystemUI/compose/core/tests/Android.bp b/packages/SystemUI/compose/core/tests/Android.bp
index 52c6385..8e9c586 100644
--- a/packages/SystemUI/compose/core/tests/Android.bp
+++ b/packages/SystemUI/compose/core/tests/Android.bp
@@ -43,7 +43,7 @@
"androidx.compose.ui_ui-test-junit4",
"androidx.compose.ui_ui-test-manifest",
- "truth-prebuilt",
+ "truth",
],
kotlincflags: ["-Xjvm-default=all"],
diff --git a/packages/SystemUI/compose/core/tests/src/com/android/compose/animation/scene/SwipeToSceneTest.kt b/packages/SystemUI/compose/core/tests/src/com/android/compose/animation/scene/SwipeToSceneTest.kt
index 2232370..53ed2b5 100644
--- a/packages/SystemUI/compose/core/tests/src/com/android/compose/animation/scene/SwipeToSceneTest.kt
+++ b/packages/SystemUI/compose/core/tests/src/com/android/compose/animation/scene/SwipeToSceneTest.kt
@@ -122,7 +122,8 @@
assertThat(transition.toScene).isEqualTo(TestScenes.SceneB)
assertThat(transition.currentScene).isEqualTo(TestScenes.SceneA)
assertThat(transition.progress).isEqualTo(55.dp / LayoutWidth)
- assertThat(transition.isUserInputDriven).isTrue()
+ assertThat(transition.isInitiatedByUserInput).isTrue()
+ assertThat(transition.isUserInputOngoing).isTrue()
// Release the finger. We should now be animating back to A (currentScene = SceneA) given
// that 55dp < positional threshold.
@@ -134,7 +135,8 @@
assertThat(transition.toScene).isEqualTo(TestScenes.SceneB)
assertThat(transition.currentScene).isEqualTo(TestScenes.SceneA)
assertThat(transition.progress).isEqualTo(55.dp / LayoutWidth)
- assertThat(transition.isUserInputDriven).isTrue()
+ assertThat(transition.isInitiatedByUserInput).isTrue()
+ assertThat(transition.isUserInputOngoing).isFalse()
// Wait for the animation to finish. We should now be in scene A.
rule.waitForIdle()
@@ -156,7 +158,8 @@
assertThat(transition.toScene).isEqualTo(TestScenes.SceneC)
assertThat(transition.currentScene).isEqualTo(TestScenes.SceneA)
assertThat(transition.progress).isEqualTo(56.dp / LayoutHeight)
- assertThat(transition.isUserInputDriven).isTrue()
+ assertThat(transition.isInitiatedByUserInput).isTrue()
+ assertThat(transition.isUserInputOngoing).isTrue()
// Release the finger. We should now be animating to C (currentScene = SceneC) given
// that 56dp >= positional threshold.
@@ -168,7 +171,8 @@
assertThat(transition.toScene).isEqualTo(TestScenes.SceneC)
assertThat(transition.currentScene).isEqualTo(TestScenes.SceneC)
assertThat(transition.progress).isEqualTo(56.dp / LayoutHeight)
- assertThat(transition.isUserInputDriven).isTrue()
+ assertThat(transition.isInitiatedByUserInput).isTrue()
+ assertThat(transition.isUserInputOngoing).isFalse()
// Wait for the animation to finish. We should now be in scene C.
rule.waitForIdle()
diff --git a/packages/SystemUI/compose/features/src/com/android/systemui/qs/ui/composable/QuickSettingsScene.kt b/packages/SystemUI/compose/features/src/com/android/systemui/qs/ui/composable/QuickSettingsScene.kt
index 1f9c3e6..a33eac5 100644
--- a/packages/SystemUI/compose/features/src/com/android/systemui/qs/ui/composable/QuickSettingsScene.kt
+++ b/packages/SystemUI/compose/features/src/com/android/systemui/qs/ui/composable/QuickSettingsScene.kt
@@ -23,11 +23,13 @@
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.padding
+import androidx.compose.material3.windowsizeclass.WindowWidthSizeClass
import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.unit.dp
import com.android.compose.animation.scene.SceneScope
+import com.android.compose.windowsizeclass.LocalWindowSizeClass
import com.android.systemui.battery.BatteryMeterViewController
import com.android.systemui.dagger.SysUISingleton
import com.android.systemui.qs.footer.ui.compose.QuickSettings
@@ -37,6 +39,7 @@
import com.android.systemui.scene.shared.model.SceneModel
import com.android.systemui.scene.shared.model.UserAction
import com.android.systemui.scene.ui.composable.ComposableScene
+import com.android.systemui.shade.ui.composable.CollapsedShadeHeader
import com.android.systemui.shade.ui.composable.ExpandedShadeHeader
import com.android.systemui.statusbar.phone.StatusBarIconController
import com.android.systemui.statusbar.phone.StatusBarIconController.TintedIconManager
@@ -98,12 +101,22 @@
.clickable(onClick = { viewModel.onContentClicked() })
.padding(start = 16.dp, end = 16.dp, bottom = 48.dp)
) {
- ExpandedShadeHeader(
- viewModel = viewModel.shadeHeaderViewModel,
- createTintedIconManager = createTintedIconManager,
- createBatteryMeterViewController = createBatteryMeterViewController,
- statusBarIconController = statusBarIconController,
- )
+ when (LocalWindowSizeClass.current.widthSizeClass) {
+ WindowWidthSizeClass.Compact ->
+ ExpandedShadeHeader(
+ viewModel = viewModel.shadeHeaderViewModel,
+ createTintedIconManager = createTintedIconManager,
+ createBatteryMeterViewController = createBatteryMeterViewController,
+ statusBarIconController = statusBarIconController,
+ )
+ else ->
+ CollapsedShadeHeader(
+ viewModel = viewModel.shadeHeaderViewModel,
+ createTintedIconManager = createTintedIconManager,
+ createBatteryMeterViewController = createBatteryMeterViewController,
+ statusBarIconController = statusBarIconController,
+ )
+ }
Spacer(modifier = Modifier.height(16.dp))
QuickSettings()
}
diff --git a/packages/SystemUI/compose/features/src/com/android/systemui/scene/ui/composable/SceneContainer.kt b/packages/SystemUI/compose/features/src/com/android/systemui/scene/ui/composable/SceneContainer.kt
index ef01266..6359ce60 100644
--- a/packages/SystemUI/compose/features/src/com/android/systemui/scene/ui/composable/SceneContainer.kt
+++ b/packages/SystemUI/compose/features/src/com/android/systemui/scene/ui/composable/SceneContainer.kt
@@ -158,7 +158,8 @@
fromScene = fromScene.toModel().key,
toScene = toScene.toModel().key,
progress = progress,
- isUserInputDriven = isUserInputDriven,
+ isInitiatedByUserInput = isInitiatedByUserInput,
+ isUserInputOngoing = isUserInputOngoing,
)
}
}
diff --git a/packages/SystemUI/compose/features/src/com/android/systemui/shade/ui/composable/ShadeHeader.kt b/packages/SystemUI/compose/features/src/com/android/systemui/shade/ui/composable/ShadeHeader.kt
index 6629a25..591fa76 100644
--- a/packages/SystemUI/compose/features/src/com/android/systemui/shade/ui/composable/ShadeHeader.kt
+++ b/packages/SystemUI/compose/features/src/com/android/systemui/shade/ui/composable/ShadeHeader.kt
@@ -30,6 +30,7 @@
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.width
import androidx.compose.foundation.layout.widthIn
+import androidx.compose.material3.windowsizeclass.WindowWidthSizeClass
import androidx.compose.runtime.Composable
import androidx.compose.runtime.collectAsState
import androidx.compose.runtime.derivedStateOf
@@ -50,6 +51,7 @@
import com.android.compose.animation.scene.SceneScope
import com.android.compose.animation.scene.ValueKey
import com.android.compose.animation.scene.animateSharedFloatAsState
+import com.android.compose.windowsizeclass.LocalWindowSizeClass
import com.android.settingslib.Utils
import com.android.systemui.battery.BatteryMeterView
import com.android.systemui.battery.BatteryMeterViewController
@@ -98,12 +100,12 @@
ShadeHeader.Keys.transitionProgress,
ShadeHeader.Elements.FormatPlaceholder
)
- val useExpandedFormat by
- remember(formatProgress) { derivedStateOf { formatProgress.value > 0.5f } }
val cutoutWidth = LocalDisplayCutout.current.width()
val cutoutLocation = LocalDisplayCutout.current.location
+ val useExpandedFormat = formatProgress.value > 0.5f || cutoutLocation != CutoutLocation.CENTER
+
// This layout assumes it is globally positioned at (0, 0) and is the
// same size as the screen.
Layout(
@@ -131,6 +133,14 @@
{
Row(horizontalArrangement = Arrangement.End) {
SystemIconContainer {
+ when (LocalWindowSizeClass.current.widthSizeClass) {
+ WindowWidthSizeClass.Medium,
+ WindowWidthSizeClass.Expanded ->
+ ShadeCarrierGroup(
+ viewModel = viewModel,
+ modifier = Modifier.align(Alignment.CenterVertically),
+ )
+ }
StatusIcons(
viewModel = viewModel,
createTintedIconManager = createTintedIconManager,
diff --git a/packages/SystemUI/customization/res/values-af/strings.xml b/packages/SystemUI/customization/res/values-af/strings.xml
new file mode 100644
index 0000000..4c2c627
--- /dev/null
+++ b/packages/SystemUI/customization/res/values-af/strings.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/**
+ * Copyright (c) 2023, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+-->
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="clock_default_description" msgid="5309401440896597541">"Verstek vir digitaal"</string>
+</resources>
\ No newline at end of file
diff --git a/packages/SystemUI/customization/res/values-am/strings.xml b/packages/SystemUI/customization/res/values-am/strings.xml
new file mode 100644
index 0000000..847d7a5
--- /dev/null
+++ b/packages/SystemUI/customization/res/values-am/strings.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/**
+ * Copyright (c) 2023, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+-->
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="clock_default_description" msgid="5309401440896597541">"ዲጂታል ነባሪ"</string>
+</resources>
\ No newline at end of file
diff --git a/packages/SystemUI/customization/res/values-ar/strings.xml b/packages/SystemUI/customization/res/values-ar/strings.xml
new file mode 100644
index 0000000..57d1612
--- /dev/null
+++ b/packages/SystemUI/customization/res/values-ar/strings.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/**
+ * Copyright (c) 2023, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+-->
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="clock_default_description" msgid="5309401440896597541">"رقمية تلقائية"</string>
+</resources>
\ No newline at end of file
diff --git a/packages/SystemUI/customization/res/values-as/strings.xml b/packages/SystemUI/customization/res/values-as/strings.xml
new file mode 100644
index 0000000..2f3b64b
--- /dev/null
+++ b/packages/SystemUI/customization/res/values-as/strings.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/**
+ * Copyright (c) 2023, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+-->
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="clock_default_description" msgid="5309401440896597541">"ডিজিটেল ডিফ’ল্ট"</string>
+</resources>
\ No newline at end of file
diff --git a/packages/SystemUI/customization/res/values-az/strings.xml b/packages/SystemUI/customization/res/values-az/strings.xml
new file mode 100644
index 0000000..eb52f95
--- /dev/null
+++ b/packages/SystemUI/customization/res/values-az/strings.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/**
+ * Copyright (c) 2023, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+-->
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="clock_default_description" msgid="5309401440896597541">"Rəqəmsal defolt"</string>
+</resources>
\ No newline at end of file
diff --git a/packages/SystemUI/customization/res/values-b+sr+Latn/strings.xml b/packages/SystemUI/customization/res/values-b+sr+Latn/strings.xml
new file mode 100644
index 0000000..90e6678
--- /dev/null
+++ b/packages/SystemUI/customization/res/values-b+sr+Latn/strings.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/**
+ * Copyright (c) 2023, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+-->
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="clock_default_description" msgid="5309401440896597541">"Digitalni podrazumevani"</string>
+</resources>
\ No newline at end of file
diff --git a/packages/SystemUI/customization/res/values-be/strings.xml b/packages/SystemUI/customization/res/values-be/strings.xml
new file mode 100644
index 0000000..f327da2
--- /dev/null
+++ b/packages/SystemUI/customization/res/values-be/strings.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/**
+ * Copyright (c) 2023, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+-->
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="clock_default_description" msgid="5309401440896597541">"электронны, стандартны шрыфт"</string>
+</resources>
\ No newline at end of file
diff --git a/packages/SystemUI/customization/res/values-bg/strings.xml b/packages/SystemUI/customization/res/values-bg/strings.xml
new file mode 100644
index 0000000..6e3754a
--- /dev/null
+++ b/packages/SystemUI/customization/res/values-bg/strings.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/**
+ * Copyright (c) 2023, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+-->
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="clock_default_description" msgid="5309401440896597541">"Стандартно дигитално"</string>
+</resources>
\ No newline at end of file
diff --git a/packages/SystemUI/customization/res/values-bn/strings.xml b/packages/SystemUI/customization/res/values-bn/strings.xml
new file mode 100644
index 0000000..adf1256
--- /dev/null
+++ b/packages/SystemUI/customization/res/values-bn/strings.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/**
+ * Copyright (c) 2023, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+-->
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="clock_default_description" msgid="5309401440896597541">"ডিজিটাল ডিফল্ট"</string>
+</resources>
\ No newline at end of file
diff --git a/packages/SystemUI/customization/res/values-bs/strings.xml b/packages/SystemUI/customization/res/values-bs/strings.xml
new file mode 100644
index 0000000..8de04ab
--- /dev/null
+++ b/packages/SystemUI/customization/res/values-bs/strings.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/**
+ * Copyright (c) 2023, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+-->
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="clock_default_description" msgid="5309401440896597541">"Digitalno zadano"</string>
+</resources>
\ No newline at end of file
diff --git a/packages/SystemUI/customization/res/values-ca/strings.xml b/packages/SystemUI/customization/res/values-ca/strings.xml
new file mode 100644
index 0000000..967bb3f
--- /dev/null
+++ b/packages/SystemUI/customization/res/values-ca/strings.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/**
+ * Copyright (c) 2023, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+-->
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="clock_default_description" msgid="5309401440896597541">"Digital predeterminat"</string>
+</resources>
\ No newline at end of file
diff --git a/packages/SystemUI/customization/res/values-cs/strings.xml b/packages/SystemUI/customization/res/values-cs/strings.xml
new file mode 100644
index 0000000..45da4d7
--- /dev/null
+++ b/packages/SystemUI/customization/res/values-cs/strings.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/**
+ * Copyright (c) 2023, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+-->
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="clock_default_description" msgid="5309401440896597541">"Digitální výchozí"</string>
+</resources>
\ No newline at end of file
diff --git a/packages/SystemUI/customization/res/values-da/strings.xml b/packages/SystemUI/customization/res/values-da/strings.xml
new file mode 100644
index 0000000..3ffaa8b
--- /dev/null
+++ b/packages/SystemUI/customization/res/values-da/strings.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/**
+ * Copyright (c) 2023, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+-->
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="clock_default_description" msgid="5309401440896597541">"Standard (digital)"</string>
+</resources>
\ No newline at end of file
diff --git a/packages/SystemUI/customization/res/values-de/strings.xml b/packages/SystemUI/customization/res/values-de/strings.xml
new file mode 100644
index 0000000..64f95e0
--- /dev/null
+++ b/packages/SystemUI/customization/res/values-de/strings.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/**
+ * Copyright (c) 2023, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+-->
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="clock_default_description" msgid="5309401440896597541">"Digital (Standard)"</string>
+</resources>
\ No newline at end of file
diff --git a/packages/SystemUI/customization/res/values-el/strings.xml b/packages/SystemUI/customization/res/values-el/strings.xml
new file mode 100644
index 0000000..57134b5
--- /dev/null
+++ b/packages/SystemUI/customization/res/values-el/strings.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/**
+ * Copyright (c) 2023, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+-->
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="clock_default_description" msgid="5309401440896597541">"Ψηφιακή προεπιλογή"</string>
+</resources>
\ No newline at end of file
diff --git a/packages/SystemUI/customization/res/values-en-rAU/strings.xml b/packages/SystemUI/customization/res/values-en-rAU/strings.xml
new file mode 100644
index 0000000..a6110d5
--- /dev/null
+++ b/packages/SystemUI/customization/res/values-en-rAU/strings.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/**
+ * Copyright (c) 2023, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+-->
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="clock_default_description" msgid="5309401440896597541">"Digital default"</string>
+</resources>
\ No newline at end of file
diff --git a/packages/SystemUI/customization/res/values-en-rCA/strings.xml b/packages/SystemUI/customization/res/values-en-rCA/strings.xml
new file mode 100644
index 0000000..79919c0
--- /dev/null
+++ b/packages/SystemUI/customization/res/values-en-rCA/strings.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/**
+ * Copyright (c) 2023, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+-->
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <!-- no translation found for clock_default_description (5309401440896597541) -->
+ <skip />
+</resources>
\ No newline at end of file
diff --git a/packages/SystemUI/customization/res/values-en-rGB/strings.xml b/packages/SystemUI/customization/res/values-en-rGB/strings.xml
new file mode 100644
index 0000000..a6110d5
--- /dev/null
+++ b/packages/SystemUI/customization/res/values-en-rGB/strings.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/**
+ * Copyright (c) 2023, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+-->
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="clock_default_description" msgid="5309401440896597541">"Digital default"</string>
+</resources>
\ No newline at end of file
diff --git a/packages/SystemUI/customization/res/values-en-rIN/strings.xml b/packages/SystemUI/customization/res/values-en-rIN/strings.xml
new file mode 100644
index 0000000..a6110d5
--- /dev/null
+++ b/packages/SystemUI/customization/res/values-en-rIN/strings.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/**
+ * Copyright (c) 2023, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+-->
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="clock_default_description" msgid="5309401440896597541">"Digital default"</string>
+</resources>
\ No newline at end of file
diff --git a/packages/SystemUI/customization/res/values-en-rXC/strings.xml b/packages/SystemUI/customization/res/values-en-rXC/strings.xml
new file mode 100644
index 0000000..7c540da
--- /dev/null
+++ b/packages/SystemUI/customization/res/values-en-rXC/strings.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/**
+ * Copyright (c) 2023, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+-->
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="clock_default_description" msgid="5309401440896597541">"Digital default"</string>
+</resources>
\ No newline at end of file
diff --git a/packages/SystemUI/customization/res/values-es-rUS/strings.xml b/packages/SystemUI/customization/res/values-es-rUS/strings.xml
new file mode 100644
index 0000000..59be786
--- /dev/null
+++ b/packages/SystemUI/customization/res/values-es-rUS/strings.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/**
+ * Copyright (c) 2023, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+-->
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="clock_default_description" msgid="5309401440896597541">"Configuración predeterminada digital"</string>
+</resources>
\ No newline at end of file
diff --git a/packages/SystemUI/customization/res/values-es/strings.xml b/packages/SystemUI/customization/res/values-es/strings.xml
new file mode 100644
index 0000000..03ef0e5
--- /dev/null
+++ b/packages/SystemUI/customization/res/values-es/strings.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/**
+ * Copyright (c) 2023, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+-->
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="clock_default_description" msgid="5309401440896597541">"Digital predeterminada"</string>
+</resources>
\ No newline at end of file
diff --git a/packages/SystemUI/customization/res/values-et/strings.xml b/packages/SystemUI/customization/res/values-et/strings.xml
new file mode 100644
index 0000000..fec793e
--- /dev/null
+++ b/packages/SystemUI/customization/res/values-et/strings.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/**
+ * Copyright (c) 2023, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+-->
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="clock_default_description" msgid="5309401440896597541">"Digitaalne vaikimisi"</string>
+</resources>
\ No newline at end of file
diff --git a/packages/SystemUI/customization/res/values-eu/strings.xml b/packages/SystemUI/customization/res/values-eu/strings.xml
new file mode 100644
index 0000000..a70c808
--- /dev/null
+++ b/packages/SystemUI/customization/res/values-eu/strings.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/**
+ * Copyright (c) 2023, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+-->
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="clock_default_description" msgid="5309401440896597541">"Digital lehenetsia"</string>
+</resources>
\ No newline at end of file
diff --git a/packages/SystemUI/customization/res/values-fa/strings.xml b/packages/SystemUI/customization/res/values-fa/strings.xml
new file mode 100644
index 0000000..6426d51
--- /dev/null
+++ b/packages/SystemUI/customization/res/values-fa/strings.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/**
+ * Copyright (c) 2023, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+-->
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="clock_default_description" msgid="5309401440896597541">"دیجیتال پیشفرض"</string>
+</resources>
\ No newline at end of file
diff --git a/packages/SystemUI/customization/res/values-fi/strings.xml b/packages/SystemUI/customization/res/values-fi/strings.xml
new file mode 100644
index 0000000..9b19373
--- /dev/null
+++ b/packages/SystemUI/customization/res/values-fi/strings.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/**
+ * Copyright (c) 2023, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+-->
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="clock_default_description" msgid="5309401440896597541">"Digitaalinen (oletus)"</string>
+</resources>
\ No newline at end of file
diff --git a/packages/SystemUI/customization/res/values-fr-rCA/strings.xml b/packages/SystemUI/customization/res/values-fr-rCA/strings.xml
new file mode 100644
index 0000000..bbd1208
--- /dev/null
+++ b/packages/SystemUI/customization/res/values-fr-rCA/strings.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/**
+ * Copyright (c) 2023, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+-->
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="clock_default_description" msgid="5309401440896597541">"Numérique, par défaut"</string>
+</resources>
\ No newline at end of file
diff --git a/packages/SystemUI/customization/res/values-fr/strings.xml b/packages/SystemUI/customization/res/values-fr/strings.xml
new file mode 100644
index 0000000..5579a42
--- /dev/null
+++ b/packages/SystemUI/customization/res/values-fr/strings.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/**
+ * Copyright (c) 2023, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+-->
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="clock_default_description" msgid="5309401440896597541">"Numérique par défaut"</string>
+</resources>
\ No newline at end of file
diff --git a/packages/SystemUI/customization/res/values-gl/strings.xml b/packages/SystemUI/customization/res/values-gl/strings.xml
new file mode 100644
index 0000000..2da93c6
--- /dev/null
+++ b/packages/SystemUI/customization/res/values-gl/strings.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/**
+ * Copyright (c) 2023, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+-->
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="clock_default_description" msgid="5309401440896597541">"Predeterminada dixital"</string>
+</resources>
\ No newline at end of file
diff --git a/packages/SystemUI/customization/res/values-gu/strings.xml b/packages/SystemUI/customization/res/values-gu/strings.xml
new file mode 100644
index 0000000..c578a2e
--- /dev/null
+++ b/packages/SystemUI/customization/res/values-gu/strings.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/**
+ * Copyright (c) 2023, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+-->
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="clock_default_description" msgid="5309401440896597541">"ડિજિટલ ડિફૉલ્ટ"</string>
+</resources>
\ No newline at end of file
diff --git a/packages/SystemUI/customization/res/values-hi/strings.xml b/packages/SystemUI/customization/res/values-hi/strings.xml
new file mode 100644
index 0000000..6080f80
--- /dev/null
+++ b/packages/SystemUI/customization/res/values-hi/strings.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/**
+ * Copyright (c) 2023, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+-->
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="clock_default_description" msgid="5309401440896597541">"डिजिटल डिफ़ॉल्ट"</string>
+</resources>
\ No newline at end of file
diff --git a/packages/SystemUI/customization/res/values-hr/strings.xml b/packages/SystemUI/customization/res/values-hr/strings.xml
new file mode 100644
index 0000000..0a1440f
--- /dev/null
+++ b/packages/SystemUI/customization/res/values-hr/strings.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/**
+ * Copyright (c) 2023, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+-->
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="clock_default_description" msgid="5309401440896597541">"Digitalni zadani"</string>
+</resources>
\ No newline at end of file
diff --git a/packages/SystemUI/customization/res/values-hu/strings.xml b/packages/SystemUI/customization/res/values-hu/strings.xml
new file mode 100644
index 0000000..32618a8
--- /dev/null
+++ b/packages/SystemUI/customization/res/values-hu/strings.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/**
+ * Copyright (c) 2023, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+-->
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="clock_default_description" msgid="5309401440896597541">"Digitális, alapértelmezett"</string>
+</resources>
\ No newline at end of file
diff --git a/packages/SystemUI/customization/res/values-hy/strings.xml b/packages/SystemUI/customization/res/values-hy/strings.xml
new file mode 100644
index 0000000..d45afbf
--- /dev/null
+++ b/packages/SystemUI/customization/res/values-hy/strings.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/**
+ * Copyright (c) 2023, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+-->
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="clock_default_description" msgid="5309401440896597541">"Թվային, կանխադրված"</string>
+</resources>
\ No newline at end of file
diff --git a/packages/SystemUI/customization/res/values-in/strings.xml b/packages/SystemUI/customization/res/values-in/strings.xml
new file mode 100644
index 0000000..a6110d5
--- /dev/null
+++ b/packages/SystemUI/customization/res/values-in/strings.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/**
+ * Copyright (c) 2023, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+-->
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="clock_default_description" msgid="5309401440896597541">"Digital default"</string>
+</resources>
\ No newline at end of file
diff --git a/packages/SystemUI/customization/res/values-is/strings.xml b/packages/SystemUI/customization/res/values-is/strings.xml
new file mode 100644
index 0000000..5a370d6
--- /dev/null
+++ b/packages/SystemUI/customization/res/values-is/strings.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/**
+ * Copyright (c) 2023, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+-->
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="clock_default_description" msgid="5309401440896597541">"Stafræn, sjálfgefið"</string>
+</resources>
\ No newline at end of file
diff --git a/packages/SystemUI/customization/res/values-it/strings.xml b/packages/SystemUI/customization/res/values-it/strings.xml
new file mode 100644
index 0000000..2a5087d
--- /dev/null
+++ b/packages/SystemUI/customization/res/values-it/strings.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/**
+ * Copyright (c) 2023, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+-->
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="clock_default_description" msgid="5309401440896597541">"Digitale - predefinito"</string>
+</resources>
\ No newline at end of file
diff --git a/packages/SystemUI/customization/res/values-iw/strings.xml b/packages/SystemUI/customization/res/values-iw/strings.xml
new file mode 100644
index 0000000..ddd28f2
--- /dev/null
+++ b/packages/SystemUI/customization/res/values-iw/strings.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/**
+ * Copyright (c) 2023, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+-->
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="clock_default_description" msgid="5309401440896597541">"דיגיטלי ברירת מחדל"</string>
+</resources>
\ No newline at end of file
diff --git a/packages/SystemUI/customization/res/values-ja/strings.xml b/packages/SystemUI/customization/res/values-ja/strings.xml
new file mode 100644
index 0000000..744604a
--- /dev/null
+++ b/packages/SystemUI/customization/res/values-ja/strings.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/**
+ * Copyright (c) 2023, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+-->
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="clock_default_description" msgid="5309401440896597541">"デジタル デフォルト"</string>
+</resources>
\ No newline at end of file
diff --git a/packages/SystemUI/customization/res/values-ka/strings.xml b/packages/SystemUI/customization/res/values-ka/strings.xml
new file mode 100644
index 0000000..88ba1df
--- /dev/null
+++ b/packages/SystemUI/customization/res/values-ka/strings.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/**
+ * Copyright (c) 2023, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+-->
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="clock_default_description" msgid="5309401440896597541">"ციფრული ნაგულისხმევი"</string>
+</resources>
\ No newline at end of file
diff --git a/packages/SystemUI/customization/res/values-kk/strings.xml b/packages/SystemUI/customization/res/values-kk/strings.xml
new file mode 100644
index 0000000..9ee6522
--- /dev/null
+++ b/packages/SystemUI/customization/res/values-kk/strings.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/**
+ * Copyright (c) 2023, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+-->
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="clock_default_description" msgid="5309401440896597541">"Цифрлық әдепкі"</string>
+</resources>
\ No newline at end of file
diff --git a/packages/SystemUI/customization/res/values-km/strings.xml b/packages/SystemUI/customization/res/values-km/strings.xml
new file mode 100644
index 0000000..bbc438a
--- /dev/null
+++ b/packages/SystemUI/customization/res/values-km/strings.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/**
+ * Copyright (c) 2023, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+-->
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="clock_default_description" msgid="5309401440896597541">"លំនាំដើមឌីជីថល"</string>
+</resources>
\ No newline at end of file
diff --git a/packages/SystemUI/customization/res/values-kn/strings.xml b/packages/SystemUI/customization/res/values-kn/strings.xml
new file mode 100644
index 0000000..e67319d
--- /dev/null
+++ b/packages/SystemUI/customization/res/values-kn/strings.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/**
+ * Copyright (c) 2023, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+-->
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="clock_default_description" msgid="5309401440896597541">"ಡಿಜಿಟಲ್ ಡೀಫಾಲ್ಟ್"</string>
+</resources>
\ No newline at end of file
diff --git a/packages/SystemUI/customization/res/values-ko/strings.xml b/packages/SystemUI/customization/res/values-ko/strings.xml
new file mode 100644
index 0000000..fa9103b
--- /dev/null
+++ b/packages/SystemUI/customization/res/values-ko/strings.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/**
+ * Copyright (c) 2023, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+-->
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="clock_default_description" msgid="5309401440896597541">"디지털 기본"</string>
+</resources>
\ No newline at end of file
diff --git a/packages/SystemUI/customization/res/values-ky/strings.xml b/packages/SystemUI/customization/res/values-ky/strings.xml
new file mode 100644
index 0000000..76cc5e2
--- /dev/null
+++ b/packages/SystemUI/customization/res/values-ky/strings.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/**
+ * Copyright (c) 2023, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+-->
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="clock_default_description" msgid="5309401440896597541">"Демейки санариптик"</string>
+</resources>
\ No newline at end of file
diff --git a/packages/SystemUI/customization/res/values-lo/strings.xml b/packages/SystemUI/customization/res/values-lo/strings.xml
new file mode 100644
index 0000000..28f5000
--- /dev/null
+++ b/packages/SystemUI/customization/res/values-lo/strings.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/**
+ * Copyright (c) 2023, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+-->
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="clock_default_description" msgid="5309401440896597541">"ດິຈິຕອນຕາມຄ່າເລີ່ມຕົ້ນ"</string>
+</resources>
\ No newline at end of file
diff --git a/packages/SystemUI/customization/res/values-lt/strings.xml b/packages/SystemUI/customization/res/values-lt/strings.xml
new file mode 100644
index 0000000..2fe7315
--- /dev/null
+++ b/packages/SystemUI/customization/res/values-lt/strings.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/**
+ * Copyright (c) 2023, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+-->
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="clock_default_description" msgid="5309401440896597541">"Skaitmeninis numatytasis"</string>
+</resources>
\ No newline at end of file
diff --git a/packages/SystemUI/customization/res/values-lv/strings.xml b/packages/SystemUI/customization/res/values-lv/strings.xml
new file mode 100644
index 0000000..e0b904a
--- /dev/null
+++ b/packages/SystemUI/customization/res/values-lv/strings.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/**
+ * Copyright (c) 2023, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+-->
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="clock_default_description" msgid="5309401440896597541">"Digitālais pulkstenis — noklusējums"</string>
+</resources>
\ No newline at end of file
diff --git a/packages/SystemUI/customization/res/values-mk/strings.xml b/packages/SystemUI/customization/res/values-mk/strings.xml
new file mode 100644
index 0000000..9b95a6e
--- /dev/null
+++ b/packages/SystemUI/customization/res/values-mk/strings.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/**
+ * Copyright (c) 2023, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+-->
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="clock_default_description" msgid="5309401440896597541">"Дигитален стандарден приказ"</string>
+</resources>
\ No newline at end of file
diff --git a/packages/SystemUI/customization/res/values-ml/strings.xml b/packages/SystemUI/customization/res/values-ml/strings.xml
new file mode 100644
index 0000000..7f6be8a
--- /dev/null
+++ b/packages/SystemUI/customization/res/values-ml/strings.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/**
+ * Copyright (c) 2023, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+-->
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="clock_default_description" msgid="5309401440896597541">"ഡിജിറ്റൽ ഡിഫോൾട്ട്"</string>
+</resources>
\ No newline at end of file
diff --git a/packages/SystemUI/customization/res/values-mn/strings.xml b/packages/SystemUI/customization/res/values-mn/strings.xml
new file mode 100644
index 0000000..38369b6
--- /dev/null
+++ b/packages/SystemUI/customization/res/values-mn/strings.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/**
+ * Copyright (c) 2023, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+-->
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="clock_default_description" msgid="5309401440896597541">"Дижитал өгөгдмөл"</string>
+</resources>
\ No newline at end of file
diff --git a/packages/SystemUI/customization/res/values-mr/strings.xml b/packages/SystemUI/customization/res/values-mr/strings.xml
new file mode 100644
index 0000000..821ff10
--- /dev/null
+++ b/packages/SystemUI/customization/res/values-mr/strings.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/**
+ * Copyright (c) 2023, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+-->
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="clock_default_description" msgid="5309401440896597541">"डिजिटल डीफॉल्टसह क्लॉक फेस"</string>
+</resources>
\ No newline at end of file
diff --git a/packages/SystemUI/customization/res/values-ms/strings.xml b/packages/SystemUI/customization/res/values-ms/strings.xml
new file mode 100644
index 0000000..2f61b47
--- /dev/null
+++ b/packages/SystemUI/customization/res/values-ms/strings.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/**
+ * Copyright (c) 2023, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+-->
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="clock_default_description" msgid="5309401440896597541">"Digital lalai"</string>
+</resources>
\ No newline at end of file
diff --git a/packages/SystemUI/customization/res/values-my/strings.xml b/packages/SystemUI/customization/res/values-my/strings.xml
new file mode 100644
index 0000000..3d137eb
--- /dev/null
+++ b/packages/SystemUI/customization/res/values-my/strings.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/**
+ * Copyright (c) 2023, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+-->
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="clock_default_description" msgid="5309401440896597541">"ဒစ်ဂျစ်တယ်နာရီ မူရင်း"</string>
+</resources>
\ No newline at end of file
diff --git a/packages/SystemUI/customization/res/values-nb/strings.xml b/packages/SystemUI/customization/res/values-nb/strings.xml
new file mode 100644
index 0000000..6eb4373
--- /dev/null
+++ b/packages/SystemUI/customization/res/values-nb/strings.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/**
+ * Copyright (c) 2023, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+-->
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="clock_default_description" msgid="5309401440896597541">"Digital – standard"</string>
+</resources>
\ No newline at end of file
diff --git a/packages/SystemUI/customization/res/values-ne/strings.xml b/packages/SystemUI/customization/res/values-ne/strings.xml
new file mode 100644
index 0000000..c5b0877
--- /dev/null
+++ b/packages/SystemUI/customization/res/values-ne/strings.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/**
+ * Copyright (c) 2023, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+-->
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="clock_default_description" msgid="5309401440896597541">"डिजिटल डिफल्ट"</string>
+</resources>
\ No newline at end of file
diff --git a/packages/SystemUI/customization/res/values-nl/strings.xml b/packages/SystemUI/customization/res/values-nl/strings.xml
new file mode 100644
index 0000000..4f46ab8
--- /dev/null
+++ b/packages/SystemUI/customization/res/values-nl/strings.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/**
+ * Copyright (c) 2023, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+-->
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="clock_default_description" msgid="5309401440896597541">"Standaard digitaal"</string>
+</resources>
\ No newline at end of file
diff --git a/packages/SystemUI/customization/res/values-or/strings.xml b/packages/SystemUI/customization/res/values-or/strings.xml
new file mode 100644
index 0000000..a74017f
--- /dev/null
+++ b/packages/SystemUI/customization/res/values-or/strings.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/**
+ * Copyright (c) 2023, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+-->
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="clock_default_description" msgid="5309401440896597541">"ଡିଜିଟାଲ ଡିଫଲ୍ଟ"</string>
+</resources>
\ No newline at end of file
diff --git a/packages/SystemUI/customization/res/values-pa/strings.xml b/packages/SystemUI/customization/res/values-pa/strings.xml
new file mode 100644
index 0000000..a77661a
--- /dev/null
+++ b/packages/SystemUI/customization/res/values-pa/strings.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/**
+ * Copyright (c) 2023, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+-->
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="clock_default_description" msgid="5309401440896597541">"ਡਿਜੀਟਲ ਡਿਫਾਲਟ"</string>
+</resources>
\ No newline at end of file
diff --git a/packages/SystemUI/customization/res/values-pl/strings.xml b/packages/SystemUI/customization/res/values-pl/strings.xml
new file mode 100644
index 0000000..6f5b6f2
--- /dev/null
+++ b/packages/SystemUI/customization/res/values-pl/strings.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/**
+ * Copyright (c) 2023, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+-->
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="clock_default_description" msgid="5309401440896597541">"Cyfrowa domyślna"</string>
+</resources>
\ No newline at end of file
diff --git a/packages/SystemUI/customization/res/values-pt-rPT/strings.xml b/packages/SystemUI/customization/res/values-pt-rPT/strings.xml
new file mode 100644
index 0000000..c6c3cc0
--- /dev/null
+++ b/packages/SystemUI/customization/res/values-pt-rPT/strings.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/**
+ * Copyright (c) 2023, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+-->
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="clock_default_description" msgid="5309401440896597541">"Predefinição digital"</string>
+</resources>
\ No newline at end of file
diff --git a/packages/SystemUI/customization/res/values-pt/strings.xml b/packages/SystemUI/customization/res/values-pt/strings.xml
new file mode 100644
index 0000000..bbe4355
--- /dev/null
+++ b/packages/SystemUI/customization/res/values-pt/strings.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/**
+ * Copyright (c) 2023, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+-->
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="clock_default_description" msgid="5309401440896597541">"Digital padrão"</string>
+</resources>
\ No newline at end of file
diff --git a/packages/SystemUI/customization/res/values-ro/strings.xml b/packages/SystemUI/customization/res/values-ro/strings.xml
new file mode 100644
index 0000000..ef163e9
--- /dev/null
+++ b/packages/SystemUI/customization/res/values-ro/strings.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/**
+ * Copyright (c) 2023, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+-->
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="clock_default_description" msgid="5309401440896597541">"Implicit digital"</string>
+</resources>
\ No newline at end of file
diff --git a/packages/SystemUI/customization/res/values-ru/strings.xml b/packages/SystemUI/customization/res/values-ru/strings.xml
new file mode 100644
index 0000000..5ee928e
--- /dev/null
+++ b/packages/SystemUI/customization/res/values-ru/strings.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/**
+ * Copyright (c) 2023, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+-->
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="clock_default_description" msgid="5309401440896597541">"Цифровые часы, стандартный"</string>
+</resources>
\ No newline at end of file
diff --git a/packages/SystemUI/customization/res/values-si/strings.xml b/packages/SystemUI/customization/res/values-si/strings.xml
new file mode 100644
index 0000000..caf9610
--- /dev/null
+++ b/packages/SystemUI/customization/res/values-si/strings.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/**
+ * Copyright (c) 2023, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+-->
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="clock_default_description" msgid="5309401440896597541">"ඩිජිටල් පෙරනිමිය"</string>
+</resources>
\ No newline at end of file
diff --git a/packages/SystemUI/customization/res/values-sk/strings.xml b/packages/SystemUI/customization/res/values-sk/strings.xml
new file mode 100644
index 0000000..1843f97
--- /dev/null
+++ b/packages/SystemUI/customization/res/values-sk/strings.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/**
+ * Copyright (c) 2023, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+-->
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="clock_default_description" msgid="5309401440896597541">"Digitálne predvolené"</string>
+</resources>
\ No newline at end of file
diff --git a/packages/SystemUI/customization/res/values-sl/strings.xml b/packages/SystemUI/customization/res/values-sl/strings.xml
new file mode 100644
index 0000000..12df66f
--- /dev/null
+++ b/packages/SystemUI/customization/res/values-sl/strings.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/**
+ * Copyright (c) 2023, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+-->
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="clock_default_description" msgid="5309401440896597541">"Digitalna (privzeta)"</string>
+</resources>
\ No newline at end of file
diff --git a/packages/SystemUI/customization/res/values-sq/strings.xml b/packages/SystemUI/customization/res/values-sq/strings.xml
new file mode 100644
index 0000000..1fc9f25
--- /dev/null
+++ b/packages/SystemUI/customization/res/values-sq/strings.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/**
+ * Copyright (c) 2023, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+-->
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="clock_default_description" msgid="5309401440896597541">"Dixhitale e parazgjedhur"</string>
+</resources>
\ No newline at end of file
diff --git a/packages/SystemUI/customization/res/values-sr/strings.xml b/packages/SystemUI/customization/res/values-sr/strings.xml
new file mode 100644
index 0000000..6b127c9
--- /dev/null
+++ b/packages/SystemUI/customization/res/values-sr/strings.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/**
+ * Copyright (c) 2023, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+-->
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="clock_default_description" msgid="5309401440896597541">"Дигитални подразумевани"</string>
+</resources>
\ No newline at end of file
diff --git a/packages/SystemUI/customization/res/values-sv/strings.xml b/packages/SystemUI/customization/res/values-sv/strings.xml
new file mode 100644
index 0000000..84ad25c
--- /dev/null
+++ b/packages/SystemUI/customization/res/values-sv/strings.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/**
+ * Copyright (c) 2023, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+-->
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="clock_default_description" msgid="5309401440896597541">"Digital standard"</string>
+</resources>
\ No newline at end of file
diff --git a/packages/SystemUI/customization/res/values-sw/strings.xml b/packages/SystemUI/customization/res/values-sw/strings.xml
new file mode 100644
index 0000000..e2ec3de
--- /dev/null
+++ b/packages/SystemUI/customization/res/values-sw/strings.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/**
+ * Copyright (c) 2023, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+-->
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="clock_default_description" msgid="5309401440896597541">"Dijitali chaguomsingi"</string>
+</resources>
\ No newline at end of file
diff --git a/packages/SystemUI/customization/res/values-sw400dp/dimens.xml b/packages/SystemUI/customization/res/values-sw400dp/dimens.xml
new file mode 100644
index 0000000..3c9e078
--- /dev/null
+++ b/packages/SystemUI/customization/res/values-sw400dp/dimens.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ * Copyright (c) 2023, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+*/
+-->
+<resources>
+ <dimen name="presentation_clock_text_size">170dp</dimen>
+</resources>
\ No newline at end of file
diff --git a/packages/SystemUI/customization/res/values-ta/strings.xml b/packages/SystemUI/customization/res/values-ta/strings.xml
new file mode 100644
index 0000000..f4eea07
--- /dev/null
+++ b/packages/SystemUI/customization/res/values-ta/strings.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/**
+ * Copyright (c) 2023, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+-->
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="clock_default_description" msgid="5309401440896597541">"டிஜிட்டல் இயல்பு"</string>
+</resources>
\ No newline at end of file
diff --git a/packages/SystemUI/customization/res/values-te/strings.xml b/packages/SystemUI/customization/res/values-te/strings.xml
new file mode 100644
index 0000000..c7c77d5
--- /dev/null
+++ b/packages/SystemUI/customization/res/values-te/strings.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/**
+ * Copyright (c) 2023, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+-->
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="clock_default_description" msgid="5309401440896597541">"డిజిటల్ ఆటోమేటిక్ సెట్టింగ్"</string>
+</resources>
\ No newline at end of file
diff --git a/packages/SystemUI/customization/res/values-th/strings.xml b/packages/SystemUI/customization/res/values-th/strings.xml
new file mode 100644
index 0000000..61d880e
--- /dev/null
+++ b/packages/SystemUI/customization/res/values-th/strings.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/**
+ * Copyright (c) 2023, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+-->
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="clock_default_description" msgid="5309401440896597541">"ดิจิทัลแบบเริ่มต้น"</string>
+</resources>
\ No newline at end of file
diff --git a/packages/SystemUI/customization/res/values-tl/strings.xml b/packages/SystemUI/customization/res/values-tl/strings.xml
new file mode 100644
index 0000000..a3484a7
--- /dev/null
+++ b/packages/SystemUI/customization/res/values-tl/strings.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/**
+ * Copyright (c) 2023, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+-->
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="clock_default_description" msgid="5309401440896597541">"Digital na default"</string>
+</resources>
\ No newline at end of file
diff --git a/packages/SystemUI/customization/res/values-tr/strings.xml b/packages/SystemUI/customization/res/values-tr/strings.xml
new file mode 100644
index 0000000..a90e985
--- /dev/null
+++ b/packages/SystemUI/customization/res/values-tr/strings.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/**
+ * Copyright (c) 2023, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+-->
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="clock_default_description" msgid="5309401440896597541">"Dijital varsayılan"</string>
+</resources>
\ No newline at end of file
diff --git a/packages/SystemUI/customization/res/values-uk/strings.xml b/packages/SystemUI/customization/res/values-uk/strings.xml
new file mode 100644
index 0000000..ee9b77b
--- /dev/null
+++ b/packages/SystemUI/customization/res/values-uk/strings.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/**
+ * Copyright (c) 2023, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+-->
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="clock_default_description" msgid="5309401440896597541">"Цифровий, стандартний"</string>
+</resources>
\ No newline at end of file
diff --git a/packages/SystemUI/customization/res/values-ur/strings.xml b/packages/SystemUI/customization/res/values-ur/strings.xml
new file mode 100644
index 0000000..06a6a7c
--- /dev/null
+++ b/packages/SystemUI/customization/res/values-ur/strings.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/**
+ * Copyright (c) 2023, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+-->
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="clock_default_description" msgid="5309401440896597541">"ڈیجیٹل ڈیفالٹ"</string>
+</resources>
\ No newline at end of file
diff --git a/packages/SystemUI/customization/res/values-uz/strings.xml b/packages/SystemUI/customization/res/values-uz/strings.xml
new file mode 100644
index 0000000..6b31b04
--- /dev/null
+++ b/packages/SystemUI/customization/res/values-uz/strings.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/**
+ * Copyright (c) 2023, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+-->
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="clock_default_description" msgid="5309401440896597541">"Raqamli soat, standart"</string>
+</resources>
\ No newline at end of file
diff --git a/packages/SystemUI/customization/res/values-vi/strings.xml b/packages/SystemUI/customization/res/values-vi/strings.xml
new file mode 100644
index 0000000..830b6e2
--- /dev/null
+++ b/packages/SystemUI/customization/res/values-vi/strings.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/**
+ * Copyright (c) 2023, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+-->
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="clock_default_description" msgid="5309401440896597541">"Mặt số mặc định"</string>
+</resources>
\ No newline at end of file
diff --git a/packages/SystemUI/customization/res/values-zh-rCN/strings.xml b/packages/SystemUI/customization/res/values-zh-rCN/strings.xml
new file mode 100644
index 0000000..747567e
--- /dev/null
+++ b/packages/SystemUI/customization/res/values-zh-rCN/strings.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/**
+ * Copyright (c) 2023, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+-->
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="clock_default_description" msgid="5309401440896597541">"默认数字"</string>
+</resources>
\ No newline at end of file
diff --git a/packages/SystemUI/customization/res/values-zh-rHK/strings.xml b/packages/SystemUI/customization/res/values-zh-rHK/strings.xml
new file mode 100644
index 0000000..c19cc68
--- /dev/null
+++ b/packages/SystemUI/customization/res/values-zh-rHK/strings.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/**
+ * Copyright (c) 2023, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+-->
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="clock_default_description" msgid="5309401440896597541">"數碼時鐘 (預設)"</string>
+</resources>
\ No newline at end of file
diff --git a/packages/SystemUI/customization/res/values-zh-rTW/strings.xml b/packages/SystemUI/customization/res/values-zh-rTW/strings.xml
new file mode 100644
index 0000000..6fcd313
--- /dev/null
+++ b/packages/SystemUI/customization/res/values-zh-rTW/strings.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/**
+ * Copyright (c) 2023, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+-->
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="clock_default_description" msgid="5309401440896597541">"數位預設"</string>
+</resources>
\ No newline at end of file
diff --git a/packages/SystemUI/customization/res/values-zu/strings.xml b/packages/SystemUI/customization/res/values-zu/strings.xml
new file mode 100644
index 0000000..c87c250a
--- /dev/null
+++ b/packages/SystemUI/customization/res/values-zu/strings.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/**
+ * Copyright (c) 2023, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+-->
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="clock_default_description" msgid="5309401440896597541">"Okuzenzakalelayo kwedijithali"</string>
+</resources>
\ No newline at end of file
diff --git a/packages/SystemUI/customization/res/values/dimens.xml b/packages/SystemUI/customization/res/values/dimens.xml
index 8eb8132..c574d1f 100644
--- a/packages/SystemUI/customization/res/values/dimens.xml
+++ b/packages/SystemUI/customization/res/values/dimens.xml
@@ -17,6 +17,7 @@
-->
<resources>
<!-- Clock maximum font size (dp is intentional, to prevent any further scaling) -->
+ <dimen name="presentation_clock_text_size">50dp</dimen>
<dimen name="large_clock_text_size">150dp</dimen>
<dimen name="small_clock_text_size">86dp</dimen>
diff --git a/packages/SystemUI/customization/res/values/strings.xml b/packages/SystemUI/customization/res/values/strings.xml
new file mode 100644
index 0000000..897c842
--- /dev/null
+++ b/packages/SystemUI/customization/res/values/strings.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/**
+ * Copyright (c) 2023, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <!-- default clock face name [CHAR LIMIT=NONE]-->
+ <string name="clock_default_name">Default</string>
+
+ <!-- default clock face description [CHAR LIMIT=NONE]-->
+ <string name="clock_default_description">Digital default</string>
+</resources>
\ No newline at end of file
diff --git a/packages/SystemUI/customization/src/com/android/systemui/shared/clocks/DefaultClockController.kt b/packages/SystemUI/customization/src/com/android/systemui/shared/clocks/DefaultClockController.kt
index b28920c..b076b2c 100644
--- a/packages/SystemUI/customization/src/com/android/systemui/shared/clocks/DefaultClockController.kt
+++ b/packages/SystemUI/customization/src/com/android/systemui/shared/clocks/DefaultClockController.kt
@@ -65,7 +65,13 @@
protected var onSecondaryDisplay: Boolean = false
override val events: DefaultClockEvents
- override val config = ClockConfig(DEFAULT_CLOCK_ID)
+ override val config: ClockConfig by lazy {
+ ClockConfig(
+ DEFAULT_CLOCK_ID,
+ resources.getString(R.string.clock_default_name),
+ resources.getString(R.string.clock_default_description)
+ )
+ }
init {
val parent = FrameLayout(ctx)
diff --git a/packages/SystemUI/customization/src/com/android/systemui/shared/clocks/DefaultClockProvider.kt b/packages/SystemUI/customization/src/com/android/systemui/shared/clocks/DefaultClockProvider.kt
index 949641a..dd52e39 100644
--- a/packages/SystemUI/customization/src/com/android/systemui/shared/clocks/DefaultClockProvider.kt
+++ b/packages/SystemUI/customization/src/com/android/systemui/shared/clocks/DefaultClockProvider.kt
@@ -25,7 +25,6 @@
import com.android.systemui.plugins.ClockSettings
private val TAG = DefaultClockProvider::class.simpleName
-const val DEFAULT_CLOCK_NAME = "Default Clock"
const val DEFAULT_CLOCK_ID = "DEFAULT"
/** Provides the default system clock */
@@ -35,8 +34,7 @@
val resources: Resources,
val hasStepClockAnimation: Boolean = false
) : ClockProvider {
- override fun getClocks(): List<ClockMetadata> =
- listOf(ClockMetadata(DEFAULT_CLOCK_ID, DEFAULT_CLOCK_NAME))
+ override fun getClocks(): List<ClockMetadata> = listOf(ClockMetadata(DEFAULT_CLOCK_ID))
override fun createClock(settings: ClockSettings): ClockController {
if (settings.clockId != DEFAULT_CLOCK_ID) {
diff --git a/packages/SystemUI/plugin/src/com/android/systemui/plugins/ClockProviderPlugin.kt b/packages/SystemUI/plugin/src/com/android/systemui/plugins/ClockProviderPlugin.kt
index e2f4793..485c27e 100644
--- a/packages/SystemUI/plugin/src/com/android/systemui/plugins/ClockProviderPlugin.kt
+++ b/packages/SystemUI/plugin/src/com/android/systemui/plugins/ClockProviderPlugin.kt
@@ -192,15 +192,18 @@
/** Some data about a clock design */
data class ClockMetadata(
val clockId: ClockId,
- val name: String,
-) {
- constructor(clockId: ClockId) : this(clockId, clockId) {}
-}
+)
/** Render configuration for the full clock. Modifies the way systemUI behaves with this clock. */
data class ClockConfig(
val id: String,
+ /** Localized name of the clock */
+ val name: String,
+
+ /** Localized accessibility description for the clock */
+ val description: String,
+
/** Transition to AOD should move smartspace like large clock instead of small clock */
val useAlternateSmartspaceAODTransition: Boolean = false,
diff --git a/packages/SystemUI/res-keyguard/layout/alternate_bouncer.xml b/packages/SystemUI/res-keyguard/layout/alternate_bouncer.xml
new file mode 100644
index 0000000..2187352
--- /dev/null
+++ b/packages/SystemUI/res-keyguard/layout/alternate_bouncer.xml
@@ -0,0 +1,34 @@
+<?xml version="1.0" encoding="utf-8"?><!--
+ ~ Copyright (C) 2023 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.
+ ~
+ -->
+
+<FrameLayout
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:sysui="http://schemas.android.com/apk/res-auto"
+ android:id="@+id/alternate_bouncer"
+ android:focusable="true"
+ android:clickable="true"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent">
+
+ <com.android.systemui.scrim.ScrimView
+ android:id="@+id/alternate_bouncer_scrim"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:importantForAccessibility="no"
+ sysui:ignoreRightInset="true"
+ />
+</FrameLayout>
diff --git a/packages/SystemUI/res-keyguard/layout/keyguard_clock_presentation.xml b/packages/SystemUI/res-keyguard/layout/keyguard_clock_presentation.xml
index 593f507f..f68ab81 100644
--- a/packages/SystemUI/res-keyguard/layout/keyguard_clock_presentation.xml
+++ b/packages/SystemUI/res-keyguard/layout/keyguard_clock_presentation.xml
@@ -16,22 +16,30 @@
*/
-->
-<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
+<androidx.constraintlayout.widget.ConstraintLayout
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="@+id/presentation"
android:layout_width="match_parent"
android:layout_height="match_parent">
<com.android.keyguard.KeyguardStatusView
android:id="@+id/clock"
- android:layout_width="410dp"
- android:layout_height="wrap_content"
+ android:layout_width="0dp"
+ android:layout_height="0dp"
android:layout_gravity="center"
- android:orientation="vertical">
+ android:orientation="vertical"
+ app:layout_constraintBottom_toBottomOf="parent"
+ app:layout_constraintDimensionRatio="1:1"
+ app:layout_constraintEnd_toEndOf="parent"
+ app:layout_constraintStart_toStartOf="parent"
+ app:layout_constraintTop_toTopOf="parent">
+
<include
android:id="@+id/keyguard_clock_container"
layout="@layout/keyguard_clock_switch"
android:layout_width="match_parent"
- android:layout_height="wrap_content" />
+ android:layout_height="wrap_content"/>
</com.android.keyguard.KeyguardStatusView>
-</FrameLayout>
+</androidx.constraintlayout.widget.ConstraintLayout>
\ No newline at end of file
diff --git a/packages/SystemUI/res/layout/super_notification_shade.xml b/packages/SystemUI/res/layout/super_notification_shade.xml
index d4b73a4..acee425 100644
--- a/packages/SystemUI/res/layout/super_notification_shade.xml
+++ b/packages/SystemUI/res/layout/super_notification_shade.xml
@@ -130,6 +130,11 @@
android:inflatedId="@+id/multi_shade"
android:layout="@layout/multi_shade" />
+ <include layout="@layout/alternate_bouncer"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:visibility="invisible" />
+
<com.android.systemui.biometrics.AuthRippleView
android:id="@+id/auth_ripple"
android:layout_width="match_parent"
diff --git a/packages/SystemUI/shared/src/com/android/systemui/dagger/qualifiers/DisplaySpecific.kt b/packages/SystemUI/shared/src/com/android/systemui/dagger/qualifiers/DisplaySpecific.kt
new file mode 100644
index 0000000..57a49c8
--- /dev/null
+++ b/packages/SystemUI/shared/src/com/android/systemui/dagger/qualifiers/DisplaySpecific.kt
@@ -0,0 +1,24 @@
+/*
+ * Copyright (C) 2023 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.dagger.qualifiers
+
+import java.lang.annotation.Documented
+import java.lang.annotation.Retention
+import java.lang.annotation.RetentionPolicy.RUNTIME
+import javax.inject.Qualifier
+
+/** Annotates a class that is display specific. */
+@Qualifier @Documented @Retention(RUNTIME) annotation class DisplaySpecific
diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/system/RecentsAnimationControllerCompat.java b/packages/SystemUI/shared/src/com/android/systemui/shared/system/RecentsAnimationControllerCompat.java
index 0094820..a6e04ce 100644
--- a/packages/SystemUI/shared/src/com/android/systemui/shared/system/RecentsAnimationControllerCompat.java
+++ b/packages/SystemUI/shared/src/com/android/systemui/shared/system/RecentsAnimationControllerCompat.java
@@ -23,6 +23,7 @@
import android.window.PictureInPictureSurfaceTransaction;
import android.window.TaskSnapshot;
+import com.android.internal.os.IResultReceiver;
import com.android.systemui.shared.recents.model.ThumbnailData;
public class RecentsAnimationControllerCompat {
@@ -89,11 +90,16 @@
* @param sendUserLeaveHint determines whether userLeaveHint will be set true to the previous
* app.
*/
- public void finish(boolean toHome, boolean sendUserLeaveHint) {
+ public void finish(boolean toHome, boolean sendUserLeaveHint, IResultReceiver finishCb) {
try {
- mAnimationController.finish(toHome, sendUserLeaveHint);
+ mAnimationController.finish(toHome, sendUserLeaveHint, finishCb);
} catch (RemoteException e) {
Log.e(TAG, "Failed to finish recents animation", e);
+ try {
+ finishCb.send(0, null);
+ } catch (Exception ex) {
+ // Local call, can ignore
+ }
}
}
diff --git a/packages/SystemUI/src/com/android/keyguard/ClockEventController.kt b/packages/SystemUI/src/com/android/keyguard/ClockEventController.kt
index 2f3c1f2..eb7a735 100644
--- a/packages/SystemUI/src/com/android/keyguard/ClockEventController.kt
+++ b/packages/SystemUI/src/com/android/keyguard/ClockEventController.kt
@@ -205,19 +205,19 @@
private var isRegistered = false
private var disposableHandle: DisposableHandle? = null
private val regionSamplingEnabled = featureFlags.isEnabled(REGION_SAMPLING)
-
+ private var largeClockOnSecondaryDisplay = false
private fun updateColors() {
if (regionSamplingEnabled) {
clock?.let { clock ->
smallRegionSampler?.let {
- smallClockIsDark = it.currentRegionDarkness().isDark
- clock.smallClock.events.onRegionDarknessChanged(smallClockIsDark)
+ val isRegionDark = it.currentRegionDarkness().isDark
+ clock.smallClock.events.onRegionDarknessChanged(isRegionDark)
}
largeRegionSampler?.let {
- largeClockIsDark = it.currentRegionDarkness().isDark
- clock.largeClock.events.onRegionDarknessChanged(largeClockIsDark)
+ val isRegionDark = it.currentRegionDarkness().isDark
+ clock.largeClock.events.onRegionDarknessChanged(isRegionDark)
}
}
return
@@ -225,12 +225,12 @@
val isLightTheme = TypedValue()
context.theme.resolveAttribute(android.R.attr.isLightTheme, isLightTheme, true)
- smallClockIsDark = isLightTheme.data == 0
- largeClockIsDark = isLightTheme.data == 0
+ val isRegionDark = isLightTheme.data == 0
clock?.run {
- smallClock.events.onRegionDarknessChanged(smallClockIsDark)
- largeClock.events.onRegionDarknessChanged(largeClockIsDark)
+ Log.i(TAG, "Region isDark: $isRegionDark")
+ smallClock.events.onRegionDarknessChanged(isRegionDark)
+ largeClock.events.onRegionDarknessChanged(isRegionDark)
}
}
protected open fun createRegionSampler(
@@ -260,9 +260,6 @@
get() = isKeyguardVisible && dozeAmount < DOZE_TICKRATE_THRESHOLD
private var cachedWeatherData: WeatherData? = null
- private var smallClockIsDark = true
- private var largeClockIsDark = true
-
private val configListener =
object : ConfigurationController.ConfigurationListener {
override fun onThemeChanged() {
@@ -381,6 +378,19 @@
?.removeOnAttachStateChangeListener(largeClockOnAttachStateChangeListener)
}
+ /**
+ * Sets this clock as showing in a secondary display.
+ *
+ * Not that this is not necessarily needed, as we could get the displayId from [Context]
+ * directly and infere [largeClockOnSecondaryDisplay] from the id being different than the
+ * default display one. However, if we do so, current screenshot tests would not work, as they
+ * pass an activity context always from the default display.
+ */
+ fun setLargeClockOnSecondaryDisplay(onSecondaryDisplay: Boolean) {
+ largeClockOnSecondaryDisplay = onSecondaryDisplay
+ updateFontSizes()
+ }
+
private fun updateTimeListeners() {
smallTimeListener?.stop()
largeTimeListener?.stop()
@@ -403,9 +413,15 @@
smallClock.events.onFontSettingChanged(
resources.getDimensionPixelSize(R.dimen.small_clock_text_size).toFloat()
)
- largeClock.events.onFontSettingChanged(
- resources.getDimensionPixelSize(R.dimen.large_clock_text_size).toFloat()
- )
+ largeClock.events.onFontSettingChanged(getLargeClockSizePx())
+ }
+ }
+
+ private fun getLargeClockSizePx(): Float {
+ return if (largeClockOnSecondaryDisplay) {
+ resources.getDimensionPixelSize(R.dimen.presentation_clock_text_size).toFloat()
+ } else {
+ resources.getDimensionPixelSize(R.dimen.large_clock_text_size).toFloat()
}
}
diff --git a/packages/SystemUI/src/com/android/keyguard/ConnectedDisplayKeyguardPresentation.kt b/packages/SystemUI/src/com/android/keyguard/ConnectedDisplayKeyguardPresentation.kt
index d677a15..dec7d79 100644
--- a/packages/SystemUI/src/com/android/keyguard/ConnectedDisplayKeyguardPresentation.kt
+++ b/packages/SystemUI/src/com/android/keyguard/ConnectedDisplayKeyguardPresentation.kt
@@ -68,10 +68,13 @@
clock = requireViewById(R.id.clock)
keyguardStatusViewController =
- keyguardStatusViewComponentFactory.build(clock).keyguardStatusViewController.apply {
- setDisplayedOnSecondaryDisplay()
- init()
- }
+ keyguardStatusViewComponentFactory
+ .build(clock, display)
+ .keyguardStatusViewController
+ .apply {
+ setDisplayedOnSecondaryDisplay()
+ init()
+ }
}
/** [ConnectedDisplayKeyguardPresentation] factory. */
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardClockSwitchController.java b/packages/SystemUI/src/com/android/keyguard/KeyguardClockSwitchController.java
index ff8e489..3c8301f 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardClockSwitchController.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardClockSwitchController.java
@@ -84,7 +84,6 @@
private final DumpManager mDumpManager;
private final ClockEventController mClockEventController;
private final LogBuffer mLogBuffer;
-
private FrameLayout mSmallClockFrame; // top aligned clock
private FrameLayout mLargeClockFrame; // centered clock
@@ -265,6 +264,7 @@
if (mShownOnSecondaryDisplay) {
mView.setLargeClockOnSecondaryDisplay(true);
+ mClockEventController.setLargeClockOnSecondaryDisplay(true);
displayClock(LARGE, /* animate= */ false);
hideSliceViewAndNotificationIconContainer();
return;
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardDisplayManager.java b/packages/SystemUI/src/com/android/keyguard/KeyguardDisplayManager.java
index 9c015fe..8a6f101 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardDisplayManager.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardDisplayManager.java
@@ -419,7 +419,7 @@
mClock.post(mMoveTextRunnable);
mKeyguardClockSwitchController = mKeyguardStatusViewComponentFactory
- .build(findViewById(R.id.clock))
+ .build(findViewById(R.id.clock), getDisplay())
.getKeyguardClockSwitchController();
mKeyguardClockSwitchController.setOnlyClock(true);
diff --git a/packages/SystemUI/src/com/android/keyguard/LockIconView.java b/packages/SystemUI/src/com/android/keyguard/LockIconView.java
index 1d2d77f..40d0be1 100644
--- a/packages/SystemUI/src/com/android/keyguard/LockIconView.java
+++ b/packages/SystemUI/src/com/android/keyguard/LockIconView.java
@@ -18,6 +18,7 @@
import static android.view.ViewGroup.LayoutParams.MATCH_PARENT;
+import android.annotation.SuppressLint;
import android.content.Context;
import android.content.res.ColorStateList;
import android.graphics.Color;
@@ -68,6 +69,7 @@
private boolean mUseBackground = false;
private float mDozeAmount = 0f;
+ @SuppressLint("ClickableViewAccessibility")
public LockIconView(Context context, AttributeSet attrs) {
super(context, attrs);
mSensorRect = new RectF();
diff --git a/packages/SystemUI/src/com/android/keyguard/LockIconViewController.java b/packages/SystemUI/src/com/android/keyguard/LockIconViewController.java
index 9b00b5f..0d3f726 100644
--- a/packages/SystemUI/src/com/android/keyguard/LockIconViewController.java
+++ b/packages/SystemUI/src/com/android/keyguard/LockIconViewController.java
@@ -29,6 +29,7 @@
import static com.android.systemui.flags.Flags.ONE_WAY_HAPTICS_API_MIGRATION;
import static com.android.systemui.util.kotlin.JavaAdapterKt.collectFlow;
+import android.annotation.SuppressLint;
import android.content.Context;
import android.content.res.Configuration;
import android.content.res.Resources;
@@ -57,11 +58,11 @@
import androidx.core.view.accessibility.AccessibilityNodeInfoCompat;
import com.android.systemui.Dumpable;
-import com.android.systemui.res.R;
import com.android.systemui.biometrics.AuthController;
import com.android.systemui.biometrics.AuthRippleController;
import com.android.systemui.biometrics.UdfpsController;
import com.android.systemui.biometrics.shared.model.UdfpsOverlayParams;
+import com.android.systemui.bouncer.domain.interactor.BouncerInteractor;
import com.android.systemui.bouncer.domain.interactor.PrimaryBouncerInteractor;
import com.android.systemui.dagger.SysUISingleton;
import com.android.systemui.dagger.qualifiers.Main;
@@ -73,12 +74,16 @@
import com.android.systemui.keyguard.shared.model.TransitionStep;
import com.android.systemui.plugins.FalsingManager;
import com.android.systemui.plugins.statusbar.StatusBarStateController;
+import com.android.systemui.res.R;
+import com.android.systemui.scene.shared.flag.SceneContainerFlags;
import com.android.systemui.statusbar.StatusBarState;
import com.android.systemui.statusbar.VibratorHelper;
import com.android.systemui.statusbar.policy.ConfigurationController;
import com.android.systemui.statusbar.policy.KeyguardStateController;
import com.android.systemui.util.concurrency.DelayableExecutor;
+import dagger.Lazy;
+
import java.io.PrintWriter;
import java.util.Objects;
import java.util.function.Consumer;
@@ -127,6 +132,8 @@
@NonNull private final KeyguardTransitionInteractor mTransitionInteractor;
@NonNull private final KeyguardInteractor mKeyguardInteractor;
@NonNull private final View.AccessibilityDelegate mAccessibilityDelegate;
+ @NonNull private final Lazy<BouncerInteractor> mBouncerInteractor;
+ @NonNull private final SceneContainerFlags mSceneContainerFlags;
// Tracks the velocity of a touch to help filter out the touches that move too fast.
private VelocityTracker mVelocityTracker;
@@ -203,7 +210,9 @@
@NonNull KeyguardInteractor keyguardInteractor,
@NonNull FeatureFlags featureFlags,
PrimaryBouncerInteractor primaryBouncerInteractor,
- Context context
+ Context context,
+ Lazy<BouncerInteractor> bouncerInteractor,
+ SceneContainerFlags sceneContainerFlags
) {
mStatusBarStateController = statusBarStateController;
mKeyguardUpdateMonitor = keyguardUpdateMonitor;
@@ -232,6 +241,8 @@
dumpManager.registerDumpable(TAG, this);
mResources = resources;
mContext = context;
+ mBouncerInteractor = bouncerInteractor;
+ mSceneContainerFlags = sceneContainerFlags;
mAccessibilityDelegate = new View.AccessibilityDelegate() {
private final AccessibilityNodeInfo.AccessibilityAction mAccessibilityAuthenticateHint =
@@ -256,6 +267,7 @@
}
/** Sets the LockIconView to the controller and rebinds any that depend on it. */
+ @SuppressLint("ClickableViewAccessibility")
public void setLockIconView(LockIconView lockIconView) {
mView = lockIconView;
mView.setImageDrawable(mIcon);
@@ -305,6 +317,8 @@
if (lockIconView.isAttachedToWindow()) {
registerCallbacks();
}
+
+ lockIconView.setOnTouchListener((view, motionEvent) -> onTouchEvent(motionEvent));
}
private void registerCallbacks() {
@@ -635,19 +649,18 @@
};
/**
- * Handles the touch if it is within the lock icon view and {@link #isActionable()} is true.
+ * Handles the touch if {@link #isActionable()} is true.
* Subsequently, will trigger {@link #onLongPress()} if a touch is continuously in the lock icon
* area for {@link #mLongPressTimeout} ms.
*
* Touch speed debouncing mimics logic from the velocity tracker in {@link UdfpsController}.
*/
- public boolean onTouchEvent(MotionEvent event, Runnable onGestureDetectedRunnable) {
- if (!onInterceptTouchEvent(event)) {
+ private boolean onTouchEvent(MotionEvent event) {
+ if (!actionableDownEventStartedOnView(event)) {
cancelTouches();
return false;
}
- mOnGestureDetectedRunnable = onGestureDetectedRunnable;
switch(event.getActionMasked()) {
case MotionEvent.ACTION_DOWN:
case MotionEvent.ACTION_HOVER_ENTER:
@@ -700,12 +713,8 @@
return true;
}
- /**
- * Intercepts the touch if the onDown event and current event are within this lock icon view's
- * bounds.
- */
- public boolean onInterceptTouchEvent(MotionEvent event) {
- if (!inLockIconArea(event) || !isActionable()) {
+ private boolean actionableDownEventStartedOnView(MotionEvent event) {
+ if (!isActionable()) {
return false;
}
@@ -716,7 +725,8 @@
return mDownDetected;
}
- private void onLongPress() {
+ @VisibleForTesting
+ protected void onLongPress() {
cancelTouches();
if (mFalsingManager.isFalseLongTap(FalsingManager.LOW_PENALTY)) {
Log.v(TAG, "lock icon long-press rejected by the falsing manager.");
@@ -729,14 +739,15 @@
mAuthRippleController.showUnlockRipple(FINGERPRINT);
}
updateVisibility();
- if (mOnGestureDetectedRunnable != null) {
- mOnGestureDetectedRunnable.run();
- }
// play device entry haptic (consistent with UDFPS controller longpress)
vibrateOnLongPress();
- mKeyguardViewController.showPrimaryBouncer(/* scrim */ true);
+ if (mSceneContainerFlags.isEnabled()) {
+ mBouncerInteractor.get().showOrUnlockDevice(null);
+ } else {
+ mKeyguardViewController.showPrimaryBouncer(/* scrim */ true);
+ }
}
@@ -751,12 +762,6 @@
}
}
- private boolean inLockIconArea(MotionEvent event) {
- mView.getHitRect(mSensorTouchLocation);
- return mSensorTouchLocation.contains((int) event.getX(), (int) event.getY())
- && mView.getVisibility() == View.VISIBLE;
- }
-
private boolean isActionable() {
if (mIsBouncerShowing) {
Log.v(TAG, "lock icon long-press ignored, bouncer already showing.");
@@ -834,6 +839,19 @@
}
};
+ /**
+ * Whether the lock icon will handle a touch while dozing.
+ */
+ public boolean willHandleTouchWhileDozing(MotionEvent event) {
+ // is in lock icon area
+ mView.getHitRect(mSensorTouchLocation);
+ final boolean inLockIconArea =
+ mSensorTouchLocation.contains((int) event.getX(), (int) event.getY())
+ && mView.getVisibility() == View.VISIBLE;
+
+ return inLockIconArea && actionableDownEventStartedOnView(event);
+ }
+
private final View.OnClickListener mA11yClickListener = v -> onLongPress();
private final AccessibilityManager.AccessibilityStateChangeListener
diff --git a/packages/SystemUI/src/com/android/keyguard/dagger/KeyguardDisplayModule.kt b/packages/SystemUI/src/com/android/keyguard/dagger/KeyguardDisplayModule.kt
new file mode 100644
index 0000000..c581788
--- /dev/null
+++ b/packages/SystemUI/src/com/android/keyguard/dagger/KeyguardDisplayModule.kt
@@ -0,0 +1,40 @@
+package com.android.keyguard.dagger
+
+import android.content.Context
+import android.content.res.Resources
+import android.view.Display
+import com.android.systemui.dagger.qualifiers.DisplaySpecific
+import dagger.BindsOptionalOf
+import dagger.Module
+import dagger.Provides
+import java.util.Optional
+
+/**
+ * Binds display specific context and resources.
+ *
+ * When a [Display] is available in the scope, binds a [DisplaySpecific] [Context] and [Resources].
+ * When not available, the default display context and resources are used.
+ */
+@Module
+abstract class KeyguardDisplayModule {
+
+ @BindsOptionalOf abstract fun optionalDisplay(): Display
+
+ companion object {
+ @Provides
+ @DisplaySpecific
+ fun getDisplayContext(context: Context, display: Optional<Display>): Context {
+ return if (display.isPresent) {
+ context.createDisplayContext(display.get())
+ } else {
+ context
+ }
+ }
+
+ @Provides
+ @DisplaySpecific
+ fun getDisplayResources(@DisplaySpecific context: Context): Resources {
+ return context.resources
+ }
+ }
+}
diff --git a/packages/SystemUI/src/com/android/keyguard/dagger/KeyguardStatusViewComponent.java b/packages/SystemUI/src/com/android/keyguard/dagger/KeyguardStatusViewComponent.java
index d342377..f3014f1 100644
--- a/packages/SystemUI/src/com/android/keyguard/dagger/KeyguardStatusViewComponent.java
+++ b/packages/SystemUI/src/com/android/keyguard/dagger/KeyguardStatusViewComponent.java
@@ -16,6 +16,8 @@
package com.android.keyguard.dagger;
+import android.view.Display;
+
import com.android.keyguard.KeyguardClockSwitchController;
import com.android.keyguard.KeyguardStatusView;
import com.android.keyguard.KeyguardStatusViewController;
@@ -28,13 +30,17 @@
*
* TODO: unify this with {@link KeyguardStatusBarViewComponent}
*/
-@Subcomponent(modules = {KeyguardStatusViewModule.class})
+@Subcomponent(modules = {KeyguardStatusViewModule.class, KeyguardDisplayModule.class})
@KeyguardStatusViewScope
public interface KeyguardStatusViewComponent {
/** Simple factory for {@link KeyguardStatusViewComponent}. */
@Subcomponent.Factory
interface Factory {
- KeyguardStatusViewComponent build(@BindsInstance KeyguardStatusView presentation);
+ /** Creates {@link KeyguardStatusViewComponent} for a given display. */
+ KeyguardStatusViewComponent build(
+ @BindsInstance KeyguardStatusView presentation,
+ @BindsInstance Display display
+ );
}
/** Builds a {@link com.android.keyguard.KeyguardClockSwitchController}. */
diff --git a/packages/SystemUI/src/com/android/systemui/Dependency.java b/packages/SystemUI/src/com/android/systemui/Dependency.java
index 0180384..7739021 100644
--- a/packages/SystemUI/src/com/android/systemui/Dependency.java
+++ b/packages/SystemUI/src/com/android/systemui/Dependency.java
@@ -87,7 +87,6 @@
import com.android.systemui.statusbar.notification.collection.render.GroupExpansionManager;
import com.android.systemui.statusbar.notification.collection.render.GroupMembershipManager;
import com.android.systemui.statusbar.notification.logging.NotificationLogger;
-import com.android.systemui.statusbar.notification.row.NotificationGutsManager;
import com.android.systemui.statusbar.notification.stack.AmbientState;
import com.android.systemui.statusbar.notification.stack.NotificationSectionsManager;
import com.android.systemui.statusbar.phone.AutoHideController;
@@ -130,14 +129,14 @@
import com.android.systemui.util.leak.LeakReporter;
import com.android.systemui.util.sensors.AsyncSensorManager;
+import dagger.Lazy;
+
import java.util.concurrent.Executor;
import java.util.function.Consumer;
import javax.inject.Inject;
import javax.inject.Named;
-import dagger.Lazy;
-
/**
* Class to handle ugly dependencies throughout sysui until we determine the
* long-term dependency injection solution.
@@ -298,7 +297,6 @@
@Inject Lazy<AccessibilityFloatingMenuController> mAccessibilityFloatingMenuController;
@Inject Lazy<StatusBarStateController> mStatusBarStateController;
@Inject Lazy<NotificationLockscreenUserManager> mNotificationLockscreenUserManager;
- @Inject Lazy<NotificationGutsManager> mNotificationGutsManager;
@Inject Lazy<NotificationMediaManager> mNotificationMediaManager;
@Inject Lazy<NotificationRemoteInputManager> mNotificationRemoteInputManager;
@Inject Lazy<SmartReplyConstants> mSmartReplyConstants;
@@ -498,7 +496,6 @@
mProviders.put(NotificationLockscreenUserManager.class,
mNotificationLockscreenUserManager::get);
mProviders.put(NotificationMediaManager.class, mNotificationMediaManager::get);
- mProviders.put(NotificationGutsManager.class, mNotificationGutsManager::get);
mProviders.put(NotificationRemoteInputManager.class,
mNotificationRemoteInputManager::get);
mProviders.put(SmartReplyConstants.class, mSmartReplyConstants::get);
diff --git a/packages/SystemUI/src/com/android/systemui/bouncer/ui/viewmodel/PinInputViewModel.kt b/packages/SystemUI/src/com/android/systemui/bouncer/ui/viewmodel/PinInputViewModel.kt
index 4efc21b..4b78e9e 100644
--- a/packages/SystemUI/src/com/android/systemui/bouncer/ui/viewmodel/PinInputViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/bouncer/ui/viewmodel/PinInputViewModel.kt
@@ -35,10 +35,8 @@
* The input is guaranteed to always contain a initial [ClearAll] token as a sentinel, thus clients
* can always assume there is a 'ClearAll' watermark available.
*/
-data class PinInputViewModel
-internal constructor(
- @get:VisibleForTesting(otherwise = VisibleForTesting.PRIVATE)
- internal val input: List<EntryToken>
+data class PinInputViewModel(
+ @get:VisibleForTesting(otherwise = VisibleForTesting.PRIVATE) val input: List<EntryToken>
) {
init {
require(input.firstOrNull() is ClearAll) { "input does not begin with a ClearAll token" }
@@ -132,8 +130,7 @@
val sequenceNumber: Int
/** The pin bouncer [input] as digits 0-9. */
- data class Digit
- internal constructor(val input: Int, override val sequenceNumber: Int = nextSequenceNumber++) :
+ data class Digit(val input: Int, override val sequenceNumber: Int = nextSequenceNumber++) :
EntryToken {
init {
check(input in 0..9)
@@ -144,8 +141,7 @@
* Marker to indicate the input is completely cleared, and subsequent [EntryToken]s mark a new
* pin entry.
*/
- data class ClearAll
- internal constructor(override val sequenceNumber: Int = nextSequenceNumber++) : EntryToken
+ data class ClearAll(override val sequenceNumber: Int = nextSequenceNumber++) : EntryToken
override fun compareTo(other: EntryToken): Int =
compareValuesBy(this, other, EntryToken::sequenceNumber)
diff --git a/packages/SystemUI/src/com/android/systemui/classifier/FalsingCollectorFake.java b/packages/SystemUI/src/com/android/systemui/classifier/FalsingCollectorFake.java
index c0ee71c..0dfaf0f 100644
--- a/packages/SystemUI/src/com/android/systemui/classifier/FalsingCollectorFake.java
+++ b/packages/SystemUI/src/com/android/systemui/classifier/FalsingCollectorFake.java
@@ -18,8 +18,15 @@
import android.view.MotionEvent;
+import javax.inject.Inject;
+
/** */
public class FalsingCollectorFake implements FalsingCollector {
+
+ @Inject
+ public FalsingCollectorFake() {
+ }
+
@Override
public void onSuccessfulUnlock() {
}
diff --git a/packages/SystemUI/src/com/android/systemui/dagger/ReferenceSysUIComponent.java b/packages/SystemUI/src/com/android/systemui/dagger/ReferenceSysUIComponent.java
index 046ccf16..a90980f 100644
--- a/packages/SystemUI/src/com/android/systemui/dagger/ReferenceSysUIComponent.java
+++ b/packages/SystemUI/src/com/android/systemui/dagger/ReferenceSysUIComponent.java
@@ -18,7 +18,6 @@
import com.android.systemui.globalactions.ShutdownUiModule;
import com.android.systemui.keyguard.CustomizationProvider;
-import com.android.systemui.shade.ShadeModule;
import com.android.systemui.statusbar.NotificationInsetsModule;
import com.android.systemui.statusbar.QsFrameTranslateModule;
@@ -33,7 +32,6 @@
DependencyProvider.class,
NotificationInsetsModule.class,
QsFrameTranslateModule.class,
- ShadeModule.class,
ShutdownUiModule.class,
SystemUIBinder.class,
SystemUIModule.class,
diff --git a/packages/SystemUI/src/com/android/systemui/dagger/ReferenceSystemUIModule.java b/packages/SystemUI/src/com/android/systemui/dagger/ReferenceSystemUIModule.java
index 9e5fd55..1dd4abf 100644
--- a/packages/SystemUI/src/com/android/systemui/dagger/ReferenceSystemUIModule.java
+++ b/packages/SystemUI/src/com/android/systemui/dagger/ReferenceSystemUIModule.java
@@ -21,12 +21,9 @@
import android.content.Context;
import android.hardware.SensorPrivacyManager;
-import android.os.Handler;
-import com.android.internal.logging.UiEventLogger;
import com.android.keyguard.KeyguardViewController;
import com.android.systemui.battery.BatterySaverModule;
-import com.android.systemui.dagger.qualifiers.Main;
import com.android.systemui.dock.DockManager;
import com.android.systemui.dock.DockManagerImpl;
import com.android.systemui.doze.DozeHost;
@@ -34,7 +31,6 @@
import com.android.systemui.navigationbar.NavigationBarControllerModule;
import com.android.systemui.navigationbar.gestural.GestureModule;
import com.android.systemui.plugins.qs.QSFactory;
-import com.android.systemui.plugins.statusbar.StatusBarStateController;
import com.android.systemui.power.dagger.PowerModule;
import com.android.systemui.qs.dagger.QSModule;
import com.android.systemui.qs.tileimpl.QSFactoryImpl;
@@ -45,7 +41,7 @@
import com.android.systemui.screenshot.ReferenceScreenshotModule;
import com.android.systemui.settings.dagger.MultiUserUtilsModule;
import com.android.systemui.shade.NotificationShadeWindowControllerImpl;
-import com.android.systemui.shade.ShadeExpansionStateManager;
+import com.android.systemui.shade.ShadeModule;
import com.android.systemui.statusbar.CommandQueue;
import com.android.systemui.statusbar.KeyboardShortcutsModule;
import com.android.systemui.statusbar.NotificationLockscreenUserManager;
@@ -53,20 +49,13 @@
import com.android.systemui.statusbar.NotificationShadeWindowController;
import com.android.systemui.statusbar.dagger.StartCentralSurfacesModule;
import com.android.systemui.statusbar.events.StatusBarEventsModule;
-import com.android.systemui.statusbar.notification.collection.provider.VisualStabilityProvider;
-import com.android.systemui.statusbar.notification.collection.render.GroupMembershipManager;
import com.android.systemui.statusbar.phone.DozeServiceHost;
-import com.android.systemui.statusbar.phone.HeadsUpManagerPhone;
-import com.android.systemui.statusbar.phone.KeyguardBypassController;
+import com.android.systemui.statusbar.phone.HeadsUpModule;
import com.android.systemui.statusbar.phone.StatusBarKeyguardViewManager;
import com.android.systemui.statusbar.phone.fragment.CollapsedStatusBarFragmentStartableModule;
-import com.android.systemui.statusbar.policy.AccessibilityManagerWrapper;
import com.android.systemui.statusbar.policy.AospPolicyModule;
-import com.android.systemui.statusbar.policy.ConfigurationController;
import com.android.systemui.statusbar.policy.DeviceProvisionedController;
import com.android.systemui.statusbar.policy.DeviceProvisionedControllerImpl;
-import com.android.systemui.statusbar.policy.HeadsUpManager;
-import com.android.systemui.statusbar.policy.HeadsUpManagerLogger;
import com.android.systemui.statusbar.policy.IndividualSensorPrivacyController;
import com.android.systemui.statusbar.policy.IndividualSensorPrivacyControllerImpl;
import com.android.systemui.statusbar.policy.SensorPrivacyController;
@@ -100,11 +89,13 @@
BatterySaverModule.class,
CollapsedStatusBarFragmentStartableModule.class,
GestureModule.class,
+ HeadsUpModule.class,
MediaModule.class,
MultiUserUtilsModule.class,
NavigationBarControllerModule.class,
PowerModule.class,
QSModule.class,
+ ShadeModule.class,
ReferenceScreenshotModule.class,
RotationLockModule.class,
SceneContainerFrameworkModule.class,
@@ -161,38 +152,6 @@
return true;
}
- @SysUISingleton
- @Provides
- static HeadsUpManagerPhone provideHeadsUpManagerPhone(
- Context context,
- HeadsUpManagerLogger headsUpManagerLogger,
- StatusBarStateController statusBarStateController,
- KeyguardBypassController bypassController,
- GroupMembershipManager groupManager,
- VisualStabilityProvider visualStabilityProvider,
- ConfigurationController configurationController,
- @Main Handler handler,
- AccessibilityManagerWrapper accessibilityManagerWrapper,
- UiEventLogger uiEventLogger,
- ShadeExpansionStateManager shadeExpansionStateManager) {
- return new HeadsUpManagerPhone(
- context,
- headsUpManagerLogger,
- statusBarStateController,
- bypassController,
- groupManager,
- visualStabilityProvider,
- configurationController,
- handler,
- accessibilityManagerWrapper,
- uiEventLogger,
- shadeExpansionStateManager
- );
- }
-
- @Binds
- abstract HeadsUpManager bindHeadsUpManagerPhone(HeadsUpManagerPhone headsUpManagerPhone);
-
@Provides
@SysUISingleton
static Recents provideRecents(Context context, RecentsImplementation recentsImplementation,
diff --git a/packages/SystemUI/src/com/android/systemui/dagger/SystemUICoreStartableModule.kt b/packages/SystemUI/src/com/android/systemui/dagger/SystemUICoreStartableModule.kt
index d89332d..5d6949b 100644
--- a/packages/SystemUI/src/com/android/systemui/dagger/SystemUICoreStartableModule.kt
+++ b/packages/SystemUI/src/com/android/systemui/dagger/SystemUICoreStartableModule.kt
@@ -37,6 +37,7 @@
import com.android.systemui.keyguard.KeyguardViewConfigurator
import com.android.systemui.keyguard.KeyguardViewMediator
import com.android.systemui.keyguard.data.quickaffordance.MuteQuickAffordanceCoreStartable
+import com.android.systemui.keyguard.ui.binder.AlternateBouncerBinder
import com.android.systemui.keyguard.ui.binder.KeyguardDismissActionBinder
import com.android.systemui.keyguard.ui.binder.KeyguardDismissBinder
import com.android.systemui.log.SessionTracker
@@ -92,6 +93,11 @@
@ClassKey(AuthController::class)
abstract fun bindAuthController(service: AuthController): CoreStartable
+ @Binds
+ @IntoMap
+ @ClassKey(AlternateBouncerBinder::class)
+ abstract fun bindAlternateBouncerBinder(impl: AlternateBouncerBinder): CoreStartable
+
/** Inject into BiometricNotificationService */
@Binds
@IntoMap
diff --git a/packages/SystemUI/src/com/android/systemui/flags/Flags.kt b/packages/SystemUI/src/com/android/systemui/flags/Flags.kt
index 74ee206..f6f24e0 100644
--- a/packages/SystemUI/src/com/android/systemui/flags/Flags.kt
+++ b/packages/SystemUI/src/com/android/systemui/flags/Flags.kt
@@ -144,11 +144,6 @@
"lockscreen_custom_clocks"
)
- // TODO(b/275694445): Tracking Bug
- @JvmField
- val LOCKSCREEN_WITHOUT_SECURE_LOCK_WHEN_DREAMING =
- releasedFlag("lockscreen_without_secure_lock_when_dreaming")
-
// TODO(b/286092087): Tracking Bug
@JvmField
val ENABLE_SYSTEM_UI_DREAM_CONTROLLER = unreleasedFlag("enable_system_ui_dream_controller")
@@ -309,6 +304,11 @@
@JvmField
val WALLPAPER_PICKER_PREVIEW_ANIMATION = releasedFlag("wallpaper_picker_preview_animation")
+ /** Flag to enable rest to unlock feature. */
+ // TODO(b/303672286): Tracking bug
+ @JvmField
+ val REST_TO_UNLOCK: UnreleasedFlag = unreleasedFlag("rest_to_unlock")
+
/**
* TODO(b/278086361): Tracking bug
* Complete rewrite of the interactions between System UI and Window Manager involving keyguard
@@ -331,7 +331,7 @@
/** Flag to use a separate view for the alternate bouncer. */
// TODO(b/300440924): Tracking bug
@JvmField
- val ALTERNATE_BOUNCER_REFACTOR: UnreleasedFlag = unreleasedFlag("alternate_bouncer_view")
+ val ALTERNATE_BOUNCER_VIEW: UnreleasedFlag = unreleasedFlag("alternate_bouncer_view")
// 300 - power menu
// TODO(b/254512600): Tracking Bug
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewConfigurator.kt b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewConfigurator.kt
index f500017..86bf368 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewConfigurator.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewConfigurator.kt
@@ -82,7 +82,8 @@
val statusViewComponent =
keyguardStatusViewComponentFactory.build(
LayoutInflater.from(context).inflate(R.layout.keyguard_status_view, null)
- as KeyguardStatusView
+ as KeyguardStatusView,
+ context.display
)
val controller = statusViewComponent.keyguardStatusViewController
controller.init()
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
index 7678f4d..39742a0 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
@@ -171,6 +171,8 @@
import com.android.systemui.wallpapers.data.repository.WallpaperRepository;
import com.android.wm.shell.keyguard.KeyguardTransitions;
+import dagger.Lazy;
+
import java.io.PrintWriter;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
@@ -180,7 +182,8 @@
import java.util.concurrent.Executor;
import java.util.function.Consumer;
-import dagger.Lazy;
+
+
import kotlinx.coroutines.CoroutineDispatcher;
/**
@@ -1933,11 +1936,7 @@
public void onDreamingStarted() {
mUpdateMonitor.dispatchDreamingStarted();
synchronized (this) {
- final boolean alwaysShowKeyguard =
- mFeatureFlags.isEnabled(Flags.LOCKSCREEN_WITHOUT_SECURE_LOCK_WHEN_DREAMING);
- if (mDeviceInteractive
- && (alwaysShowKeyguard ||
- mLockPatternUtils.isSecure(KeyguardUpdateMonitor.getCurrentUser()))) {
+ if (mDeviceInteractive) {
doKeyguardLaterLocked();
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/dagger/KeyguardModule.java b/packages/SystemUI/src/com/android/systemui/keyguard/dagger/KeyguardModule.java
index 03c166c..41bde91 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/dagger/KeyguardModule.java
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/dagger/KeyguardModule.java
@@ -28,6 +28,7 @@
import com.android.keyguard.KeyguardUpdateMonitor;
import com.android.keyguard.KeyguardViewController;
import com.android.keyguard.ViewMediatorCallback;
+import com.android.keyguard.dagger.KeyguardDisplayModule;
import com.android.keyguard.dagger.KeyguardQsUserSwitchComponent;
import com.android.keyguard.dagger.KeyguardStatusBarViewComponent;
import com.android.keyguard.dagger.KeyguardStatusViewComponent;
@@ -100,6 +101,7 @@
KeyguardDataQuickAffordanceModule.class,
KeyguardRepositoryModule.class,
KeyguardFaceAuthModule.class,
+ KeyguardDisplayModule.class,
StartKeyguardTransitionModule.class,
ResourceTrimmerModule.class,
})
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromAlternateBouncerTransitionInteractor.kt b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromAlternateBouncerTransitionInteractor.kt
index 3ccf446..d06f31f 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromAlternateBouncerTransitionInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromAlternateBouncerTransitionInteractor.kt
@@ -32,6 +32,7 @@
import kotlinx.coroutines.flow.onEach
import kotlinx.coroutines.launch
import javax.inject.Inject
+import kotlin.time.Duration.Companion.milliseconds
@SysUISingleton
class FromAlternateBouncerTransitionInteractor
@@ -129,11 +130,11 @@
override fun getDefaultAnimatorForTransitionsToState(toState: KeyguardState): ValueAnimator {
return ValueAnimator().apply {
interpolator = Interpolators.LINEAR
- duration = TRANSITION_DURATION_MS
+ duration = TRANSITION_DURATION_MS.inWholeMilliseconds
}
}
companion object {
- private const val TRANSITION_DURATION_MS = 300L
+ val TRANSITION_DURATION_MS = 300.milliseconds
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardFaceAuthInteractor.kt b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardFaceAuthInteractor.kt
index e57c919..89aca76 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardFaceAuthInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardFaceAuthInteractor.kt
@@ -61,6 +61,7 @@
fun onSwipeUpOnBouncer()
fun onPrimaryBouncerUserInput()
fun onAccessibilityAction()
+ fun onWalletLaunched()
}
/**
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/NoopKeyguardFaceAuthInteractor.kt b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/NoopKeyguardFaceAuthInteractor.kt
index 596a1c0..f38bb2b 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/NoopKeyguardFaceAuthInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/NoopKeyguardFaceAuthInteractor.kt
@@ -61,4 +61,5 @@
override fun onSwipeUpOnBouncer() {}
override fun onPrimaryBouncerUserInput() {}
override fun onAccessibilityAction() {}
+ override fun onWalletLaunched() = Unit
}
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/SystemUIKeyguardFaceAuthInteractor.kt b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/SystemUIKeyguardFaceAuthInteractor.kt
index ef1d5ac..797dec2 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/SystemUIKeyguardFaceAuthInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/SystemUIKeyguardFaceAuthInteractor.kt
@@ -24,6 +24,7 @@
import com.android.systemui.CoreStartable
import com.android.systemui.biometrics.data.repository.FacePropertyRepository
import com.android.systemui.biometrics.shared.model.LockoutMode
+import com.android.systemui.biometrics.shared.model.SensorStrength
import com.android.systemui.bouncer.domain.interactor.AlternateBouncerInteractor
import com.android.systemui.bouncer.domain.interactor.PrimaryBouncerInteractor
import com.android.systemui.dagger.SysUISingleton
@@ -33,7 +34,6 @@
import com.android.systemui.flags.Flags
import com.android.systemui.keyguard.data.repository.DeviceEntryFaceAuthRepository
import com.android.systemui.keyguard.data.repository.DeviceEntryFingerprintAuthRepository
-import com.android.systemui.keyguard.data.repository.KeyguardRepository
import com.android.systemui.keyguard.shared.model.ErrorFaceAuthenticationStatus
import com.android.systemui.keyguard.shared.model.FaceAuthenticationStatus
import com.android.systemui.keyguard.shared.model.TransitionState
@@ -44,6 +44,7 @@
import com.android.systemui.user.data.repository.UserRepository
import com.android.systemui.util.kotlin.pairwise
import com.android.systemui.util.kotlin.sample
+import javax.inject.Inject
import kotlinx.coroutines.CoroutineDispatcher
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.flow.Flow
@@ -56,7 +57,6 @@
import kotlinx.coroutines.flow.merge
import kotlinx.coroutines.flow.onEach
import kotlinx.coroutines.yield
-import javax.inject.Inject
/**
* Encapsulates business logic related face authentication being triggered for device entry from
@@ -79,7 +79,6 @@
private val deviceEntryFingerprintAuthRepository: DeviceEntryFingerprintAuthRepository,
private val userRepository: UserRepository,
private val facePropertyRepository: FacePropertyRepository,
- private val keyguardRepository: KeyguardRepository,
private val faceWakeUpTriggersConfig: FaceWakeUpTriggersConfig,
private val powerInteractor: PowerInteractor,
) : CoreStartable, KeyguardFaceAuthInteractor {
@@ -207,6 +206,12 @@
runFaceAuth(FaceAuthUiEvent.FACE_AUTH_ACCESSIBILITY_ACTION, false)
}
+ override fun onWalletLaunched() {
+ if (facePropertyRepository.sensorInfo.value?.strength == SensorStrength.STRONG) {
+ runFaceAuth(FaceAuthUiEvent.FACE_AUTH_TRIGGERED_OCCLUDING_APP_REQUESTED, true)
+ }
+ }
+
override fun registerListener(listener: FaceAuthenticationListener) {
listeners.add(listener)
}
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/AlternateBouncerViewBinder.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/AlternateBouncerViewBinder.kt
new file mode 100644
index 0000000..41af9e8
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/AlternateBouncerViewBinder.kt
@@ -0,0 +1,115 @@
+/*
+ * Copyright (C) 2023 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.keyguard.ui.binder
+
+import android.view.View
+import android.view.ViewGroup
+import androidx.lifecycle.Lifecycle
+import androidx.lifecycle.repeatOnLifecycle
+import com.android.systemui.CoreStartable
+import com.android.systemui.dagger.SysUISingleton
+import com.android.systemui.dagger.qualifiers.Application
+import com.android.systemui.flags.FeatureFlagsClassic
+import com.android.systemui.flags.Flags
+import com.android.systemui.keyguard.ui.viewmodel.AlternateBouncerViewModel
+import com.android.systemui.lifecycle.repeatWhenAttached
+import com.android.systemui.res.R
+import com.android.systemui.scrim.ScrimView
+import com.android.systemui.shade.NotificationShadeWindowView
+import com.android.systemui.statusbar.NotificationShadeWindowController
+import kotlinx.coroutines.CoroutineScope
+import kotlinx.coroutines.ExperimentalCoroutinesApi
+import kotlinx.coroutines.launch
+import javax.inject.Inject
+
+@ExperimentalCoroutinesApi
+@SysUISingleton
+class AlternateBouncerBinder
+@Inject
+constructor(
+ private val notificationShadeWindowView: NotificationShadeWindowView,
+ private val featureFlags: FeatureFlagsClassic,
+ private val alternateBouncerViewModel: AlternateBouncerViewModel,
+ @Application private val scope: CoroutineScope,
+ private val notificationShadeWindowController: NotificationShadeWindowController,
+) : CoreStartable {
+ override fun start() {
+ if (!featureFlags.isEnabled(Flags.ALTERNATE_BOUNCER_VIEW)) {
+ return
+ }
+
+ AlternateBouncerViewBinder.bind(
+ notificationShadeWindowView.requireViewById(R.id.alternate_bouncer),
+ alternateBouncerViewModel,
+ scope,
+ notificationShadeWindowController,
+ )
+ }
+}
+
+/**
+ * Binds the alternate bouncer view to its view-model.
+ *
+ * To use this properly, users should maintain a one-to-one relationship between the [View] and the
+ * view-binding, binding each view only once. It is okay and expected for the same instance of the
+ * view-model to be reused for multiple view/view-binder bindings.
+ */
+@ExperimentalCoroutinesApi
+object AlternateBouncerViewBinder {
+
+ /** Binds the view to the view-model, continuing to update the former based on the latter. */
+ @JvmStatic
+ fun bind(
+ view: ViewGroup,
+ viewModel: AlternateBouncerViewModel,
+ scope: CoroutineScope,
+ notificationShadeWindowController: NotificationShadeWindowController,
+ ) {
+ scope.launch {
+ // forcePluginOpen is necessary to show over occluded apps.
+ // This cannot be tied to the view's lifecycle because setting this allows the view
+ // to be started in the first place.
+ viewModel.forcePluginOpen.collect {
+ notificationShadeWindowController.setForcePluginOpen(it, this)
+ }
+ }
+
+ val scrim = view.requireViewById(R.id.alternate_bouncer_scrim) as ScrimView
+ view.repeatWhenAttached { alternateBouncerViewContainer ->
+ repeatOnLifecycle(Lifecycle.State.STARTED) {
+ scrim.viewAlpha = 0f
+
+ launch {
+ viewModel.onClickListener.collect {
+ // TODO (b/287599719): Support swiping to dismiss altBouncer
+ alternateBouncerViewContainer.setOnClickListener(it)
+ }
+ }
+
+ launch {
+ viewModel.scrimAlpha.collect {
+ alternateBouncerViewContainer.visibility =
+ if (it < .1f) View.INVISIBLE else View.VISIBLE
+ scrim.viewAlpha = it
+ }
+ }
+
+ launch { viewModel.scrimColor.collect { scrim.tint = it } }
+ }
+ }
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/preview/KeyguardPreviewRenderer.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/preview/KeyguardPreviewRenderer.kt
index 5ae2aba..c6d8ec7 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/preview/KeyguardPreviewRenderer.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/preview/KeyguardPreviewRenderer.kt
@@ -27,11 +27,14 @@
import android.os.Bundle
import android.os.Handler
import android.os.IBinder
+import android.view.Display
+import android.view.Display.DEFAULT_DISPLAY
import android.view.LayoutInflater
import android.view.SurfaceControlViewHost
import android.view.View
import android.view.ViewGroup
import android.view.WindowManager
+import android.view.WindowManager.LayoutParams.TYPE_KEYGUARD
import android.widget.FrameLayout
import androidx.constraintlayout.widget.ConstraintLayout
import androidx.core.view.isInvisible
@@ -125,6 +128,8 @@
private val shouldHideClock: Boolean =
bundle.getBoolean(ClockPreviewConstants.KEY_HIDE_CLOCK, false)
private val wallpaperColors: WallpaperColors? = bundle.getParcelable(KEY_COLORS)
+ private val displayId = bundle.getInt(KEY_DISPLAY_ID, DEFAULT_DISPLAY)
+ private val display: Display = displayManager.getDisplay(displayId)
private var host: SurfaceControlViewHost
@@ -164,7 +169,7 @@
host =
SurfaceControlViewHost(
context,
- displayManager.getDisplay(bundle.getInt(KEY_DISPLAY_ID)),
+ displayManager.getDisplay(DEFAULT_DISPLAY),
hostToken,
"KeyguardPreviewRenderer"
)
@@ -174,21 +179,27 @@
fun render() {
mainHandler.post {
- val rootView = FrameLayout(context)
+ val previewContext = context.createDisplayContext(display)
- setupKeyguardRootView(rootView)
+ val rootView = FrameLayout(previewContext)
+
+ setupKeyguardRootView(previewContext, rootView)
if (!featureFlags.isEnabled(Flags.MIGRATE_SPLIT_KEYGUARD_BOTTOM_AREA)) {
setUpBottomArea(rootView)
}
+ val windowContext = context.createWindowContext(display, TYPE_KEYGUARD, null)
+ val windowManagerOfDisplay = windowContext.getSystemService(WindowManager::class.java)
rootView.measure(
View.MeasureSpec.makeMeasureSpec(
- windowManager.currentWindowMetrics.bounds.width(),
+ windowManagerOfDisplay?.currentWindowMetrics?.bounds?.width()
+ ?: windowManager.currentWindowMetrics.bounds.width(),
View.MeasureSpec.EXACTLY
),
View.MeasureSpec.makeMeasureSpec(
- windowManager.currentWindowMetrics.bounds.height(),
+ windowManagerOfDisplay?.currentWindowMetrics?.bounds?.height()
+ ?: windowManager.currentWindowMetrics.bounds.height(),
View.MeasureSpec.EXACTLY
),
)
@@ -251,7 +262,7 @@
*
* The end padding is as follows: Below clock padding end
*/
- private fun setUpSmartspace(parentView: ViewGroup) {
+ private fun setUpSmartspace(previewContext: Context, parentView: ViewGroup) {
if (
!lockscreenSmartspaceController.isEnabled() ||
!lockscreenSmartspaceController.isDateWeatherDecoupled()
@@ -263,12 +274,12 @@
val topPadding: Int =
KeyguardPreviewSmartspaceViewModel.getLargeClockSmartspaceTopPadding(
- context.resources,
+ previewContext.resources,
)
val startPadding: Int =
- context.resources.getDimensionPixelSize(R.dimen.below_clock_padding_start)
+ previewContext.resources.getDimensionPixelSize(R.dimen.below_clock_padding_start)
val endPadding: Int =
- context.resources.getDimensionPixelSize(R.dimen.below_clock_padding_end)
+ previewContext.resources.getDimensionPixelSize(R.dimen.below_clock_padding_end)
smartSpaceView?.let {
it.setPaddingRelative(startPadding, topPadding, endPadding, 0)
@@ -308,8 +319,8 @@
}
@OptIn(ExperimentalCoroutinesApi::class)
- private fun setupKeyguardRootView(rootView: FrameLayout) {
- val keyguardRootView = KeyguardRootView(context, null).apply { removeAllViews() }
+ private fun setupKeyguardRootView(previewContext: Context, rootView: FrameLayout) {
+ val keyguardRootView = KeyguardRootView(previewContext, null).apply { removeAllViews() }
disposables.add(
KeyguardRootViewBinder.bind(
keyguardRootView,
@@ -333,10 +344,10 @@
if (featureFlags.isEnabled(Flags.MIGRATE_SPLIT_KEYGUARD_BOTTOM_AREA)) {
setupShortcuts(keyguardRootView)
}
- setUpUdfps(rootView)
+ setUpUdfps(previewContext, rootView)
if (!shouldHideClock) {
- setUpClock(rootView)
+ setUpClock(previewContext, rootView)
KeyguardPreviewClockViewBinder.bind(
largeClockHostView,
smallClockHostView,
@@ -344,7 +355,7 @@
)
}
- setUpSmartspace(rootView)
+ setUpSmartspace(previewContext, rootView)
smartSpaceView?.let {
KeyguardPreviewSmartspaceViewBinder.bind(it, smartspaceViewModel)
}
@@ -381,7 +392,7 @@
}
}
- private fun setUpUdfps(parentView: ViewGroup) {
+ private fun setUpUdfps(previewContext: Context, parentView: ViewGroup) {
val sensorBounds = udfpsOverlayInteractor.udfpsOverlayParams.value.sensorBounds
// If sensorBounds are default rect, then there is no UDFPS
@@ -399,7 +410,7 @@
sensorBounds.bottom
)
val finger =
- LayoutInflater.from(context)
+ LayoutInflater.from(previewContext)
.inflate(
R.layout.udfps_keyguard_preview,
parentView,
@@ -408,12 +419,12 @@
parentView.addView(finger, fingerprintLayoutParams)
}
- private fun setUpClock(parentView: ViewGroup) {
+ private fun setUpClock(previewContext: Context, parentView: ViewGroup) {
largeClockHostView =
if (featureFlags.isEnabled(Flags.MIGRATE_KEYGUARD_STATUS_VIEW)) {
parentView.requireViewById<FrameLayout>(R.id.lockscreen_clock_view_large)
} else {
- val hostView = FrameLayout(context)
+ val hostView = FrameLayout(previewContext)
hostView.layoutParams =
FrameLayout.LayoutParams(
FrameLayout.LayoutParams.MATCH_PARENT,
@@ -429,7 +440,7 @@
parentView.requireViewById<FrameLayout>(R.id.lockscreen_clock_view)
} else {
val resources = parentView.resources
- val hostView = FrameLayout(context)
+ val hostView = FrameLayout(previewContext)
val layoutParams =
FrameLayout.LayoutParams(
FrameLayout.LayoutParams.WRAP_CONTENT,
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/sections/DefaultStatusViewSection.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/sections/DefaultStatusViewSection.kt
index 1a9f021..0b0f21d 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/sections/DefaultStatusViewSection.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/sections/DefaultStatusViewSection.kt
@@ -31,12 +31,12 @@
import androidx.constraintlayout.widget.ConstraintSet.TOP
import com.android.keyguard.KeyguardStatusView
import com.android.keyguard.dagger.KeyguardStatusViewComponent
-import com.android.systemui.res.R
import com.android.systemui.flags.FeatureFlags
import com.android.systemui.flags.Flags
import com.android.systemui.keyguard.KeyguardViewConfigurator
import com.android.systemui.keyguard.shared.model.KeyguardSection
import com.android.systemui.media.controls.ui.KeyguardMediaController
+import com.android.systemui.res.R
import com.android.systemui.shade.NotificationPanelView
import com.android.systemui.shade.NotificationPanelViewController
import com.android.systemui.statusbar.policy.SplitShadeStateController
@@ -84,7 +84,8 @@
override fun bindData(constraintLayout: ConstraintLayout) {
if (featureFlags.isEnabled(Flags.MIGRATE_KEYGUARD_STATUS_VIEW)) {
constraintLayout.findViewById<KeyguardStatusView?>(R.id.keyguard_status_view)?.let {
- val statusViewComponent = keyguardStatusViewComponentFactory.build(it)
+ val statusViewComponent =
+ keyguardStatusViewComponentFactory.build(it, context.display)
val controller = statusViewComponent.keyguardStatusViewController
controller.init()
keyguardMediaController.attachSplitShadeContainer(
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/AlternateBouncerViewModel.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/AlternateBouncerViewModel.kt
new file mode 100644
index 0000000..235a28d
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/AlternateBouncerViewModel.kt
@@ -0,0 +1,103 @@
+/*
+ * Copyright (C) 2023 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.keyguard.ui.viewmodel
+
+import android.graphics.Color
+import android.view.View
+import com.android.systemui.keyguard.domain.interactor.FromAlternateBouncerTransitionInteractor.Companion.TRANSITION_DURATION_MS
+import com.android.systemui.keyguard.domain.interactor.KeyguardTransitionInteractor
+import com.android.systemui.keyguard.shared.model.KeyguardState.ALTERNATE_BOUNCER
+import com.android.systemui.keyguard.ui.KeyguardTransitionAnimationFlow
+import com.android.systemui.plugins.FalsingManager
+import com.android.systemui.statusbar.phone.StatusBarKeyguardViewManager
+import com.android.wm.shell.animation.Interpolators
+import javax.inject.Inject
+import kotlinx.coroutines.ExperimentalCoroutinesApi
+import kotlinx.coroutines.flow.Flow
+import kotlinx.coroutines.flow.distinctUntilChanged
+import kotlinx.coroutines.flow.flowOf
+import kotlinx.coroutines.flow.map
+import kotlinx.coroutines.flow.merge
+
+@ExperimentalCoroutinesApi
+class AlternateBouncerViewModel
+@Inject
+constructor(
+ statusBarKeyguardViewManager: StatusBarKeyguardViewManager,
+ transitionInteractor: KeyguardTransitionInteractor,
+ falsingManager: FalsingManager,
+) {
+ // When we're fully transitioned to the AlternateBouncer, the alpha of the scrim should be:
+ private val alternateBouncerScrimAlpha = .66f
+ private val toAlternateBouncerTransition =
+ KeyguardTransitionAnimationFlow(
+ transitionDuration = TRANSITION_DURATION_MS,
+ transitionFlow = transitionInteractor.anyStateToAlternateBouncerTransition,
+ )
+ .createFlow(
+ duration = TRANSITION_DURATION_MS,
+ onStep = { it },
+ onFinish = { 1f },
+ // Reset on cancel
+ onCancel = { 0f },
+ interpolator = Interpolators.FAST_OUT_SLOW_IN,
+ )
+ private val fromAlternateBouncerTransition =
+ KeyguardTransitionAnimationFlow(
+ transitionDuration = TRANSITION_DURATION_MS,
+ transitionFlow = transitionInteractor.transitionStepsFromState(ALTERNATE_BOUNCER),
+ )
+ .createFlow(
+ duration = TRANSITION_DURATION_MS,
+ onStep = { 1f - it },
+ // Reset on cancel
+ onCancel = { 0f },
+ interpolator = Interpolators.FAST_OUT_SLOW_IN,
+ )
+
+ /** Progress to a fully transitioned alternate bouncer. 1f represents fully transitioned. */
+ private val transitionToAlternateBouncerProgress =
+ merge(fromAlternateBouncerTransition, toAlternateBouncerTransition)
+
+ val forcePluginOpen: Flow<Boolean> =
+ transitionToAlternateBouncerProgress.map { it > 0f }.distinctUntilChanged()
+
+ /** An observable for the scrim alpha. */
+ val scrimAlpha = transitionToAlternateBouncerProgress.map { it * alternateBouncerScrimAlpha }
+
+ /** An observable for the scrim color. Change color for easier debugging. */
+ val scrimColor: Flow<Int> = flowOf(Color.BLACK)
+
+ private val clickListener =
+ View.OnClickListener {
+ if (!falsingManager.isFalseTap(FalsingManager.LOW_PENALTY)) {
+ statusBarKeyguardViewManager.showPrimaryBouncer(/* scrimmed */ true)
+ }
+ }
+
+ val onClickListener: Flow<View.OnClickListener?> =
+ transitionToAlternateBouncerProgress
+ .map {
+ if (it == 1f) {
+ clickListener
+ } else {
+ null
+ }
+ }
+ .distinctUntilChanged()
+}
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/UdfpsLockscreenViewModel.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/UdfpsLockscreenViewModel.kt
index 54abc5b..0b1079f 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/UdfpsLockscreenViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/UdfpsLockscreenViewModel.kt
@@ -19,13 +19,13 @@
import android.content.Context
import androidx.annotation.ColorInt
import com.android.settingslib.Utils.getColorAttrDefaultColor
-import com.android.systemui.res.R
import com.android.systemui.keyguard.domain.interactor.BurnInOffsets
import com.android.systemui.keyguard.domain.interactor.KeyguardInteractor
import com.android.systemui.keyguard.domain.interactor.KeyguardTransitionInteractor
import com.android.systemui.keyguard.domain.interactor.UdfpsKeyguardInteractor
import com.android.systemui.keyguard.shared.model.KeyguardState
import com.android.systemui.keyguard.shared.model.StatusBarState
+import com.android.systemui.res.R
import com.android.wm.shell.animation.Interpolators
import javax.inject.Inject
import kotlin.math.roundToInt
@@ -62,7 +62,7 @@
private val toAlternateBouncer: Flow<TransitionViewModel> =
keyguardInteractor.statusBarState.flatMapLatest { statusBarState ->
- transitionInteractor.anyStateToAlternateBouncerTransition.map {
+ transitionInteractor.transitionStepsToState(KeyguardState.ALTERNATE_BOUNCER).map {
TransitionViewModel(
alpha = 1f,
scale =
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSFragmentLegacy.java b/packages/SystemUI/src/com/android/systemui/qs/QSFragmentLegacy.java
index 8589ae9..68bf88b 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSFragmentLegacy.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSFragmentLegacy.java
@@ -72,7 +72,7 @@
@Override
public void onViewCreated(View view, @Nullable Bundle savedInstanceState) {
- QSFragmentComponent qsFragmentComponent = mQsComponentFactory.create(this);
+ QSFragmentComponent qsFragmentComponent = mQsComponentFactory.create(getView());
mQsImpl = mQsImplProvider.get();
mQsImpl.onComponentCreated(qsFragmentComponent, savedInstanceState);
}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSHostAdapter.kt b/packages/SystemUI/src/com/android/systemui/qs/QSHostAdapter.kt
index 2a36fdb..65a2c8c 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSHostAdapter.kt
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSHostAdapter.kt
@@ -105,7 +105,7 @@
override fun removeCallback(callback: QSHost.Callback) {
if (useNewHost) {
- synchronized(callbacksMap) { callbacksMap.get(callback)?.cancel() }
+ synchronized(callbacksMap) { callbacksMap.remove(callback)?.cancel() }
} else {
qsTileHost.removeCallback(callback)
}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSImpl.java b/packages/SystemUI/src/com/android/systemui/qs/QSImpl.java
index a32a024..202254b 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSImpl.java
@@ -199,11 +199,13 @@
mListeningAndVisibilityLifecycleOwner = new ListeningAndVisibilityLifecycleOwner();
}
+ /**
+ * This method will set up all the necessary fields. Methods from the implemented interfaces
+ * should not be called before this method returns.
+ */
public void onComponentCreated(QSComponent qsComponent, @Nullable Bundle savedInstanceState) {
mRootView = qsComponent.getRootView();
- mCommandQueue.addCallback(this);
-
mQSPanelController = qsComponent.getQSPanelController();
mQuickQSPanelController = qsComponent.getQuickQSPanelController();
@@ -270,6 +272,9 @@
mQSPanelController.getMediaHost().getHostView().setAlpha(1.0f);
mQSAnimator.requestAnimatorUpdate();
});
+
+ // This will immediately call disable, so it needs to be added after setting up the fields.
+ mCommandQueue.addCallback(this);
}
private void bindFooterActionsView(View root) {
@@ -323,6 +328,8 @@
public void onDestroy() {
mCommandQueue.removeCallback(this);
mStatusBarStateController.removeCallback(this);
+ mQSPanelController.destroy();
+ mQuickQSPanelController.destroy();
if (mListening) {
setListening(false);
}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSPanelControllerBase.java b/packages/SystemUI/src/com/android/systemui/qs/QSPanelControllerBase.java
index 60c92c0..fc2f5f9 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSPanelControllerBase.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSPanelControllerBase.java
@@ -158,6 +158,7 @@
protected void onInit() {
mView.initialize(mQSLogger);
mQSLogger.logAllTilesChangeListening(mView.isListening(), mView.getDumpableTag(), "");
+ mHost.addCallback(mQSHostCallback);
}
/**
@@ -172,6 +173,18 @@
}
@Override
+ public void destroy() {
+ super.destroy();
+ mHost.removeCallback(mQSHostCallback);
+
+ for (TileRecord record : mRecords) {
+ record.tile.removeCallback(record.callback);
+ mView.removeTile(record);
+ }
+ mRecords.clear();
+ }
+
+ @Override
protected void onViewAttached() {
mQsTileRevealController = createTileRevealController();
if (mQsTileRevealController != null) {
@@ -180,7 +193,6 @@
mMediaHost.addVisibilityChangeListener(mMediaHostVisibilityListener);
mView.addOnConfigurationChangedListener(mOnConfigurationChangedListener);
- mHost.addCallback(mQSHostCallback);
setTiles();
mLastOrientation = getResources().getConfiguration().orientation;
mQSLogger.logOnViewAttached(mLastOrientation, mView.getDumpableTag());
@@ -193,16 +205,11 @@
protected void onViewDetached() {
mQSLogger.logOnViewDetached(mLastOrientation, mView.getDumpableTag());
mView.removeOnConfigurationChangedListener(mOnConfigurationChangedListener);
- mHost.removeCallback(mQSHostCallback);
mView.getTileLayout().setListening(false, mUiEventLogger);
mMediaHost.removeVisibilityChangeListener(mMediaHostVisibilityListener);
- for (TileRecord record : mRecords) {
- record.tile.removeCallback(record.callback);
- }
- mRecords.clear();
mDumpManager.unregisterDumpable(mView.getDumpableTag());
}
@@ -222,15 +229,30 @@
if (!collapsedView && mQsTileRevealController != null) {
mQsTileRevealController.updateRevealedTiles(tiles);
}
-
- for (QSPanelControllerBase.TileRecord record : mRecords) {
- mView.removeTile(record);
- record.tile.removeCallback(record.callback);
+ boolean shouldChange = false;
+ if (tiles.size() == mRecords.size()) {
+ int i = 0;
+ for (QSTile tile : tiles) {
+ if (tile != mRecords.get(i).tile) {
+ shouldChange = true;
+ break;
+ }
+ i++;
+ }
+ } else {
+ shouldChange = true;
}
- mRecords.clear();
- mCachedSpecs = "";
- for (QSTile tile : tiles) {
- addTile(tile, collapsedView);
+
+ if (shouldChange) {
+ for (QSPanelControllerBase.TileRecord record : mRecords) {
+ mView.removeTile(record);
+ record.tile.removeCallback(record.callback);
+ }
+ mRecords.clear();
+ mCachedSpecs = "";
+ for (QSTile tile : tiles) {
+ addTile(tile, collapsedView);
+ }
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/dagger/QSFragmentComponent.java b/packages/SystemUI/src/com/android/systemui/qs/dagger/QSFragmentComponent.java
index 327e858..ce8db7898 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/dagger/QSFragmentComponent.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/dagger/QSFragmentComponent.java
@@ -16,6 +16,9 @@
package com.android.systemui.qs.dagger;
+import android.view.View;
+
+import com.android.systemui.dagger.qualifiers.RootView;
import com.android.systemui.qs.QSFragmentLegacy;
import dagger.BindsInstance;
@@ -31,6 +34,7 @@
/** Factory for building a {@link QSFragmentComponent}. */
@Subcomponent.Factory
interface Factory {
- QSFragmentComponent create(@BindsInstance QSFragmentLegacy qsFragment);
+ /** */
+ QSFragmentComponent create(@BindsInstance @RootView View view);
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/dagger/QSFragmentModule.java b/packages/SystemUI/src/com/android/systemui/qs/dagger/QSFragmentModule.java
index 0c9c24d..0e75b21 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/dagger/QSFragmentModule.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/dagger/QSFragmentModule.java
@@ -20,34 +20,17 @@
import static com.android.systemui.util.Utils.useQsMediaPlayer;
import android.content.Context;
-import android.view.View;
-import com.android.systemui.dagger.qualifiers.RootView;
-import com.android.systemui.plugins.qs.QS;
-import com.android.systemui.qs.QSFragmentLegacy;
-
-import javax.inject.Named;
-
-import dagger.Binds;
import dagger.Module;
import dagger.Provides;
+import javax.inject.Named;
+
/**
* Dagger Module for {@link QSFragmentComponent}.
*/
@Module(includes = {QSScopeModule.class})
public interface QSFragmentModule {
-
- @Provides
- @RootView
- static View provideRootView(QSFragmentLegacy qsFragment) {
- return qsFragment.getView();
- }
-
- /** */
- @Binds
- QS bindQS(QSFragmentLegacy qsFragment);
-
/** */
@Provides
@Named(QSScopeModule.QS_USING_MEDIA_PLAYER)
diff --git a/packages/SystemUI/src/com/android/systemui/qs/pipeline/domain/interactor/CurrentTilesInteractor.kt b/packages/SystemUI/src/com/android/systemui/qs/pipeline/domain/interactor/CurrentTilesInteractor.kt
index c5512c1..4bb8c6e 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/pipeline/domain/interactor/CurrentTilesInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/qs/pipeline/domain/interactor/CurrentTilesInteractor.kt
@@ -272,7 +272,6 @@
// repository
launch { tileSpecRepository.setTiles(currentUser.value, resolvedSpecs) }
}
- Log.d("Fabian", "Finished resolving tiles")
}
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/scene/shared/model/ObservableTransitionState.kt b/packages/SystemUI/src/com/android/systemui/scene/shared/model/ObservableTransitionState.kt
index 3927873..f704894 100644
--- a/packages/SystemUI/src/com/android/systemui/scene/shared/model/ObservableTransitionState.kt
+++ b/packages/SystemUI/src/com/android/systemui/scene/shared/model/ObservableTransitionState.kt
@@ -42,6 +42,13 @@
* scene, this value will remain true after the pointer is no longer touching the screen and
* will be true in any transition created to animate back to the original position.
*/
- val isUserInputDriven: Boolean,
+ val isInitiatedByUserInput: Boolean,
+
+ /**
+ * Whether user input is currently driving the transition. For example, if a user is
+ * dragging a pointer, this emits true. Once they lift their finger, this emits false while
+ * the transition completes/settles.
+ */
+ val isUserInputOngoing: Flow<Boolean>,
) : ObservableTransitionState()
}
diff --git a/packages/SystemUI/src/com/android/systemui/settings/UserTrackerImpl.kt b/packages/SystemUI/src/com/android/systemui/settings/UserTrackerImpl.kt
index 2f87301..393a698 100644
--- a/packages/SystemUI/src/com/android/systemui/settings/UserTrackerImpl.kt
+++ b/packages/SystemUI/src/com/android/systemui/settings/UserTrackerImpl.kt
@@ -132,6 +132,7 @@
setUserIdInternal(startingUser)
val filter = IntentFilter().apply {
+ addAction(Intent.ACTION_LOCALE_CHANGED)
addAction(Intent.ACTION_USER_INFO_CHANGED)
// These get called when a managed profile goes in or out of quiet mode.
addAction(Intent.ACTION_MANAGED_PROFILE_AVAILABLE)
@@ -149,6 +150,7 @@
override fun onReceive(context: Context, intent: Intent) {
when (intent.action) {
+ Intent.ACTION_LOCALE_CHANGED,
Intent.ACTION_USER_INFO_CHANGED,
Intent.ACTION_MANAGED_PROFILE_AVAILABLE,
Intent.ACTION_MANAGED_PROFILE_UNAVAILABLE,
diff --git a/packages/SystemUI/src/com/android/systemui/shade/DebugDrawable.java b/packages/SystemUI/src/com/android/systemui/shade/DebugDrawable.java
index 9235fcc..c42fdf8 100644
--- a/packages/SystemUI/src/com/android/systemui/shade/DebugDrawable.java
+++ b/packages/SystemUI/src/com/android/systemui/shade/DebugDrawable.java
@@ -67,8 +67,6 @@
mDebugPaint.setStrokeWidth(2);
mDebugPaint.setStyle(Paint.Style.STROKE);
mDebugPaint.setTextSize(24);
- String headerDebugInfo = mNotificationPanelViewController.getHeaderDebugInfo();
- if (headerDebugInfo != null) canvas.drawText(headerDebugInfo, 50, 100, mDebugPaint);
drawDebugInfo(canvas, mNotificationPanelViewController.getMaxPanelHeight(),
Color.RED, "getMaxPanelHeight()");
diff --git a/packages/SystemUI/src/com/android/systemui/shade/NotificationPanelViewController.java b/packages/SystemUI/src/com/android/systemui/shade/NotificationPanelViewController.java
index d3d38e5c..2ef83dd 100644
--- a/packages/SystemUI/src/com/android/systemui/shade/NotificationPanelViewController.java
+++ b/packages/SystemUI/src/com/android/systemui/shade/NotificationPanelViewController.java
@@ -138,7 +138,6 @@
import com.android.systemui.keyguard.domain.interactor.KeyguardTransitionInteractor;
import com.android.systemui.keyguard.shared.model.TransitionState;
import com.android.systemui.keyguard.shared.model.TransitionStep;
-import com.android.systemui.power.shared.model.WakefulnessModel;
import com.android.systemui.keyguard.ui.binder.KeyguardLongPressViewBinder;
import com.android.systemui.keyguard.ui.viewmodel.DreamingToLockscreenTransitionViewModel;
import com.android.systemui.keyguard.ui.viewmodel.GoneToDreamingLockscreenHostedTransitionViewModel;
@@ -162,9 +161,10 @@
import com.android.systemui.plugins.qs.QS;
import com.android.systemui.plugins.statusbar.StatusBarStateController;
import com.android.systemui.plugins.statusbar.StatusBarStateController.StateListener;
+import com.android.systemui.power.domain.interactor.PowerInteractor;
+import com.android.systemui.power.shared.model.WakefulnessModel;
import com.android.systemui.res.R;
import com.android.systemui.shade.data.repository.ShadeRepository;
-import com.android.systemui.power.domain.interactor.PowerInteractor;
import com.android.systemui.shade.transition.ShadeTransitionController;
import com.android.systemui.shared.system.QuickStepContract;
import com.android.systemui.statusbar.CommandQueue;
@@ -200,7 +200,6 @@
import com.android.systemui.statusbar.phone.CentralSurfaces;
import com.android.systemui.statusbar.phone.DozeParameters;
import com.android.systemui.statusbar.phone.HeadsUpAppearanceController;
-import com.android.systemui.statusbar.phone.HeadsUpManagerPhone;
import com.android.systemui.statusbar.phone.HeadsUpTouchHelper;
import com.android.systemui.statusbar.phone.KeyguardBottomAreaView;
import com.android.systemui.statusbar.phone.KeyguardBottomAreaViewController;
@@ -217,6 +216,7 @@
import com.android.systemui.statusbar.phone.UnlockedScreenOffAnimationController;
import com.android.systemui.statusbar.phone.fragment.CollapsedStatusBarFragment;
import com.android.systemui.statusbar.policy.ConfigurationController;
+import com.android.systemui.statusbar.policy.HeadsUpManager;
import com.android.systemui.statusbar.policy.KeyguardQsUserSwitchController;
import com.android.systemui.statusbar.policy.KeyguardStateController;
import com.android.systemui.statusbar.policy.KeyguardUserSwitcherController;
@@ -362,7 +362,7 @@
private boolean mIsLaunchAnimationRunning;
private float mOverExpansion;
private CentralSurfaces mCentralSurfaces;
- private HeadsUpManagerPhone mHeadsUpManager;
+ private HeadsUpManager mHeadsUpManager;
private float mExpandedHeight = 0;
/** The current squish amount for the predictive back animation */
private float mCurrentBackProgress = 0.0f;
@@ -1275,7 +1275,8 @@
KeyguardStatusView keyguardStatusView = mView.getRootView().findViewById(
R.id.keyguard_status_view);
KeyguardStatusViewComponent statusViewComponent =
- mKeyguardStatusViewComponentFactory.build(keyguardStatusView);
+ mKeyguardStatusViewComponentFactory.build(keyguardStatusView,
+ mView.getContext().getDisplay());
mKeyguardStatusViewController = statusViewComponent.getKeyguardStatusViewController();
mKeyguardStatusViewController.init();
}
@@ -3025,7 +3026,7 @@
return headsUpVisible || isExpanded() || mBouncerShowing;
}
- private void setHeadsUpManager(HeadsUpManagerPhone headsUpManager) {
+ private void setHeadsUpManager(HeadsUpManager headsUpManager) {
mHeadsUpManager = headsUpManager;
mHeadsUpManager.addListener(mOnHeadsUpChangedListener);
mHeadsUpTouchHelper = new HeadsUpTouchHelper(
@@ -3507,7 +3508,7 @@
GestureRecorder recorder,
Runnable hideExpandedRunnable,
NotificationShelfController notificationShelfController,
- HeadsUpManagerPhone headsUpManager) {
+ HeadsUpManager headsUpManager) {
setHeadsUpManager(headsUpManager);
// TODO(b/254859580): this can be injected.
mCentralSurfaces = centralSurfaces;
@@ -3556,10 +3557,6 @@
mView.getViewTreeObserver().removeOnGlobalLayoutListener(listener);
}
- String getHeaderDebugInfo() {
- return "USER " + mHeadsUpManager.getUser();
- }
-
@Override
public void onThemeChanged() {
mConfigurationListener.onThemeChanged();
diff --git a/packages/SystemUI/src/com/android/systemui/shade/NotificationShadeWindowViewController.java b/packages/SystemUI/src/com/android/systemui/shade/NotificationShadeWindowViewController.java
index 6cf4ff5..5414b3f 100644
--- a/packages/SystemUI/src/com/android/systemui/shade/NotificationShadeWindowViewController.java
+++ b/packages/SystemUI/src/com/android/systemui/shade/NotificationShadeWindowViewController.java
@@ -21,7 +21,6 @@
import static com.android.systemui.util.kotlin.JavaAdapterKt.collectFlow;
import android.app.StatusBarManager;
-import android.os.PowerManager;
import android.util.Log;
import android.view.GestureDetector;
import android.view.InputDevice;
@@ -36,10 +35,11 @@
import com.android.keyguard.LockIconViewController;
import com.android.keyguard.dagger.KeyguardBouncerComponent;
import com.android.systemui.Dumpable;
-import com.android.systemui.res.R;
import com.android.systemui.animation.ActivityLaunchAnimator;
import com.android.systemui.back.domain.interactor.BackActionInteractor;
+import com.android.systemui.bouncer.domain.interactor.AlternateBouncerInteractor;
import com.android.systemui.bouncer.domain.interactor.BouncerMessageInteractor;
+import com.android.systemui.bouncer.domain.interactor.PrimaryBouncerInteractor;
import com.android.systemui.bouncer.ui.binder.KeyguardBouncerViewBinder;
import com.android.systemui.bouncer.ui.viewmodel.KeyguardBouncerViewModel;
import com.android.systemui.classifier.FalsingCollector;
@@ -56,6 +56,7 @@
import com.android.systemui.keyguard.ui.viewmodel.PrimaryBouncerToGoneTransitionViewModel;
import com.android.systemui.log.BouncerLogger;
import com.android.systemui.power.domain.interactor.PowerInteractor;
+import com.android.systemui.res.R;
import com.android.systemui.shared.animation.DisableSubpixelTextTransitionListener;
import com.android.systemui.statusbar.DragDownHelper;
import com.android.systemui.statusbar.LockscreenShadeTransitionController;
@@ -106,6 +107,8 @@
private final boolean mIsTrackpadCommonEnabled;
private final FeatureFlags mFeatureFlags;
private final KeyEventInteractor mKeyEventInteractor;
+ private final PrimaryBouncerInteractor mPrimaryBouncerInteractor;
+ private final AlternateBouncerInteractor mAlternateBouncerInteractor;
private GestureDetector mPulsingWakeupGestureHandler;
private GestureDetector mDreamingWakeupGestureHandler;
private View mBrightnessMirror;
@@ -182,7 +185,9 @@
SystemClock clock,
BouncerMessageInteractor bouncerMessageInteractor,
BouncerLogger bouncerLogger,
- KeyEventInteractor keyEventInteractor) {
+ KeyEventInteractor keyEventInteractor,
+ PrimaryBouncerInteractor primaryBouncerInteractor,
+ AlternateBouncerInteractor alternateBouncerInteractor) {
mLockscreenShadeTransitionController = transitionController;
mFalsingCollector = falsingCollector;
mStatusBarStateController = statusBarStateController;
@@ -210,6 +215,8 @@
mIsTrackpadCommonEnabled = featureFlags.isEnabled(TRACKPAD_GESTURE_COMMON);
mFeatureFlags = featureFlags;
mKeyEventInteractor = keyEventInteractor;
+ mPrimaryBouncerInteractor = primaryBouncerInteractor;
+ mAlternateBouncerInteractor = alternateBouncerInteractor;
// This view is not part of the newly inflated expanded status bar.
mBrightnessMirror = mView.findViewById(R.id.brightness_mirror_container);
@@ -351,16 +358,6 @@
if (mStatusBarStateController.isDozing()) {
mDozeScrimController.extendPulse();
}
- mLockIconViewController.onTouchEvent(
- ev,
- /* onGestureDetectedRunnable */
- () -> {
- mService.userActivity();
- mPowerInteractor.wakeUpIfDozing(
- "LOCK_ICON_TOUCH",
- PowerManager.WAKE_REASON_GESTURE);
- }
- );
// In case we start outside of the view bounds (below the status bar), we need to
// dispatch the touch manually as the view system can't accommodate for touches
@@ -415,8 +412,18 @@
private boolean shouldInterceptTouchEventInternal(MotionEvent ev) {
mLastInterceptWasDragDownHelper = false;
- if (mStatusBarStateController.isDozing() && !mDozeServiceHost.isPulsing()
- && !mDockManager.isDocked()) {
+ // When the device starts dozing, there's a delay before the device's display state
+ // changes from ON => DOZE to allow for the light reveal animation to run at
+ // a higher refresh rate and to delay visual changes (ie: display blink) when
+ // changing the display state. We'll call this specific state the
+ // "aodDefermentState". In this state we:
+ // - don't want touches to get sent to underlying views, except the lock icon
+ // - handle the tap to wake gesture via the PulsingGestureListener
+ if (mStatusBarStateController.isDozing()
+ && !mDozeServiceHost.isPulsing()
+ && !mDockManager.isDocked()
+ && !mLockIconViewController.willHandleTouchWhileDozing(ev)
+ ) {
if (ev.getAction() == MotionEvent.ACTION_DOWN) {
mShadeLogger.d("NSWVC: capture all touch events in always-on");
}
@@ -432,16 +439,15 @@
return true;
}
- if (mLockIconViewController.onInterceptTouchEvent(ev)) {
- // immediately return true; don't send the touch to the drag down helper
- if (ev.getAction() == MotionEvent.ACTION_DOWN) {
- mShadeLogger.d("NSWVC: don't send touch to drag down helper");
- }
- return true;
+ boolean bouncerShowing;
+ if (mFeatureFlags.isEnabled(Flags.ALTERNATE_BOUNCER_VIEW)) {
+ bouncerShowing = mPrimaryBouncerInteractor.isBouncerShowing()
+ || mAlternateBouncerInteractor.isVisibleState();
+ } else {
+ bouncerShowing = mService.isBouncerShowing();
}
-
if (mNotificationPanelViewController.isFullyExpanded()
- && !mService.isBouncerShowing()
+ && !bouncerShowing
&& !mStatusBarStateController.isDozing()) {
if (mDragDownHelper.isDragDownEnabled()) {
// This handles drag down over lockscreen
diff --git a/packages/SystemUI/src/com/android/systemui/shade/ShadeController.java b/packages/SystemUI/src/com/android/systemui/shade/ShadeController.java
index 447a15d..2c4b0b9 100644
--- a/packages/SystemUI/src/com/android/systemui/shade/ShadeController.java
+++ b/packages/SystemUI/src/com/android/systemui/shade/ShadeController.java
@@ -178,9 +178,6 @@
/** Listens for shade visibility changes. */
interface ShadeVisibilityListener {
- /** Called when the visibility of the shade changes. */
- void visibilityChanged(boolean visible);
-
/** Called when shade expanded and visible state changed. */
void expandedVisibleChanged(boolean expandedVisible);
}
diff --git a/packages/SystemUI/src/com/android/systemui/shade/ShadeControllerImpl.java b/packages/SystemUI/src/com/android/systemui/shade/ShadeControllerImpl.java
index 367449b..fdc7eec 100644
--- a/packages/SystemUI/src/com/android/systemui/shade/ShadeControllerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/shade/ShadeControllerImpl.java
@@ -24,6 +24,7 @@
import android.view.WindowManager;
import android.view.WindowManagerGlobal;
+import com.android.systemui.DejankUtils;
import com.android.systemui.assist.AssistManager;
import com.android.systemui.dagger.SysUISingleton;
import com.android.systemui.dagger.qualifiers.Main;
@@ -75,6 +76,7 @@
private final ArrayList<Runnable> mPostCollapseRunnables = new ArrayList<>();
private boolean mExpandedVisible;
+ private boolean mLockscreenOrShadeVisible;
private NotificationPresenter mPresenter;
private NotificationShadeWindowViewController mNotificationShadeWindowViewController;
@@ -399,8 +401,19 @@
}
private void notifyVisibilityChanged(boolean visible) {
- mShadeVisibilityListener.visibilityChanged(visible);
mWindowRootViewVisibilityInteractor.setIsLockscreenOrShadeVisible(visible);
+ if (mLockscreenOrShadeVisible != visible) {
+ mLockscreenOrShadeVisible = visible;
+ if (visible) {
+ // It would be best if this could be done as a side effect of listening to the
+ // [WindowRootViewVisibilityInteractor.isLockscreenOrShadeVisible] flow inside
+ // NotificationShadeWindowViewController. However, there's no guarantee that the
+ // flow will emit in the same frame as when the visibility changed, and we want the
+ // DejankUtils to be notified immediately, so we do it immediately here.
+ DejankUtils.notifyRendererOfExpensiveFrame(
+ getNotificationShadeWindowView(), "onShadeVisibilityChanged");
+ }
+ }
}
private void notifyExpandedVisibleChanged(boolean expandedVisible) {
diff --git a/packages/SystemUI/src/com/android/systemui/shade/ShadeSurface.kt b/packages/SystemUI/src/com/android/systemui/shade/ShadeSurface.kt
index 6ee6cbf..4e23e7d 100644
--- a/packages/SystemUI/src/com/android/systemui/shade/ShadeSurface.kt
+++ b/packages/SystemUI/src/com/android/systemui/shade/ShadeSurface.kt
@@ -20,7 +20,7 @@
import com.android.systemui.statusbar.NotificationShelfController
import com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayoutController
import com.android.systemui.statusbar.phone.CentralSurfaces
-import com.android.systemui.statusbar.phone.HeadsUpManagerPhone
+import com.android.systemui.statusbar.policy.HeadsUpManager
/**
* Allows CentralSurfacesImpl to interact with the shade. Only CentralSurfacesImpl should reference
@@ -34,7 +34,7 @@
recorder: GestureRecorder,
hideExpandedRunnable: Runnable,
notificationShelfController: NotificationShelfController,
- headsUpManager: HeadsUpManagerPhone
+ headsUpManager: HeadsUpManager
)
/** Cancels any pending collapses. */
diff --git a/packages/SystemUI/src/com/android/systemui/shade/domain/interactor/ShadeInteractor.kt b/packages/SystemUI/src/com/android/systemui/shade/domain/interactor/ShadeInteractor.kt
index ac8333a..6117f9f 100644
--- a/packages/SystemUI/src/com/android/systemui/shade/domain/interactor/ShadeInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/shade/domain/interactor/ShadeInteractor.kt
@@ -19,7 +19,11 @@
import com.android.systemui.dagger.SysUISingleton
import com.android.systemui.dagger.qualifiers.Application
import com.android.systemui.keyguard.data.repository.KeyguardRepository
+import com.android.systemui.keyguard.domain.interactor.KeyguardTransitionInteractor
+import com.android.systemui.keyguard.shared.model.DozeStateModel
+import com.android.systemui.keyguard.shared.model.KeyguardState
import com.android.systemui.keyguard.shared.model.StatusBarState
+import com.android.systemui.power.domain.interactor.PowerInteractor
import com.android.systemui.scene.domain.interactor.SceneInteractor
import com.android.systemui.scene.shared.flag.SceneContainerFlags
import com.android.systemui.scene.shared.model.ObservableTransitionState
@@ -27,8 +31,9 @@
import com.android.systemui.shade.data.repository.ShadeRepository
import com.android.systemui.statusbar.disableflags.data.repository.DisableFlagsRepository
import com.android.systemui.statusbar.notification.stack.domain.interactor.SharedNotificationContainerInteractor
+import com.android.systemui.statusbar.phone.DozeParameters
import com.android.systemui.statusbar.pipeline.mobile.data.repository.UserSetupRepository
-import com.android.systemui.statusbar.policy.DeviceProvisionedController
+import com.android.systemui.statusbar.policy.data.repository.DeviceProvisioningRepository
import com.android.systemui.user.domain.interactor.UserInteractor
import com.android.systemui.util.kotlin.pairwise
import javax.inject.Inject
@@ -56,13 +61,16 @@
@Inject
constructor(
@Application scope: CoroutineScope,
+ deviceProvisioningRepository: DeviceProvisioningRepository,
disableFlagsRepository: DisableFlagsRepository,
+ dozeParams: DozeParameters,
sceneContainerFlags: SceneContainerFlags,
// TODO(b/300258424) convert to direct reference instead of provider
sceneInteractorProvider: Provider<SceneInteractor>,
keyguardRepository: KeyguardRepository,
+ keyguardTransitionInteractor: KeyguardTransitionInteractor,
+ powerInteractor: PowerInteractor,
userSetupRepository: UserSetupRepository,
- deviceProvisionedController: DeviceProvisionedController,
userInteractor: UserInteractor,
sharedNotificationContainerInteractor: SharedNotificationContainerInteractor,
repository: ShadeRepository,
@@ -187,6 +195,26 @@
combine(isUserInteractingWithShade, isUserInteractingWithShade) { shade, qs -> shade || qs }
.distinctUntilChanged()
+ /** Are touches allowed on the notification panel? */
+ val isShadeTouchable: Flow<Boolean> =
+ combine(
+ powerInteractor.isAsleep,
+ keyguardTransitionInteractor.isInTransitionToStateWhere { it == KeyguardState.AOD },
+ keyguardRepository.dozeTransitionModel.map { it.to == DozeStateModel.DOZE_PULSING },
+ deviceProvisioningRepository.isFactoryResetProtectionActive,
+ ) { isAsleep, goingToSleep, isPulsing, isFrpActive ->
+ when {
+ // Touches are disabled when Factory Reset Protection is active
+ isFrpActive -> false
+ // If the device is going to sleep, only accept touches if we're still
+ // animating
+ goingToSleep -> dozeParams.shouldControlScreenOff()
+ // If the device is asleep, only accept touches if there's a pulse
+ isAsleep -> isPulsing
+ else -> true
+ }
+ }
+
/** Emits true if the shade can be expanded from QQS to QS and false otherwise. */
val isExpandToQsEnabled: Flow<Boolean> =
combine(
@@ -194,8 +222,9 @@
isShadeEnabled,
keyguardRepository.isDozing,
userSetupRepository.isUserSetupFlow,
- ) { disableFlags, isShadeEnabled, isDozing, isUserSetup ->
- deviceProvisionedController.isDeviceProvisioned &&
+ deviceProvisioningRepository.isDeviceProvisioned,
+ ) { disableFlags, isShadeEnabled, isDozing, isUserSetup, isDeviceProvisioned ->
+ isDeviceProvisioned &&
// Disallow QS during setup if it's a simple user switcher. (The user intends to
// use the lock screen user switcher, QS is not needed.)
(isUserSetup || !userInteractor.isSimpleUserSwitcher) &&
@@ -232,7 +261,7 @@
when (state) {
is ObservableTransitionState.Idle -> false
is ObservableTransitionState.Transition ->
- state.isUserInputDriven &&
+ state.isInitiatedByUserInput &&
(state.toScene == sceneKey || state.fromScene == sceneKey)
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/PulseExpansionHandler.kt b/packages/SystemUI/src/com/android/systemui/statusbar/PulseExpansionHandler.kt
index 3640ae0..4ea7026 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/PulseExpansionHandler.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/PulseExpansionHandler.kt
@@ -31,22 +31,22 @@
import com.android.app.animation.Interpolators
import com.android.systemui.Dumpable
import com.android.systemui.Gefingerpoken
-import com.android.systemui.res.R
import com.android.systemui.classifier.Classifier.NOTIFICATION_DRAG_DOWN
import com.android.systemui.classifier.FalsingCollector
import com.android.systemui.dagger.SysUISingleton
import com.android.systemui.dump.DumpManager
import com.android.systemui.plugins.FalsingManager
import com.android.systemui.plugins.statusbar.StatusBarStateController
+import com.android.systemui.res.R
import com.android.systemui.shade.ShadeExpansionStateManager
import com.android.systemui.statusbar.notification.NotificationWakeUpCoordinator
import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow
import com.android.systemui.statusbar.notification.row.ExpandableView
import com.android.systemui.statusbar.notification.stack.NotificationRoundnessManager
import com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayoutController
-import com.android.systemui.statusbar.phone.HeadsUpManagerPhone
import com.android.systemui.statusbar.phone.KeyguardBypassController
import com.android.systemui.statusbar.policy.ConfigurationController
+import com.android.systemui.statusbar.policy.HeadsUpManager
import java.io.PrintWriter
import javax.inject.Inject
import kotlin.math.max
@@ -63,7 +63,7 @@
context: Context,
private val wakeUpCoordinator: NotificationWakeUpCoordinator,
private val bypassController: KeyguardBypassController,
- private val headsUpManager: HeadsUpManagerPhone,
+ private val headsUpManager: HeadsUpManager,
private val roundnessManager: NotificationRoundnessManager,
configurationController: ConfigurationController,
private val statusBarStateController: StatusBarStateController,
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationLaunchAnimatorController.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationLaunchAnimatorController.kt
index c62546f..756151b 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationLaunchAnimatorController.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationLaunchAnimatorController.kt
@@ -24,7 +24,7 @@
import com.android.systemui.statusbar.notification.data.repository.NotificationExpansionRepository
import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow
import com.android.systemui.statusbar.notification.stack.NotificationListContainer
-import com.android.systemui.statusbar.phone.HeadsUpManagerPhone
+import com.android.systemui.statusbar.policy.HeadsUpManager
import com.android.systemui.statusbar.policy.HeadsUpUtil
import kotlin.math.ceil
import kotlin.math.max
@@ -35,7 +35,7 @@
class NotificationLaunchAnimatorControllerProvider(
private val notificationExpansionRepository: NotificationExpansionRepository,
private val notificationListContainer: NotificationListContainer,
- private val headsUpManager: HeadsUpManagerPhone,
+ private val headsUpManager: HeadsUpManager,
private val jankMonitor: InteractionJankMonitor
) {
@JvmOverloads
@@ -62,7 +62,7 @@
class NotificationLaunchAnimatorController(
private val notificationExpansionRepository: NotificationExpansionRepository,
private val notificationListContainer: NotificationListContainer,
- private val headsUpManager: HeadsUpManagerPhone,
+ private val headsUpManager: HeadsUpManager,
private val notification: ExpandableNotificationRow,
private val jankMonitor: InteractionJankMonitor,
private val onFinishAnimationCallback: Runnable?
@@ -152,16 +152,17 @@
}
}
- private val headsUpNotificationRow: ExpandableNotificationRow? get() {
- val summaryEntry = notificationEntry.parent?.summary
+ private val headsUpNotificationRow: ExpandableNotificationRow?
+ get() {
+ val summaryEntry = notificationEntry.parent?.summary
- return when {
- headsUpManager.isAlerting(notificationKey) -> notification
- summaryEntry == null -> null
- headsUpManager.isAlerting(summaryEntry.key) -> summaryEntry.row
- else -> null
+ return when {
+ headsUpManager.isAlerting(notificationKey) -> notification
+ summaryEntry == null -> null
+ headsUpManager.isAlerting(summaryEntry.key) -> summaryEntry.row
+ else -> null
+ }
}
- }
private fun removeHun(animate: Boolean) {
val row = headsUpNotificationRow ?: return
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/KeyguardCoordinator.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/KeyguardCoordinator.kt
index 07eb8a00..2d83970 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/KeyguardCoordinator.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/KeyguardCoordinator.kt
@@ -37,8 +37,8 @@
import com.android.systemui.statusbar.notification.collection.listbuilder.pluggable.NotifFilter
import com.android.systemui.statusbar.notification.collection.notifcollection.NotifCollectionListener
import com.android.systemui.statusbar.notification.collection.provider.SectionHeaderVisibilityProvider
-import com.android.systemui.statusbar.notification.collection.provider.SeenNotificationsProviderImpl
import com.android.systemui.statusbar.notification.interruption.KeyguardNotificationVisibilityProvider
+import com.android.systemui.statusbar.notification.stack.domain.interactor.NotificationListInteractor
import com.android.systemui.statusbar.policy.HeadsUpManager
import com.android.systemui.statusbar.policy.headsUpEvents
import com.android.systemui.util.asIndenting
@@ -85,7 +85,7 @@
@Application private val scope: CoroutineScope,
private val sectionHeaderVisibilityProvider: SectionHeaderVisibilityProvider,
private val secureSettings: SecureSettings,
- private val seenNotifsProvider: SeenNotificationsProviderImpl,
+ private val notificationListInteractor: NotificationListInteractor,
private val statusBarStateController: StatusBarStateController,
) : Coordinator, Dumpable {
@@ -351,7 +351,7 @@
override fun onCleanup() {
logger.logProviderHasFilteredOutSeenNotifs(hasFilteredAnyNotifs)
- seenNotifsProvider.hasFilteredOutSeenNotifications = hasFilteredAnyNotifs
+ notificationListInteractor.setHasFilteredOutSeenNotifications(hasFilteredAnyNotifs)
hasFilteredAnyNotifs = false
}
}
@@ -388,8 +388,8 @@
override fun dump(pw: PrintWriter, args: Array<out String>) =
with(pw.asIndenting()) {
println(
- "seenNotifsProvider.hasFilteredOutSeenNotifications=" +
- seenNotifsProvider.hasFilteredOutSeenNotifications
+ "notificationListInteractor.hasFilteredOutSeenNotifications.value=" +
+ notificationListInteractor.hasFilteredOutSeenNotifications.value
)
println("unseen notifications:")
indentIfPossible {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/ViewConfigCoordinator.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/ViewConfigCoordinator.kt
index 657c394d..c0f674846 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/ViewConfigCoordinator.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/ViewConfigCoordinator.kt
@@ -28,6 +28,7 @@
import com.android.systemui.statusbar.notification.row.NotificationGutsManager
import com.android.systemui.statusbar.policy.ConfigurationController
import com.android.systemui.util.Compile
+import com.android.systemui.util.traceSection
import javax.inject.Inject
/**
@@ -122,8 +123,10 @@
private fun updateNotificationsOnUiModeChanged() {
log { "ViewConfigCoordinator.updateNotificationsOnUiModeChanged()" }
- mPipeline?.allNotifs?.forEach { entry ->
- entry.row?.onUiModeChanged()
+ traceSection("updateNotifOnUiModeChanged") {
+ mPipeline?.allNotifs?.forEach { entry ->
+ entry.row?.onUiModeChanged()
+ }
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/provider/SeenNotificationsProvider.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/provider/SeenNotificationsProvider.kt
deleted file mode 100644
index cff47e2..0000000
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/provider/SeenNotificationsProvider.kt
+++ /dev/null
@@ -1,41 +0,0 @@
-/*
- * Copyright (C) 2022 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.systemui.statusbar.notification.collection.provider
-
-import com.android.systemui.dagger.SysUISingleton
-import dagger.Binds
-import dagger.Module
-import javax.inject.Inject
-
-/** Keeps track of whether "seen" notification content has been filtered out of the shade. */
-interface SeenNotificationsProvider {
- /** Are any already-seen notifications currently filtered out of the shade? */
- val hasFilteredOutSeenNotifications: Boolean
-}
-
-@Module
-interface SeenNotificationsProviderModule {
- @Binds
- fun bindSeenNotificationsProvider(
- impl: SeenNotificationsProviderImpl
- ): SeenNotificationsProvider
-}
-
-@SysUISingleton
-class SeenNotificationsProviderImpl @Inject constructor() : SeenNotificationsProvider {
- override var hasFilteredOutSeenNotifications: Boolean = false
-}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/render/ShadeViewDiffer.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/render/ShadeViewDiffer.kt
index 59fc387..1a88815 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/render/ShadeViewDiffer.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/render/ShadeViewDiffer.kt
@@ -231,18 +231,24 @@
fun getChildCount(): Int = controller.getChildCount()
fun addChildAt(child: ShadeNode, index: Int) {
- controller.addChildAt(child.controller, index)
- child.controller.onViewAdded()
+ traceSection("ShadeNode#addChildAt") {
+ controller.addChildAt(child.controller, index)
+ child.controller.onViewAdded()
+ }
}
fun moveChildTo(child: ShadeNode, index: Int) {
- controller.moveChildTo(child.controller, index)
- child.controller.onViewMoved()
+ traceSection("ShadeNode#moveChildTo") {
+ controller.moveChildTo(child.controller, index)
+ child.controller.onViewMoved()
+ }
}
fun removeChild(child: ShadeNode, isTransfer: Boolean) {
- controller.removeChild(child.controller, isTransfer)
- child.controller.onViewRemoved()
+ traceSection("ShadeNode#removeChild") {
+ controller.removeChild(child.controller, isTransfer)
+ child.controller.onViewRemoved()
+ }
}
fun offerToKeepInParentForAnimation(): Boolean {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/dagger/NotificationsModule.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/dagger/NotificationsModule.java
index 8ee0de6..733d774 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/dagger/NotificationsModule.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/dagger/NotificationsModule.java
@@ -20,10 +20,10 @@
import com.android.internal.jank.InteractionJankMonitor;
import com.android.systemui.CoreStartable;
-import com.android.systemui.res.R;
import com.android.systemui.dagger.SysUISingleton;
import com.android.systemui.dagger.qualifiers.UiBackground;
import com.android.systemui.plugins.statusbar.StatusBarStateController;
+import com.android.systemui.res.R;
import com.android.systemui.scene.domain.interactor.WindowRootViewVisibilityInteractor;
import com.android.systemui.shade.ShadeEventsModule;
import com.android.systemui.statusbar.NotificationListener;
@@ -45,7 +45,6 @@
import com.android.systemui.statusbar.notification.collection.provider.NotificationDismissibilityProvider;
import com.android.systemui.statusbar.notification.collection.provider.NotificationDismissibilityProviderImpl;
import com.android.systemui.statusbar.notification.collection.provider.NotificationVisibilityProviderImpl;
-import com.android.systemui.statusbar.notification.collection.provider.SeenNotificationsProviderModule;
import com.android.systemui.statusbar.notification.collection.provider.VisibilityLocationProviderDelegator;
import com.android.systemui.statusbar.notification.collection.render.GroupExpansionManager;
import com.android.systemui.statusbar.notification.collection.render.GroupExpansionManagerImpl;
@@ -74,9 +73,9 @@
import com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayoutController;
import com.android.systemui.statusbar.notification.stack.StackScrollAlgorithm;
import com.android.systemui.statusbar.notification.stack.ui.viewmodel.NotificationListViewModelModule;
-import com.android.systemui.statusbar.phone.HeadsUpManagerPhone;
import com.android.systemui.statusbar.phone.KeyguardBypassController;
import com.android.systemui.statusbar.phone.StatusBarNotificationActivityStarter;
+import com.android.systemui.statusbar.policy.HeadsUpManager;
import com.android.systemui.util.kotlin.JavaAdapter;
import dagger.Binds;
@@ -95,7 +94,6 @@
@Module(includes = {
CoordinatorsModule.class,
KeyguardNotificationVisibilityProviderModule.class,
- SeenNotificationsProviderModule.class,
ShadeEventsModule.class,
NotifPipelineChoreographerModule.class,
NotificationSectionHeadersModule.class,
@@ -206,7 +204,7 @@
static NotificationLaunchAnimatorControllerProvider provideNotifLaunchAnimControllerProvider(
NotificationExpansionRepository notificationExpansionRepository,
NotificationListContainer notificationListContainer,
- HeadsUpManagerPhone headsUpManager,
+ HeadsUpManager headsUpManager,
InteractionJankMonitor jankMonitor) {
return new NotificationLaunchAnimatorControllerProvider(
notificationExpansionRepository,
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/icon/ui/viewbinder/NotificationIconAreaControllerViewBinderWrapperImpl.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/icon/ui/viewbinder/NotificationIconAreaControllerViewBinderWrapperImpl.kt
index 5cc5e75..a77e67b 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/icon/ui/viewbinder/NotificationIconAreaControllerViewBinderWrapperImpl.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/icon/ui/viewbinder/NotificationIconAreaControllerViewBinderWrapperImpl.kt
@@ -118,7 +118,6 @@
private var aodIcons: NotificationIconContainer? = null
private var aodBindJob: DisposableHandle? = null
private var aodIconAppearTranslation = 0
- private var animationsEnabled = false
private var aodIconTint = 0
private var aodIconsVisible = false
private var showLowPriority = true
@@ -157,9 +156,12 @@
}
this.aodIcons = aodIcons
this.aodIcons!!.setOnLockScreen(true)
- aodBindJob = NotificationIconContainerViewBinder.bind(aodIcons, aodIconsViewModel)
+ aodBindJob =
+ NotificationIconContainerViewBinder.bind(
+ aodIcons,
+ aodIconsViewModel,
+ )
updateAodIconsVisibility(animate = false, forceUpdate = changed)
- updateAnimations()
if (changed) {
updateAodNotificationIcons()
}
@@ -171,7 +173,10 @@
override fun setShelfIcons(icons: NotificationIconContainer) {
if (shelfRefactor.expectEnabled()) {
- NotificationIconContainerViewBinder.bind(icons, shelfIconsViewModel)
+ NotificationIconContainerViewBinder.bind(
+ icons,
+ shelfIconsViewModel,
+ )
shelfIcons = icons
}
}
@@ -252,14 +257,10 @@
aodIcons!!.setDozing(isDozing, animate, 0)
}
- override fun setAnimationsEnabled(enabled: Boolean) {
- animationsEnabled = enabled
- updateAnimations()
- }
+ override fun setAnimationsEnabled(enabled: Boolean) = unsupported
override fun onStateChanged(newState: Int) {
updateAodIconsVisibility(animate = false, forceUpdate = false)
- updateAnimations()
}
override fun onThemeChanged() {
@@ -348,7 +349,10 @@
val layoutInflater = LayoutInflater.from(context)
notificationIconArea = inflateIconArea(layoutInflater)
notificationIcons = notificationIconArea?.findViewById(R.id.notificationIcons)
- NotificationIconContainerViewBinder.bind(notificationIcons!!, statusBarIconsViewModel)
+ NotificationIconContainerViewBinder.bind(
+ notificationIcons!!,
+ statusBarIconsViewModel,
+ )
}
private fun updateIconLayoutParams(context: Context) {
@@ -598,14 +602,6 @@
v.setDecorColor(tint)
}
- private fun updateAnimations() {
- val inShade = statusBarStateController.state == StatusBarState.SHADE
- if (aodIcons != null) {
- aodIcons!!.setAnimationsEnabled(animationsEnabled && !inShade)
- }
- notificationIcons!!.setAnimationsEnabled(animationsEnabled && inShade)
- }
-
private fun animateInAodIconTranslation() {
if (!statusViewMigrated) {
aodIcons!!
@@ -702,7 +698,12 @@
companion object {
private const val AOD_ICONS_APPEAR_DURATION: Long = 200
-
@ColorInt private val DEFAULT_AOD_ICON_COLOR = -0x1
+
+ val unsupported: Nothing
+ get() =
+ error(
+ "Code path not supported when NOTIFICATION_ICON_CONTAINER_REFACTOR is disabled"
+ )
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/icon/ui/viewbinder/NotificationIconContainerViewBinder.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/icon/ui/viewbinder/NotificationIconContainerViewBinder.kt
index 8293bb3..f8ff3e3 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/icon/ui/viewbinder/NotificationIconContainerViewBinder.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/icon/ui/viewbinder/NotificationIconContainerViewBinder.kt
@@ -21,6 +21,7 @@
import com.android.systemui.statusbar.notification.icon.ui.viewmodel.NotificationIconContainerViewModel
import com.android.systemui.statusbar.phone.NotificationIconContainer
import kotlinx.coroutines.DisposableHandle
+import kotlinx.coroutines.launch
/** Binds a [NotificationIconContainer] to its [view model][NotificationIconContainerViewModel]. */
object NotificationIconContainerViewBinder {
@@ -28,6 +29,10 @@
view: NotificationIconContainer,
viewModel: NotificationIconContainerViewModel,
): DisposableHandle {
- return view.repeatWhenAttached { repeatOnLifecycle(Lifecycle.State.CREATED) {} }
+ return view.repeatWhenAttached {
+ repeatOnLifecycle(Lifecycle.State.CREATED) {
+ launch { viewModel.animationsEnabled.collect(view::setAnimationsEnabled) }
+ }
+ }
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/icon/ui/viewmodel/NotificationIconContainerAlwaysOnDisplayViewModel.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/icon/ui/viewmodel/NotificationIconContainerAlwaysOnDisplayViewModel.kt
index f68b0ef..90507fc 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/icon/ui/viewmodel/NotificationIconContainerAlwaysOnDisplayViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/icon/ui/viewmodel/NotificationIconContainerAlwaysOnDisplayViewModel.kt
@@ -15,8 +15,24 @@
*/
package com.android.systemui.statusbar.notification.icon.ui.viewmodel
+import com.android.systemui.keyguard.domain.interactor.KeyguardInteractor
+import com.android.systemui.shade.domain.interactor.ShadeInteractor
import javax.inject.Inject
+import kotlinx.coroutines.flow.Flow
+import kotlinx.coroutines.flow.combine
/** View-model for the row of notification icons displayed on the always-on display. */
-class NotificationIconContainerAlwaysOnDisplayViewModel @Inject constructor() :
- NotificationIconContainerViewModel
+class NotificationIconContainerAlwaysOnDisplayViewModel
+@Inject
+constructor(
+ keyguardInteractor: KeyguardInteractor,
+ shadeInteractor: ShadeInteractor,
+) : NotificationIconContainerViewModel {
+ override val animationsEnabled: Flow<Boolean> =
+ combine(
+ shadeInteractor.isShadeTouchable,
+ keyguardInteractor.isKeyguardVisible,
+ ) { panelTouchesEnabled, isKeyguardVisible ->
+ panelTouchesEnabled && isKeyguardVisible
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/icon/ui/viewmodel/NotificationIconContainerShelfViewModel.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/icon/ui/viewmodel/NotificationIconContainerShelfViewModel.kt
index 933c76f..49f262d 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/icon/ui/viewmodel/NotificationIconContainerShelfViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/icon/ui/viewmodel/NotificationIconContainerShelfViewModel.kt
@@ -16,7 +16,11 @@
package com.android.systemui.statusbar.notification.icon.ui.viewmodel
import javax.inject.Inject
+import kotlinx.coroutines.flow.Flow
+import kotlinx.coroutines.flow.flowOf
/** View-model for the overflow row of notification icons displayed in the notification shade. */
class NotificationIconContainerShelfViewModel @Inject constructor() :
- NotificationIconContainerViewModel
+ NotificationIconContainerViewModel {
+ override val animationsEnabled: Flow<Boolean> = flowOf(true)
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/icon/ui/viewmodel/NotificationIconContainerStatusBarViewModel.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/icon/ui/viewmodel/NotificationIconContainerStatusBarViewModel.kt
index 2217646..ee57b78 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/icon/ui/viewmodel/NotificationIconContainerStatusBarViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/icon/ui/viewmodel/NotificationIconContainerStatusBarViewModel.kt
@@ -15,8 +15,24 @@
*/
package com.android.systemui.statusbar.notification.icon.ui.viewmodel
+import com.android.systemui.keyguard.domain.interactor.KeyguardInteractor
+import com.android.systemui.shade.domain.interactor.ShadeInteractor
import javax.inject.Inject
+import kotlinx.coroutines.flow.Flow
+import kotlinx.coroutines.flow.combine
/** View-model for the row of notification icons displayed in the status bar, */
-class NotificationIconContainerStatusBarViewModel @Inject constructor() :
- NotificationIconContainerViewModel
+class NotificationIconContainerStatusBarViewModel
+@Inject
+constructor(
+ keyguardInteractor: KeyguardInteractor,
+ shadeInteractor: ShadeInteractor,
+) : NotificationIconContainerViewModel {
+ override val animationsEnabled: Flow<Boolean> =
+ combine(
+ shadeInteractor.isShadeTouchable,
+ keyguardInteractor.isKeyguardShowing,
+ ) { panelTouchesEnabled, isKeyguardShowing ->
+ panelTouchesEnabled && !isKeyguardShowing
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/icon/ui/viewmodel/NotificationIconContainerViewModel.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/icon/ui/viewmodel/NotificationIconContainerViewModel.kt
index 892b2be..6f8ce4b 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/icon/ui/viewmodel/NotificationIconContainerViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/icon/ui/viewmodel/NotificationIconContainerViewModel.kt
@@ -15,8 +15,13 @@
*/
package com.android.systemui.statusbar.notification.icon.ui.viewmodel
+import kotlinx.coroutines.flow.Flow
+
/**
* View-model for the row of notification icons displayed in the NotificationShelf, StatusBar, and
* AOD.
*/
-interface NotificationIconContainerViewModel
+interface NotificationIconContainerViewModel {
+ /** Are changes to the icon container animated? */
+ val animationsEnabled: Flow<Boolean>
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ActivatableNotificationView.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ActivatableNotificationView.java
index c61258b..847d948 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ActivatableNotificationView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ActivatableNotificationView.java
@@ -355,12 +355,8 @@
AnimatorListenerAdapter animationListener) {
enableAppearDrawing(true);
mIsHeadsUpAnimation = isHeadsUpAnimation;
- if (mDrawingAppearAnimation) {
- startAppearAnimation(false /* isAppearing */, translationDirection,
- delay, duration, onFinishedRunnable, animationListener);
- } else if (onFinishedRunnable != null) {
- onFinishedRunnable.run();
- }
+ startAppearAnimation(false /* isAppearing */, translationDirection,
+ delay, duration, onFinishedRunnable, animationListener);
return 0;
}
@@ -369,10 +365,8 @@
Runnable onFinishRunnable) {
enableAppearDrawing(true);
mIsHeadsUpAnimation = isHeadsUpAppear;
- if (mDrawingAppearAnimation) {
- startAppearAnimation(true /* isAppearing */, isHeadsUpAppear ? 0.0f : -1.0f, delay,
- duration, null, null);
- }
+ startAppearAnimation(true /* isAppearing */, isHeadsUpAppear ? 0.0f : -1.0f, delay,
+ duration, null, null);
}
private void startAppearAnimation(boolean isAppearing, float translationDirection, long delay,
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/FeedbackInfo.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/FeedbackInfo.java
index 42c80ed..40897da 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/FeedbackInfo.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/FeedbackInfo.java
@@ -42,9 +42,8 @@
import android.widget.TextView;
import com.android.internal.statusbar.IStatusBarService;
-import com.android.systemui.Dependency;
-import com.android.systemui.res.R;
import com.android.systemui.plugins.statusbar.NotificationMenuRowPlugin;
+import com.android.systemui.res.R;
import com.android.systemui.statusbar.notification.AssistantFeedbackController;
import com.android.systemui.statusbar.notification.collection.NotificationEntry;
import com.android.systemui.util.Compile;
@@ -76,7 +75,9 @@
final StatusBarNotification sbn,
final NotificationEntry entry,
final ExpandableNotificationRow row,
- final AssistantFeedbackController controller) {
+ final AssistantFeedbackController controller,
+ final IStatusBarService statusBarService,
+ final NotificationGutsManager notificationGutsManager) {
mPkg = sbn.getPackageName();
mPm = pm;
mEntry = entry;
@@ -84,8 +85,8 @@
mRanking = entry.getRanking();
mFeedbackController = controller;
mAppName = mPkg;
- mStatusBarService = Dependency.get(IStatusBarService.class);
- mNotificationGutsManager = Dependency.get(NotificationGutsManager.class);
+ mStatusBarService = statusBarService;
+ mNotificationGutsManager = notificationGutsManager;
bindHeader();
bindPrompt();
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationGutsManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationGutsManager.java
index 6d656605..9e9116b 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationGutsManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationGutsManager.java
@@ -44,9 +44,9 @@
import com.android.internal.logging.MetricsLogger;
import com.android.internal.logging.UiEventLogger;
import com.android.internal.logging.nano.MetricsProto;
+import com.android.internal.statusbar.IStatusBarService;
import com.android.settingslib.notification.ConversationIconFactory;
import com.android.systemui.CoreStartable;
-import com.android.systemui.res.R;
import com.android.systemui.dagger.SysUISingleton;
import com.android.systemui.dagger.qualifiers.Background;
import com.android.systemui.dagger.qualifiers.Main;
@@ -54,6 +54,7 @@
import com.android.systemui.plugins.ActivityStarter;
import com.android.systemui.plugins.statusbar.NotificationMenuRowPlugin;
import com.android.systemui.plugins.statusbar.StatusBarStateController;
+import com.android.systemui.res.R;
import com.android.systemui.scene.domain.interactor.WindowRootViewVisibilityInteractor;
import com.android.systemui.settings.UserContextProvider;
import com.android.systemui.shade.ShadeController;
@@ -69,8 +70,8 @@
import com.android.systemui.statusbar.notification.collection.render.NotifGutsViewManager;
import com.android.systemui.statusbar.notification.stack.NotificationListContainer;
import com.android.systemui.statusbar.phone.CentralSurfaces;
-import com.android.systemui.statusbar.phone.HeadsUpManagerPhone;
import com.android.systemui.statusbar.policy.DeviceProvisionedController;
+import com.android.systemui.statusbar.policy.HeadsUpManager;
import com.android.systemui.util.kotlin.JavaAdapter;
import com.android.systemui.wmshell.BubblesManager;
@@ -99,6 +100,7 @@
// Dependencies:
private final NotificationLockscreenUserManager mLockscreenUserManager;
private final StatusBarStateController mStatusBarStateController;
+ private final IStatusBarService mStatusBarService;
private final DeviceProvisionedController mDeviceProvisionedController;
private final AssistantFeedbackController mAssistantFeedbackController;
@@ -127,7 +129,7 @@
private final ShadeController mShadeController;
private final WindowRootViewVisibilityInteractor mWindowRootViewVisibilityInteractor;
private NotifGutsViewListener mGutsListener;
- private final HeadsUpManagerPhone mHeadsUpManagerPhone;
+ private final HeadsUpManager mHeadsUpManager;
private final ActivityStarter mActivityStarter;
@Inject
@@ -152,9 +154,10 @@
WindowRootViewVisibilityInteractor windowRootViewVisibilityInteractor,
NotificationLockscreenUserManager notificationLockscreenUserManager,
StatusBarStateController statusBarStateController,
+ IStatusBarService statusBarService,
DeviceProvisionedController deviceProvisionedController,
MetricsLogger metricsLogger,
- HeadsUpManagerPhone headsUpManagerPhone,
+ HeadsUpManager headsUpManager,
ActivityStarter activityStarter) {
mContext = context;
mMainHandler = mainHandler;
@@ -177,9 +180,10 @@
mWindowRootViewVisibilityInteractor = windowRootViewVisibilityInteractor;
mLockscreenUserManager = notificationLockscreenUserManager;
mStatusBarStateController = statusBarStateController;
+ mStatusBarService = statusBarService;
mDeviceProvisionedController = deviceProvisionedController;
mMetricsLogger = metricsLogger;
- mHeadsUpManagerPhone = headsUpManagerPhone;
+ mHeadsUpManager = headsUpManager;
mActivityStarter = activityStarter;
}
@@ -296,7 +300,7 @@
if (mGutsListener != null) {
mGutsListener.onGutsClose(entry);
}
- mHeadsUpManagerPhone.setGutsShown(row.getEntry(), false);
+ mHeadsUpManager.setGutsShown(row.getEntry(), false);
});
View gutsView = item.getGutsView();
@@ -358,7 +362,8 @@
PackageManager pmUser = CentralSurfaces.getPackageManagerForUser(mContext,
userHandle.getIdentifier());
- feedbackInfo.bindGuts(pmUser, sbn, row.getEntry(), row, mAssistantFeedbackController);
+ feedbackInfo.bindGuts(pmUser, sbn, row.getEntry(), row, mAssistantFeedbackController,
+ mStatusBarService, this);
}
/**
@@ -676,7 +681,7 @@
row.closeRemoteInput();
mListContainer.onHeightChanged(row, true /* needsAnimation */);
mGutsMenuItem = menuItem;
- mHeadsUpManagerPhone.setGutsShown(row.getEntry(), true);
+ mHeadsUpManager.setGutsShown(row.getEntry(), true);
}
};
guts.post(mOpenRunnable);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutController.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutController.java
index 66b2555..9695cb1 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutController.java
@@ -99,7 +99,6 @@
import com.android.systemui.statusbar.notification.collection.notifcollection.DismissedByUserStats;
import com.android.systemui.statusbar.notification.collection.notifcollection.NotifCollectionListener;
import com.android.systemui.statusbar.notification.collection.provider.NotificationDismissibilityProvider;
-import com.android.systemui.statusbar.notification.collection.provider.SeenNotificationsProvider;
import com.android.systemui.statusbar.notification.collection.provider.VisibilityLocationProviderDelegator;
import com.android.systemui.statusbar.notification.collection.render.GroupExpansionManager;
import com.android.systemui.statusbar.notification.collection.render.NotifStackController;
@@ -115,10 +114,10 @@
import com.android.systemui.statusbar.notification.row.NotificationGuts;
import com.android.systemui.statusbar.notification.row.NotificationGutsManager;
import com.android.systemui.statusbar.notification.row.NotificationSnooze;
+import com.android.systemui.statusbar.notification.stack.domain.interactor.NotificationListInteractor;
import com.android.systemui.statusbar.notification.stack.ui.viewbinder.NotificationListViewBinder;
import com.android.systemui.statusbar.notification.stack.ui.viewmodel.NotificationListViewModel;
import com.android.systemui.statusbar.phone.HeadsUpAppearanceController;
-import com.android.systemui.statusbar.phone.HeadsUpManagerPhone;
import com.android.systemui.statusbar.phone.HeadsUpTouchHelper;
import com.android.systemui.statusbar.phone.KeyguardBypassController;
import com.android.systemui.statusbar.phone.NotificationIconAreaController;
@@ -127,6 +126,7 @@
import com.android.systemui.statusbar.policy.ConfigurationController.ConfigurationListener;
import com.android.systemui.statusbar.policy.DeviceProvisionedController;
import com.android.systemui.statusbar.policy.DeviceProvisionedController.DeviceProvisionedListener;
+import com.android.systemui.statusbar.policy.HeadsUpManager;
import com.android.systemui.statusbar.policy.OnHeadsUpChangedListener;
import com.android.systemui.statusbar.policy.SplitShadeStateController;
import com.android.systemui.statusbar.policy.ZenModeController;
@@ -156,7 +156,7 @@
private final NotificationGutsManager mNotificationGutsManager;
private final NotificationsController mNotificationsController;
private final NotificationVisibilityProvider mVisibilityProvider;
- private final HeadsUpManagerPhone mHeadsUpManager;
+ private final HeadsUpManager mHeadsUpManager;
private final NotificationRoundnessManager mNotificationRoundnessManager;
private final TunerService mTunerService;
private final DeviceProvisionedController mDeviceProvisionedController;
@@ -194,7 +194,7 @@
private final GroupExpansionManager mGroupExpansionManager;
private final NotifPipelineFlags mNotifPipelineFlags;
- private final SeenNotificationsProvider mSeenNotificationsProvider;
+ private final NotificationListInteractor mNotificationListInteractor;
private final KeyguardTransitionRepository mKeyguardTransitionRepo;
private NotificationStackScrollLayout mView;
@@ -631,7 +631,7 @@
NotificationGutsManager notificationGutsManager,
NotificationsController notificationsController,
NotificationVisibilityProvider visibilityProvider,
- HeadsUpManagerPhone headsUpManager,
+ HeadsUpManager headsUpManager,
NotificationRoundnessManager notificationRoundnessManager,
TunerService tunerService,
DeviceProvisionedController deviceProvisionedController,
@@ -662,7 +662,7 @@
UiEventLogger uiEventLogger,
NotificationRemoteInputManager remoteInputManager,
VisibilityLocationProviderDelegator visibilityLocationProviderDelegator,
- SeenNotificationsProvider seenNotificationsProvider,
+ NotificationListInteractor notificationListInteractor,
ShadeController shadeController,
InteractionJankMonitor jankMonitor,
StackStateLogger stackLogger,
@@ -715,7 +715,7 @@
mUiEventLogger = uiEventLogger;
mRemoteInputManager = remoteInputManager;
mVisibilityLocationProviderDelegator = visibilityLocationProviderDelegator;
- mSeenNotificationsProvider = seenNotificationsProvider;
+ mNotificationListInteractor = notificationListInteractor;
mShadeController = shadeController;
mNotifIconAreaController = notifIconAreaController;
mFeatureFlags = featureFlags;
@@ -2006,7 +2006,7 @@
public void setNotifStats(@NonNull NotifStats notifStats) {
mNotifStats = notifStats;
mView.setHasFilteredOutSeenNotifications(
- mSeenNotificationsProvider.getHasFilteredOutSeenNotifications());
+ mNotificationListInteractor.getHasFilteredOutSeenNotifications().getValue());
updateFooter();
updateShowEmptyShadeView();
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/data/repository/NotificationListRepository.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/data/repository/NotificationListRepository.kt
new file mode 100644
index 0000000..f6ed8c8
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/data/repository/NotificationListRepository.kt
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.statusbar.notification.stack.data.repository
+
+import com.android.systemui.dagger.SysUISingleton
+import javax.inject.Inject
+import kotlinx.coroutines.flow.MutableStateFlow
+import kotlinx.coroutines.flow.StateFlow
+import kotlinx.coroutines.flow.asStateFlow
+
+/** Repository for information about the current notification list. */
+@SysUISingleton
+class NotificationListRepository @Inject constructor() {
+ private val _hasFilteredOutSeenNotifications = MutableStateFlow(false)
+ val hasFilteredOutSeenNotifications: StateFlow<Boolean> =
+ _hasFilteredOutSeenNotifications.asStateFlow()
+
+ fun setHasFilteredOutSeenNotifications(value: Boolean) {
+ _hasFilteredOutSeenNotifications.value = value
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/domain/interactor/NotificationListInteractor.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/domain/interactor/NotificationListInteractor.kt
new file mode 100644
index 0000000..3fd68a8
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/domain/interactor/NotificationListInteractor.kt
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.statusbar.notification.stack.domain.interactor
+
+import com.android.systemui.dagger.SysUISingleton
+import com.android.systemui.statusbar.notification.stack.data.repository.NotificationListRepository
+import javax.inject.Inject
+import kotlinx.coroutines.flow.StateFlow
+
+/** Interactor for business logic associated with the notification stack. */
+@SysUISingleton
+class NotificationListInteractor
+@Inject
+constructor(
+ private val notificationListRepository: NotificationListRepository,
+) {
+ /** Are any already-seen notifications currently filtered out of the shade? */
+ val hasFilteredOutSeenNotifications: StateFlow<Boolean>
+ get() = notificationListRepository.hasFilteredOutSeenNotifications
+
+ fun setHasFilteredOutSeenNotifications(value: Boolean) {
+ notificationListRepository.setHasFilteredOutSeenNotifications(value)
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfacesImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfacesImpl.java
index 3e2f10d..6e6318e 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfacesImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfacesImpl.java
@@ -220,6 +220,7 @@
import com.android.systemui.statusbar.policy.DeviceProvisionedController;
import com.android.systemui.statusbar.policy.DeviceProvisionedController.DeviceProvisionedListener;
import com.android.systemui.statusbar.policy.ExtensionController;
+import com.android.systemui.statusbar.policy.HeadsUpManager;
import com.android.systemui.statusbar.policy.KeyguardStateController;
import com.android.systemui.statusbar.policy.UserInfoControllerImpl;
import com.android.systemui.statusbar.policy.UserSwitcherController;
@@ -236,6 +237,8 @@
import com.android.wm.shell.startingsurface.SplashscreenContentDrawer;
import com.android.wm.shell.startingsurface.StartingSurface;
+import dagger.Lazy;
+
import java.io.PrintWriter;
import java.io.StringWriter;
import java.util.List;
@@ -247,8 +250,6 @@
import javax.inject.Named;
import javax.inject.Provider;
-import dagger.Lazy;
-
/**
* A class handling initialization and coordination between some of the key central surfaces in
* System UI: The notification shade, the keyguard (lockscreen), and the status bar.
@@ -417,7 +418,7 @@
private final NotificationWakeUpCoordinator mWakeUpCoordinator;
private final KeyguardBypassController mKeyguardBypassController;
private final KeyguardStateController mKeyguardStateController;
- private final HeadsUpManagerPhone mHeadsUpManager;
+ private final HeadsUpManager mHeadsUpManager;
private final StatusBarTouchableRegionManager mStatusBarTouchableRegionManager;
private final FalsingCollector mFalsingCollector;
private final FalsingManager mFalsingManager;
@@ -611,7 +612,7 @@
NotificationWakeUpCoordinator notificationWakeUpCoordinator,
KeyguardBypassController keyguardBypassController,
KeyguardStateController keyguardStateController,
- HeadsUpManagerPhone headsUpManagerPhone,
+ HeadsUpManager headsUpManager,
DynamicPrivacyController dynamicPrivacyController,
FalsingManager falsingManager,
FalsingCollector falsingCollector,
@@ -718,7 +719,7 @@
mWakeUpCoordinator = notificationWakeUpCoordinator;
mKeyguardBypassController = keyguardBypassController;
mKeyguardStateController = keyguardStateController;
- mHeadsUpManager = headsUpManagerPhone;
+ mHeadsUpManager = headsUpManager;
mBackActionInteractor = backActionInteractor;
mKeyguardIndicationController = keyguardIndicationController;
mStatusBarTouchableRegionManager = statusBarTouchableRegionManager;
@@ -1088,11 +1089,6 @@
void initShadeVisibilityListener() {
mShadeController.setVisibilityListener(new ShadeController.ShadeVisibilityListener() {
@Override
- public void visibilityChanged(boolean visible) {
- onShadeVisibilityChanged(visible);
- }
-
- @Override
public void expandedVisibleChanged(boolean expandedVisible) {
if (expandedVisible) {
setInteracting(StatusBarManager.WINDOW_STATUS_BAR, true);
@@ -1195,7 +1191,7 @@
});
mStatusBarInitializer.initializeStatusBar();
- mStatusBarTouchableRegionManager.setup(this, getNotificationShadeWindowView());
+ mStatusBarTouchableRegionManager.setup(getNotificationShadeWindowView());
createNavigationBar(result);
@@ -2688,7 +2684,9 @@
!mDozeServiceHost.isPulsing(), mDeviceProvisionedController.isFrpActive());
mShadeSurface.setTouchAndAnimationDisabled(disabled);
- mNotificationIconAreaController.setAnimationsEnabled(!disabled);
+ if (!mFeatureFlags.isEnabled(Flags.NOTIFICATION_ICON_CONTAINER_REFACTOR)) {
+ mNotificationIconAreaController.setAnimationsEnabled(!disabled);
+ }
}
final ScreenLifecycle.Observer mScreenObserver = new ScreenLifecycle.Observer() {
@@ -2844,13 +2842,16 @@
mScrimController.setExpansionAffectsAlpha(!unlocking);
if (mAlternateBouncerInteractor.isVisibleState()) {
- if ((!mKeyguardStateController.isOccluded() || mShadeSurface.isPanelExpanded())
- && (mState == StatusBarState.SHADE || mState == StatusBarState.SHADE_LOCKED
- || mTransitionToFullShadeProgress > 0f)) {
- mScrimController.transitionTo(ScrimState.AUTH_SCRIMMED_SHADE);
- } else {
- mScrimController.transitionTo(ScrimState.AUTH_SCRIMMED);
+ if (!mFeatureFlags.isEnabled(Flags.ALTERNATE_BOUNCER_VIEW)) {
+ if ((!mKeyguardStateController.isOccluded() || mShadeSurface.isPanelExpanded())
+ && (mState == StatusBarState.SHADE || mState == StatusBarState.SHADE_LOCKED
+ || mTransitionToFullShadeProgress > 0f)) {
+ mScrimController.transitionTo(ScrimState.AUTH_SCRIMMED_SHADE);
+ } else {
+ mScrimController.transitionTo(ScrimState.AUTH_SCRIMMED);
+ }
}
+
// This will cancel the keyguardFadingAway animation if it is running. We need to do
// this as otherwise it can remain pending and leave keyguard in a weird state.
mUnlockScrimCallback.onCancelled();
@@ -2913,8 +2914,6 @@
protected boolean mDeviceInteractive;
- protected boolean mVisible;
-
protected DevicePolicyManager mDevicePolicyManager;
private final PowerManager mPowerManager;
protected StatusBarKeyguardViewManager mStatusBarKeyguardViewManager;
@@ -3032,16 +3031,6 @@
afterKeyguardGone);
}
- private void onShadeVisibilityChanged(boolean visible) {
- if (mVisible != visible) {
- mVisible = visible;
- if (visible) {
- DejankUtils.notifyRendererOfExpensiveFrame(
- getNotificationShadeWindowView(), "onShadeVisibilityChanged");
- }
- }
- }
-
private void clearNotificationEffects() {
try {
mBarService.clearNotificationEffects();
@@ -3163,7 +3152,6 @@
// TODO: Bring these out of CentralSurfaces.
mUserInfoControllerImpl.onDensityOrFontScaleChanged();
mNotificationIconAreaController.onDensityOrFontScaleChanged(mContext);
- mHeadsUpManager.onDensityOrFontScaleChanged();
}
@Override
@@ -3200,7 +3188,8 @@
// down on the lockscreen), clear notification LED, vibration,
// ringing.
// Other transitions are covered in WindowRootViewVisibilityInteractor.
- if (mVisible && (newState == StatusBarState.SHADE_LOCKED
+ if (mWindowRootViewVisibilityInteractor.isLockscreenOrShadeVisible().getValue()
+ && (newState == StatusBarState.SHADE_LOCKED
|| mStatusBarStateController.goingToFullShade())) {
clearNotificationEffects();
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/DozeServiceHost.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/DozeServiceHost.java
index 4849f64..d3d11ea 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/DozeServiceHost.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/DozeServiceHost.java
@@ -49,6 +49,7 @@
import com.android.systemui.statusbar.notification.collection.NotificationEntry;
import com.android.systemui.statusbar.policy.BatteryController;
import com.android.systemui.statusbar.policy.DeviceProvisionedController;
+import com.android.systemui.statusbar.policy.HeadsUpManager;
import com.android.systemui.statusbar.policy.OnHeadsUpChangedListener;
import com.android.systemui.util.Assert;
@@ -80,7 +81,7 @@
private final WakefulnessLifecycle mWakefulnessLifecycle;
private final SysuiStatusBarStateController mStatusBarStateController;
private final DeviceProvisionedController mDeviceProvisionedController;
- private final HeadsUpManagerPhone mHeadsUpManagerPhone;
+ private final HeadsUpManager mHeadsUpManager;
private final BatteryController mBatteryController;
private final ScrimController mScrimController;
private final Lazy<BiometricUnlockController> mBiometricUnlockControllerLazy;
@@ -106,7 +107,7 @@
WakefulnessLifecycle wakefulnessLifecycle,
SysuiStatusBarStateController statusBarStateController,
DeviceProvisionedController deviceProvisionedController,
- HeadsUpManagerPhone headsUpManagerPhone, BatteryController batteryController,
+ HeadsUpManager headsUpManager, BatteryController batteryController,
ScrimController scrimController,
Lazy<BiometricUnlockController> biometricUnlockControllerLazy,
Lazy<AssistManager> assistManagerLazy,
@@ -123,7 +124,7 @@
mWakefulnessLifecycle = wakefulnessLifecycle;
mStatusBarStateController = statusBarStateController;
mDeviceProvisionedController = deviceProvisionedController;
- mHeadsUpManagerPhone = headsUpManagerPhone;
+ mHeadsUpManager = headsUpManager;
mBatteryController = batteryController;
mScrimController = scrimController;
mBiometricUnlockControllerLazy = biometricUnlockControllerLazy;
@@ -135,7 +136,7 @@
mNotificationWakeUpCoordinator = notificationWakeUpCoordinator;
mAuthController = authController;
mNotificationIconAreaController = notificationIconAreaController;
- mHeadsUpManagerPhone.addListener(mOnHeadsUpChangedListener);
+ mHeadsUpManager.addListener(mOnHeadsUpChangedListener);
mDozeInteractor = dozeInteractor;
}
@@ -337,8 +338,8 @@
if (reason == DozeLog.PULSE_REASON_SENSOR_WAKE_REACH) {
mScrimController.setWakeLockScreenSensorActive(true);
}
- if (mDozeScrimController.isPulsing() && mHeadsUpManagerPhone.hasNotifications()) {
- mHeadsUpManagerPhone.extendHeadsUp();
+ if (mDozeScrimController.isPulsing() && mHeadsUpManager.hasNotifications()) {
+ mHeadsUpManager.extendHeadsUp();
} else {
mDozeScrimController.extendPulse();
}
@@ -493,7 +494,7 @@
mDozeScrimController.cancelPendingPulseTimeout();
}
}
- if (!isHeadsUp && !mHeadsUpManagerPhone.hasNotifications()) {
+ if (!isHeadsUp && !mHeadsUpManager.hasNotifications()) {
// There are no longer any notifications to show. We should end the
// pulse now.
stopPulsing();
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/HeadsUpAppearanceController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/HeadsUpAppearanceController.java
index 270c40e..c493eeda 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/HeadsUpAppearanceController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/HeadsUpAppearanceController.java
@@ -26,9 +26,9 @@
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.widget.ViewClippingUtil;
-import com.android.systemui.res.R;
import com.android.systemui.plugins.DarkIconDispatcher;
import com.android.systemui.plugins.statusbar.StatusBarStateController;
+import com.android.systemui.res.R;
import com.android.systemui.shade.ShadeHeadsUpTracker;
import com.android.systemui.shade.ShadeViewController;
import com.android.systemui.statusbar.CommandQueue;
@@ -43,6 +43,7 @@
import com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayoutController;
import com.android.systemui.statusbar.phone.fragment.dagger.StatusBarFragmentScope;
import com.android.systemui.statusbar.policy.Clock;
+import com.android.systemui.statusbar.policy.HeadsUpManager;
import com.android.systemui.statusbar.policy.KeyguardStateController;
import com.android.systemui.statusbar.policy.OnHeadsUpChangedListener;
import com.android.systemui.util.ViewController;
@@ -70,7 +71,7 @@
private static final SourceType HEADS_UP = SourceType.from("HeadsUp");
private static final SourceType PULSING = SourceType.from("Pulsing");
private final NotificationIconAreaController mNotificationIconAreaController;
- private final HeadsUpManagerPhone mHeadsUpManager;
+ private final HeadsUpManager mHeadsUpManager;
private final NotificationStackScrollLayoutController mStackScrollerController;
private final DarkIconDispatcher mDarkIconDispatcher;
@@ -108,7 +109,7 @@
@Inject
public HeadsUpAppearanceController(
NotificationIconAreaController notificationIconAreaController,
- HeadsUpManagerPhone headsUpManager,
+ HeadsUpManager headsUpManager,
StatusBarStateController stateController,
PhoneStatusBarTransitions phoneStatusBarTransitions,
KeyguardBypassController bypassController,
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/HeadsUpManagerPhone.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/HeadsUpManagerPhone.java
index a5ea142..6b4382f73 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/HeadsUpManagerPhone.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/HeadsUpManagerPhone.java
@@ -29,11 +29,11 @@
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.logging.UiEventLogger;
import com.android.internal.policy.SystemBarUtils;
-import com.android.systemui.Dumpable;
-import com.android.systemui.res.R;
+import com.android.systemui.dagger.SysUISingleton;
import com.android.systemui.dagger.qualifiers.Main;
import com.android.systemui.plugins.statusbar.StatusBarStateController;
import com.android.systemui.plugins.statusbar.StatusBarStateController.StateListener;
+import com.android.systemui.res.R;
import com.android.systemui.shade.ShadeExpansionStateManager;
import com.android.systemui.statusbar.StatusBarState;
import com.android.systemui.statusbar.notification.collection.NotificationEntry;
@@ -42,10 +42,12 @@
import com.android.systemui.statusbar.notification.collection.render.GroupMembershipManager;
import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
import com.android.systemui.statusbar.policy.AccessibilityManagerWrapper;
+import com.android.systemui.statusbar.policy.AnimationStateHandler;
+import com.android.systemui.statusbar.policy.BaseHeadsUpManager;
import com.android.systemui.statusbar.policy.ConfigurationController;
-import com.android.systemui.statusbar.policy.HeadsUpManager;
import com.android.systemui.statusbar.policy.HeadsUpManagerLogger;
import com.android.systemui.statusbar.policy.OnHeadsUpChangedListener;
+import com.android.systemui.statusbar.policy.OnHeadsUpPhoneListenerChange;
import java.io.PrintWriter;
import java.util.ArrayList;
@@ -53,11 +55,11 @@
import java.util.List;
import java.util.Stack;
-/**
- * A implementation of HeadsUpManager for phone and car.
- */
-public class HeadsUpManagerPhone extends HeadsUpManager implements Dumpable,
- OnHeadsUpChangedListener {
+import javax.inject.Inject;
+
+/** A implementation of HeadsUpManager for phone. */
+@SysUISingleton
+public class HeadsUpManagerPhone extends BaseHeadsUpManager implements OnHeadsUpChangedListener {
private static final String TAG = "HeadsUpManagerPhone";
@VisibleForTesting
@@ -102,7 +104,7 @@
///////////////////////////////////////////////////////////////////////////////////////////////
// Constructor:
-
+ @Inject
public HeadsUpManagerPhone(@NonNull final Context context,
HeadsUpManagerLogger logger,
StatusBarStateController statusBarStateController,
@@ -154,7 +156,8 @@
/**
* Add a listener to receive callbacks onHeadsUpGoingAway
*/
- void addHeadsUpPhoneListener(OnHeadsUpPhoneListenerChange listener) {
+ @Override
+ public void addHeadsUpPhoneListener(OnHeadsUpPhoneListenerChange listener) {
mHeadsUpPhoneListeners.add(listener);
}
@@ -162,7 +165,8 @@
* Gets the touchable region needed for heads up notifications. Returns null if no touchable
* region is required (ie: no heads up notification currently exists).
*/
- @Nullable Region getTouchableRegion() {
+ @Override
+ public @Nullable Region getTouchableRegion() {
NotificationEntry topEntry = getTopEntry();
// This call could be made in an inconsistent state while the pinnedMode hasn't been
@@ -197,8 +201,9 @@
* @param key the key of the touched notification
* @return whether the touch is invalid and should be discarded
*/
- boolean shouldSwallowClick(@NonNull String key) {
- HeadsUpManager.HeadsUpEntry entry = getHeadsUpEntry(key);
+ @Override
+ public boolean shouldSwallowClick(@NonNull String key) {
+ BaseHeadsUpManager.HeadsUpEntry entry = getHeadsUpEntry(key);
return entry != null && mClock.currentTimeMillis() < entry.mPostTime;
}
@@ -238,7 +243,8 @@
* Set that we are exiting the headsUp pinned mode, but some notifications might still be
* animating out. This is used to keep the touchable regions in a reasonable state.
*/
- void setHeadsUpGoingAway(boolean headsUpGoingAway) {
+ @Override
+ public void setHeadsUpGoingAway(boolean headsUpGoingAway) {
if (headsUpGoingAway != mHeadsUpGoingAway) {
mHeadsUpGoingAway = headsUpGoingAway;
for (OnHeadsUpPhoneListenerChange listener : mHeadsUpPhoneListeners) {
@@ -247,7 +253,8 @@
}
}
- boolean isHeadsUpGoingAway() {
+ @Override
+ public boolean isHeadsUpGoingAway() {
return mHeadsUpGoingAway;
}
@@ -260,8 +267,8 @@
public void setRemoteInputActive(
@NonNull NotificationEntry entry, boolean remoteInputActive) {
HeadsUpEntryPhone headsUpEntry = getHeadsUpEntryPhone(entry.getKey());
- if (headsUpEntry != null && headsUpEntry.remoteInputActive != remoteInputActive) {
- headsUpEntry.remoteInputActive = remoteInputActive;
+ if (headsUpEntry != null && headsUpEntry.mRemoteInputActive != remoteInputActive) {
+ headsUpEntry.mRemoteInputActive = remoteInputActive;
if (remoteInputActive) {
headsUpEntry.removeAutoRemovalCallbacks("setRemoteInputActive(true)");
} else {
@@ -313,6 +320,7 @@
mSwipedOutKeys.add(key);
}
+ @Override
public boolean removeNotification(@NonNull String key, boolean releaseImmediately,
boolean animate) {
if (animate) {
@@ -411,7 +419,7 @@
///////////////////////////////////////////////////////////////////////////////////////////////
// HeadsUpEntryPhone:
- protected class HeadsUpEntryPhone extends HeadsUpManager.HeadsUpEntry {
+ protected class HeadsUpEntryPhone extends BaseHeadsUpManager.HeadsUpEntry {
private boolean mGutsShownPinned;
@@ -459,11 +467,11 @@
@Override
public void setExpanded(boolean expanded) {
- if (this.expanded == expanded) {
+ if (this.mExpanded == expanded) {
return;
}
- this.expanded = expanded;
+ this.mExpanded = expanded;
if (expanded) {
removeAutoRemovalCallbacks("setExpanded(true)");
} else {
@@ -504,21 +512,6 @@
}
}
- public interface AnimationStateHandler {
- void setHeadsUpGoingAwayAnimationsAllowed(boolean allowed);
- }
-
- /**
- * Listener to register for HeadsUpNotification Phone changes.
- */
- public interface OnHeadsUpPhoneListenerChange {
- /**
- * Called when a heads up notification is 'going away' or no longer 'going away'.
- * See {@link HeadsUpManagerPhone#setHeadsUpGoingAway}.
- */
- void onHeadsUpGoingAwayStateChanged(boolean headsUpGoingAway);
- }
-
private final StateListener mStatusBarStateListener = new StateListener() {
@Override
public void onStateChanged(int newState) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/HeadsUpModule.kt b/packages/SystemUI/src/com/android/systemui/statusbar/phone/HeadsUpModule.kt
new file mode 100644
index 0000000..0d0f2cd
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/HeadsUpModule.kt
@@ -0,0 +1,11 @@
+package com.android.systemui.statusbar.phone
+
+import com.android.systemui.dagger.SysUISingleton
+import com.android.systemui.statusbar.policy.HeadsUpManager
+import dagger.Binds
+import dagger.Module
+
+@Module
+interface HeadsUpModule {
+ @Binds @SysUISingleton fun bindsHeadsUpManager(hum: HeadsUpManagerPhone): HeadsUpManager
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/HeadsUpTouchHelper.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/HeadsUpTouchHelper.java
index dcbaac2..198272e 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/HeadsUpTouchHelper.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/HeadsUpTouchHelper.java
@@ -26,13 +26,14 @@
import com.android.systemui.statusbar.notification.collection.NotificationEntry;
import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
import com.android.systemui.statusbar.notification.row.ExpandableView;
+import com.android.systemui.statusbar.policy.HeadsUpManager;
/**
* A helper class to handle touches on the heads-up views.
*/
public class HeadsUpTouchHelper implements Gefingerpoken {
- private final HeadsUpManagerPhone mHeadsUpManager;
+ private final HeadsUpManager mHeadsUpManager;
private final IStatusBarService mStatusBarService;
private final Callback mCallback;
private int mTrackingPointer;
@@ -45,7 +46,7 @@
private final HeadsUpNotificationViewController mPanel;
private ExpandableNotificationRow mPickedChild;
- public HeadsUpTouchHelper(HeadsUpManagerPhone headsUpManager,
+ public HeadsUpTouchHelper(HeadsUpManager headsUpManager,
IStatusBarService statusBarService,
Callback callback,
HeadsUpNotificationViewController notificationPanelView) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarHeadsUpChangeListener.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarHeadsUpChangeListener.java
index 4b39854..235ed25 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarHeadsUpChangeListener.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarHeadsUpChangeListener.java
@@ -24,6 +24,7 @@
import com.android.systemui.statusbar.NotificationShadeWindowController;
import com.android.systemui.statusbar.StatusBarState;
import com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayoutController;
+import com.android.systemui.statusbar.policy.HeadsUpManager;
import com.android.systemui.statusbar.policy.OnHeadsUpChangedListener;
import com.android.systemui.statusbar.window.StatusBarWindowController;
@@ -39,7 +40,7 @@
private final ShadeViewController mShadeViewController;
private final NotificationStackScrollLayoutController mNsslController;
private final KeyguardBypassController mKeyguardBypassController;
- private final HeadsUpManagerPhone mHeadsUpManager;
+ private final HeadsUpManager mHeadsUpManager;
private final StatusBarStateController mStatusBarStateController;
private final NotificationRemoteInputManager mNotificationRemoteInputManager;
@@ -50,7 +51,7 @@
ShadeViewController shadeViewController,
NotificationStackScrollLayoutController nsslController,
KeyguardBypassController keyguardBypassController,
- HeadsUpManagerPhone headsUpManager,
+ HeadsUpManager headsUpManager,
StatusBarStateController statusBarStateController,
NotificationRemoteInputManager notificationRemoteInputManager) {
mNotificationShadeWindowController = notificationShadeWindowController;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java
index eedf35f..62b2445 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java
@@ -1573,6 +1573,9 @@
* notification shade's child views.
*/
public boolean shouldInterceptTouchEvent(MotionEvent event) {
+ if (mFlags.isEnabled(Flags.ALTERNATE_BOUNCER_VIEW)) {
+ return false;
+ }
return mAlternateBouncerInteractor.isVisibleState();
}
@@ -1581,6 +1584,10 @@
* showing.
*/
public boolean onTouch(MotionEvent event) {
+ if (mFlags.isEnabled(Flags.ALTERNATE_BOUNCER_VIEW)) {
+ return false;
+ }
+
boolean handleTouch = shouldInterceptTouchEvent(event);
if (handleTouch) {
final boolean actionDown = event.getActionMasked() == MotionEvent.ACTION_DOWN;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarNotificationActivityStarter.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarNotificationActivityStarter.java
index dc4c709..dbee080 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarNotificationActivityStarter.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarNotificationActivityStarter.java
@@ -76,6 +76,7 @@
import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
import com.android.systemui.statusbar.notification.row.ExpandableNotificationRowDragController;
import com.android.systemui.statusbar.notification.row.OnUserInteractionCallback;
+import com.android.systemui.statusbar.policy.HeadsUpManager;
import com.android.systemui.statusbar.policy.HeadsUpUtil;
import com.android.systemui.statusbar.policy.KeyguardStateController;
import com.android.systemui.wmshell.BubblesManager;
@@ -102,7 +103,7 @@
private final Executor mUiBgExecutor;
private final NotificationVisibilityProvider mVisibilityProvider;
- private final HeadsUpManagerPhone mHeadsUpManager;
+ private final HeadsUpManager mHeadsUpManager;
private final ActivityStarter mActivityStarter;
private final NotificationClickNotifier mClickNotifier;
private final StatusBarKeyguardViewManager mStatusBarKeyguardViewManager;
@@ -141,7 +142,7 @@
Handler mainThreadHandler,
Executor uiBgExecutor,
NotificationVisibilityProvider visibilityProvider,
- HeadsUpManagerPhone headsUpManager,
+ HeadsUpManager headsUpManager,
ActivityStarter activityStarter,
NotificationClickNotifier clickNotifier,
StatusBarKeyguardViewManager statusBarKeyguardViewManager,
@@ -213,7 +214,9 @@
*/
@Override
public void onNotificationClicked(NotificationEntry entry, ExpandableNotificationRow row) {
- mLogger.logStartingActivityFromClick(entry);
+ mLogger.logStartingActivityFromClick(entry, row.isHeadsUpState(),
+ mKeyguardStateController.isVisible(),
+ mNotificationShadeWindowController.getPanelExpanded());
if (mRemoteInputManager.isRemoteInputActive(entry)) {
// We have an active remote input typed and the user clicked on the notification.
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarNotificationActivityStarterLogger.kt b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarNotificationActivityStarterLogger.kt
index 2d30a12..4211cab 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarNotificationActivityStarterLogger.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarNotificationActivityStarterLogger.kt
@@ -30,11 +30,16 @@
class StatusBarNotificationActivityStarterLogger @Inject constructor(
@NotifInteractionLog private val buffer: LogBuffer
) {
- fun logStartingActivityFromClick(entry: NotificationEntry) {
+ fun logStartingActivityFromClick(entry: NotificationEntry, isHeadsUpState: Boolean,
+ isKeyguardVisible: Boolean, isPanelExpanded: Boolean) {
buffer.log(TAG, DEBUG, {
str1 = entry.logKey
+ bool1 = isHeadsUpState
+ bool2 = isKeyguardVisible
+ bool3 = isPanelExpanded
}, {
- "(1/5) onNotificationClicked: $str1"
+ "(1/5) onNotificationClicked: $str1 isHeadsUpState: $bool1 " +
+ "isKeyguardVisible: $bool2 isPanelExpanded: $bool3"
})
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarNotificationPresenter.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarNotificationPresenter.java
index fb7f9d1..2d14f6b 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarNotificationPresenter.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarNotificationPresenter.java
@@ -31,11 +31,11 @@
import com.android.internal.statusbar.IStatusBarService;
import com.android.systemui.InitController;
-import com.android.systemui.res.R;
import com.android.systemui.dagger.SysUISingleton;
import com.android.systemui.plugins.ActivityStarter;
import com.android.systemui.plugins.ActivityStarter.OnDismissAction;
import com.android.systemui.power.domain.interactor.PowerInteractor;
+import com.android.systemui.res.R;
import com.android.systemui.shade.NotificationShadeWindowView;
import com.android.systemui.shade.QuickSettingsController;
import com.android.systemui.shade.ShadeViewController;
@@ -60,6 +60,7 @@
import com.android.systemui.statusbar.notification.row.NotificationGutsManager.OnSettingsClickListener;
import com.android.systemui.statusbar.notification.stack.NotificationListContainer;
import com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayoutController;
+import com.android.systemui.statusbar.policy.HeadsUpManager;
import com.android.systemui.statusbar.policy.KeyguardStateController;
import javax.inject.Inject;
@@ -76,7 +77,7 @@
private final NotificationMediaManager mMediaManager;
private final NotificationGutsManager mGutsManager;
private final ShadeViewController mNotificationPanel;
- private final HeadsUpManagerPhone mHeadsUpManager;
+ private final HeadsUpManager mHeadsUpManager;
private final AboveShelfObserver mAboveShelfObserver;
private final DozeScrimController mDozeScrimController;
private final NotificationsInteractor mNotificationsInteractor;
@@ -98,7 +99,7 @@
Context context,
ShadeViewController panel,
QuickSettingsController quickSettingsController,
- HeadsUpManagerPhone headsUp,
+ HeadsUpManager headsUp,
NotificationShadeWindowView statusBarWindow,
ActivityStarter activityStarter,
NotificationStackScrollLayoutController stackScrollerController,
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarTouchableRegionManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarTouchableRegionManager.java
index 40bd8d3..ba73c10 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarTouchableRegionManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarTouchableRegionManager.java
@@ -31,15 +31,18 @@
import com.android.internal.policy.SystemBarUtils;
import com.android.systemui.Dumpable;
-import com.android.systemui.res.R;
import com.android.systemui.ScreenDecorations;
+import com.android.systemui.bouncer.domain.interactor.AlternateBouncerInteractor;
+import com.android.systemui.bouncer.domain.interactor.PrimaryBouncerInteractor;
import com.android.systemui.dagger.SysUISingleton;
+import com.android.systemui.res.R;
import com.android.systemui.scene.domain.interactor.SceneInteractor;
import com.android.systemui.scene.shared.flag.SceneContainerFlags;
import com.android.systemui.shade.ShadeExpansionStateManager;
import com.android.systemui.statusbar.NotificationShadeWindowController;
import com.android.systemui.statusbar.policy.ConfigurationController;
import com.android.systemui.statusbar.policy.ConfigurationController.ConfigurationListener;
+import com.android.systemui.statusbar.policy.HeadsUpManager;
import com.android.systemui.statusbar.policy.OnHeadsUpChangedListener;
import com.android.systemui.util.kotlin.JavaAdapter;
@@ -58,13 +61,12 @@
private static final String TAG = "TouchableRegionManager";
private final Context mContext;
- private final HeadsUpManagerPhone mHeadsUpManager;
+ private final HeadsUpManager mHeadsUpManager;
private final NotificationShadeWindowController mNotificationShadeWindowController;
private final UnlockedScreenOffAnimationController mUnlockedScreenOffAnimationController;
private boolean mIsStatusBarExpanded = false;
private boolean mShouldAdjustInsets = false;
- private CentralSurfaces mCentralSurfaces;
private View mNotificationShadeWindowView;
private View mNotificationPanelView;
private boolean mForceCollapsedUntilLayout = false;
@@ -72,6 +74,8 @@
private Region mTouchableRegion = new Region();
private int mDisplayCutoutTouchableRegionSize;
private int mStatusBarHeight;
+ private final PrimaryBouncerInteractor mPrimaryBouncerInteractor;
+ private final AlternateBouncerInteractor mAlternateBouncerInteractor;
private final OnComputeInternalInsetsListener mOnComputeInternalInsetsListener;
@@ -80,12 +84,14 @@
Context context,
NotificationShadeWindowController notificationShadeWindowController,
ConfigurationController configurationController,
- HeadsUpManagerPhone headsUpManager,
+ HeadsUpManager headsUpManager,
ShadeExpansionStateManager shadeExpansionStateManager,
Provider<SceneInteractor> sceneInteractor,
Provider<JavaAdapter> javaAdapter,
SceneContainerFlags sceneContainerFlags,
- UnlockedScreenOffAnimationController unlockedScreenOffAnimationController
+ UnlockedScreenOffAnimationController unlockedScreenOffAnimationController,
+ PrimaryBouncerInteractor primaryBouncerInteractor,
+ AlternateBouncerInteractor alternateBouncerInteractor
) {
mContext = context;
initResources();
@@ -128,13 +134,12 @@
this::onShadeExpansionFullyChanged);
}
+ mPrimaryBouncerInteractor = primaryBouncerInteractor;
+ mAlternateBouncerInteractor = alternateBouncerInteractor;
mOnComputeInternalInsetsListener = this::onComputeInternalInsets;
}
- protected void setup(
- @NonNull CentralSurfaces centralSurfaces,
- @NonNull View notificationShadeWindowView) {
- mCentralSurfaces = centralSurfaces;
+ protected void setup(@NonNull View notificationShadeWindowView) {
mNotificationShadeWindowView = notificationShadeWindowView;
mNotificationPanelView = mNotificationShadeWindowView.findViewById(R.id.notification_panel);
}
@@ -260,7 +265,8 @@
// since we don't want stray touches to go through the light reveal scrim to whatever is
// underneath.
return mIsStatusBarExpanded
- || mCentralSurfaces.isBouncerShowing()
+ || mPrimaryBouncerInteractor.isShowing().getValue()
+ || mAlternateBouncerInteractor.isVisibleState()
|| mUnlockedScreenOffAnimationController.isAnimationPlaying();
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/fragment/CollapsedStatusBarFragment.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/fragment/CollapsedStatusBarFragment.java
index babd435..63c022c 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/fragment/CollapsedStatusBarFragment.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/fragment/CollapsedStatusBarFragment.java
@@ -38,11 +38,11 @@
import com.android.app.animation.InterpolatorsAndroidX;
import com.android.keyguard.KeyguardUpdateMonitor;
import com.android.systemui.Dumpable;
-import com.android.systemui.res.R;
import com.android.systemui.dagger.qualifiers.Main;
import com.android.systemui.dump.DumpManager;
import com.android.systemui.flags.FeatureFlags;
import com.android.systemui.plugins.statusbar.StatusBarStateController;
+import com.android.systemui.res.R;
import com.android.systemui.shade.ShadeExpansionStateManager;
import com.android.systemui.shade.ShadeViewController;
import com.android.systemui.statusbar.CommandQueue;
@@ -74,8 +74,6 @@
import com.android.systemui.util.CarrierConfigTracker.DefaultDataSubscriptionChangedListener;
import com.android.systemui.util.settings.SecureSettings;
-import kotlin.Unit;
-
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.Arrays;
@@ -85,6 +83,7 @@
import java.util.concurrent.Executor;
import javax.inject.Inject;
+import kotlin.Unit;
/**
* Contains the collapsed status bar and handles hiding/showing based on disable flags
@@ -279,7 +278,8 @@
public void onViewCreated(View view, @Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
mDumpManager.registerDumpable(getClass().getSimpleName(), this);
- mStatusBarFragmentComponent = mStatusBarFragmentComponentFactory.create(this);
+ mStatusBarFragmentComponent = mStatusBarFragmentComponentFactory.create(
+ (PhoneStatusBarView) getView());
mStatusBarFragmentComponent.init();
mStartableStates.clear();
for (Startable startable : mStatusBarFragmentComponent.getStartables()) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/fragment/dagger/StatusBarFragmentComponent.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/fragment/dagger/StatusBarFragmentComponent.java
index d9a5844..0618abb 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/fragment/dagger/StatusBarFragmentComponent.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/fragment/dagger/StatusBarFragmentComponent.java
@@ -27,11 +27,11 @@
import com.android.systemui.statusbar.phone.StatusBarDemoMode;
import com.android.systemui.statusbar.phone.fragment.CollapsedStatusBarFragment;
-import java.util.Set;
-
import dagger.BindsInstance;
import dagger.Subcomponent;
+import java.util.Set;
+
/**
* A subcomponent that gets re-created each time we create a new {@link CollapsedStatusBarFragment}.
*
@@ -54,7 +54,7 @@
@Subcomponent.Factory
interface Factory {
StatusBarFragmentComponent create(
- @BindsInstance CollapsedStatusBarFragment collapsedStatusBarFragment);
+ @BindsInstance @RootView PhoneStatusBarView phoneStatusBarView);
}
/**
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/fragment/dagger/StatusBarFragmentModule.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/fragment/dagger/StatusBarFragmentModule.java
index 6ef877b..3741f14 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/fragment/dagger/StatusBarFragmentModule.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/fragment/dagger/StatusBarFragmentModule.java
@@ -19,15 +19,14 @@
import android.view.View;
import android.view.ViewStub;
-import com.android.systemui.res.R;
import com.android.systemui.battery.BatteryMeterView;
import com.android.systemui.dagger.qualifiers.RootView;
+import com.android.systemui.res.R;
import com.android.systemui.statusbar.HeadsUpStatusBarView;
import com.android.systemui.statusbar.phone.PhoneStatusBarTransitions;
import com.android.systemui.statusbar.phone.PhoneStatusBarView;
import com.android.systemui.statusbar.phone.PhoneStatusBarViewController;
import com.android.systemui.statusbar.phone.StatusBarLocation;
-import com.android.systemui.statusbar.phone.fragment.CollapsedStatusBarFragment;
import com.android.systemui.statusbar.phone.userswitcher.StatusBarUserSwitcherContainer;
import com.android.systemui.statusbar.policy.Clock;
import com.android.systemui.statusbar.window.StatusBarWindowController;
@@ -51,15 +50,6 @@
/** */
@Provides
- @RootView
- @StatusBarFragmentScope
- static PhoneStatusBarView providePhoneStatusBarView(
- CollapsedStatusBarFragment collapsedStatusBarFragment) {
- return (PhoneStatusBarView) collapsedStatusBarFragment.getView();
- }
-
- /** */
- @Provides
@StatusBarFragmentScope
static BatteryMeterView provideBatteryMeterView(@RootView PhoneStatusBarView view) {
return view.findViewById(R.id.battery);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/HeadsUpManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/BaseHeadsUpManager.java
similarity index 93%
rename from packages/SystemUI/src/com/android/systemui/statusbar/policy/HeadsUpManager.java
rename to packages/SystemUI/src/com/android/systemui/statusbar/policy/BaseHeadsUpManager.java
index e59ec04..cec76f3 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/HeadsUpManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/BaseHeadsUpManager.java
@@ -34,8 +34,8 @@
import com.android.internal.logging.UiEvent;
import com.android.internal.logging.UiEventLogger;
import com.android.systemui.EventLogTags;
-import com.android.systemui.res.R;
import com.android.systemui.dagger.qualifiers.Main;
+import com.android.systemui.res.R;
import com.android.systemui.statusbar.AlertingNotificationManager;
import com.android.systemui.statusbar.notification.collection.NotificationEntry;
import com.android.systemui.statusbar.notification.row.NotificationRowContentBinder.InflationFlag;
@@ -47,7 +47,8 @@
* A manager which handles heads up notifications which is a special mode where
* they simply peek from the top of the screen.
*/
-public abstract class HeadsUpManager extends AlertingNotificationManager {
+public abstract class BaseHeadsUpManager extends AlertingNotificationManager implements
+ HeadsUpManager {
private static final String TAG = "HeadsUpManager";
private static final String SETTING_HEADS_UP_SNOOZE_LENGTH_MS = "heads_up_snooze_length_ms";
@@ -81,7 +82,7 @@
}
}
- public HeadsUpManager(@NonNull final Context context,
+ public BaseHeadsUpManager(@NonNull final Context context,
HeadsUpManagerLogger logger,
@Main Handler handler,
AccessibilityManagerWrapper accessibilityManagerWrapper,
@@ -131,6 +132,7 @@
mListeners.remove(listener);
}
+ /** Updates the notification with the given key. */
public void updateNotification(@NonNull String key, boolean alert) {
super.updateNotification(key, alert);
HeadsUpEntry headsUpEntry = getHeadsUpEntry(key);
@@ -146,7 +148,7 @@
// the NotificationEntry into AlertingNotificationManager's mAlertEntries map.
return hasFullScreenIntent(entry);
}
- return hasFullScreenIntent(entry) && !headsUpEntry.wasUnpinned;
+ return hasFullScreenIntent(entry) && !headsUpEntry.mWasUnpinned;
}
protected boolean hasFullScreenIntent(@NonNull NotificationEntry entry) {
@@ -154,11 +156,11 @@
}
protected void setEntryPinned(
- @NonNull HeadsUpManager.HeadsUpEntry headsUpEntry, boolean isPinned) {
+ @NonNull BaseHeadsUpManager.HeadsUpEntry headsUpEntry, boolean isPinned) {
mLogger.logSetEntryPinned(headsUpEntry.mEntry, isPinned);
NotificationEntry entry = headsUpEntry.mEntry;
if (!isPinned) {
- headsUpEntry.wasUnpinned = true;
+ headsUpEntry.mWasUnpinned = true;
}
if (entry.isRowPinned() != isPinned) {
entry.setRowPinned(isPinned);
@@ -292,10 +294,12 @@
mUser = user;
}
+ /** Returns the ID of the current user. */
public int getUser() {
return mUser;
}
+ @Override
public void dump(@NonNull PrintWriter pw, @NonNull String[] args) {
pw.println("HeadsUpManager state:");
dumpInternal(pw, args);
@@ -309,9 +313,9 @@
for (AlertEntry entry: mAlertEntries.values()) {
pw.print(" HeadsUpEntry="); pw.println(entry.mEntry);
}
- int N = mSnoozedPackages.size();
- pw.println(" snoozed packages: " + N);
- for (int i = 0; i < N; i++) {
+ int n = mSnoozedPackages.size();
+ pw.println(" snoozed packages: " + n);
+ for (int i = 0; i < n; i++) {
pw.print(" "); pw.print(mSnoozedPackages.valueAt(i));
pw.print(", "); pw.println(mSnoozedPackages.keyAt(i));
}
@@ -399,20 +403,20 @@
*
* @param entry the entry that might be indirectly removed by the user's action
*
- * @see com.android.systemui.statusbar.notification.collection.coordinator.HeadsUpCoordinator#mActionPressListener
+ * @see HeadsUpCoordinator#mActionPressListener
* @see #canRemoveImmediately(String)
*/
public void setUserActionMayIndirectlyRemove(@NonNull NotificationEntry entry) {
HeadsUpEntry headsUpEntry = getHeadsUpEntry(entry.getKey());
if (headsUpEntry != null) {
- headsUpEntry.userActionMayIndirectlyRemove = true;
+ headsUpEntry.mUserActionMayIndirectlyRemove = true;
}
}
@Override
public boolean canRemoveImmediately(@NonNull String key) {
HeadsUpEntry headsUpEntry = getHeadsUpEntry(key);
- if (headsUpEntry != null && headsUpEntry.userActionMayIndirectlyRemove) {
+ if (headsUpEntry != null && headsUpEntry.mUserActionMayIndirectlyRemove) {
return true;
}
return super.canRemoveImmediately(key);
@@ -424,9 +428,6 @@
return new HeadsUpEntry();
}
- public void onDensityOrFontScaleChanged() {
- }
-
/**
* Determines if the notification is for a critical call that must display on top of an active
* input notification.
@@ -445,16 +446,16 @@
* lifecycle automatically when created.
*/
protected class HeadsUpEntry extends AlertEntry {
- public boolean remoteInputActive;
- public boolean userActionMayIndirectlyRemove;
+ public boolean mRemoteInputActive;
+ public boolean mUserActionMayIndirectlyRemove;
- protected boolean expanded;
- protected boolean wasUnpinned;
+ protected boolean mExpanded;
+ protected boolean mWasUnpinned;
@Override
public boolean isSticky() {
- return (mEntry.isRowPinned() && expanded)
- || remoteInputActive
+ return (mEntry.isRowPinned() && mExpanded)
+ || mRemoteInputActive
|| hasFullScreenIntent(mEntry);
}
@@ -490,9 +491,9 @@
return 1;
}
- if (remoteInputActive && !headsUpEntry.remoteInputActive) {
+ if (mRemoteInputActive && !headsUpEntry.mRemoteInputActive) {
return -1;
- } else if (!remoteInputActive && headsUpEntry.remoteInputActive) {
+ } else if (!mRemoteInputActive && headsUpEntry.mRemoteInputActive) {
return 1;
}
@@ -500,14 +501,14 @@
}
public void setExpanded(boolean expanded) {
- this.expanded = expanded;
+ this.mExpanded = expanded;
}
@Override
public void reset() {
super.reset();
- expanded = false;
- remoteInputActive = false;
+ mExpanded = false;
+ mRemoteInputActive = false;
}
@Override
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/HeadsUpManager.kt b/packages/SystemUI/src/com/android/systemui/statusbar/policy/HeadsUpManager.kt
new file mode 100644
index 0000000..d9527fe
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/HeadsUpManager.kt
@@ -0,0 +1,245 @@
+package com.android.systemui.statusbar.policy
+
+import android.graphics.Region
+import com.android.systemui.Dumpable
+import com.android.systemui.dagger.SysUISingleton
+import com.android.systemui.statusbar.notification.collection.NotificationEntry
+import dagger.Binds
+import dagger.Module
+import java.io.PrintWriter
+import java.util.stream.Stream
+import javax.inject.Inject
+
+/**
+ * A manager which handles heads up notifications which is a special mode where they simply peek
+ * from the top of the screen.
+ */
+interface HeadsUpManager : Dumpable {
+ /** The stream of all current notifications managed by this manager. */
+ val allEntries: Stream<NotificationEntry>
+
+ /** Add a listener to receive callbacks onHeadsUpGoingAway. */
+ fun addHeadsUpPhoneListener(listener: OnHeadsUpPhoneListenerChange)
+
+ /** Adds an OnHeadUpChangedListener to observe events. */
+ fun addListener(listener: OnHeadsUpChangedListener)
+
+ fun addSwipedOutNotification(key: String)
+
+ /**
+ * Whether or not the alert can be removed currently. If it hasn't been on screen long enough it
+ * should not be removed unless forced
+ *
+ * @param key the key to check if removable
+ * @return true if the alert entry can be removed
+ */
+ fun canRemoveImmediately(key: String): Boolean
+
+ /**
+ * Compare two entries and decide how they should be ranked.
+ *
+ * @return -1 if the first argument should be ranked higher than the second, 1 if the second one
+ * should be ranked higher and 0 if they are equal.
+ */
+ fun compare(a: NotificationEntry?, b: NotificationEntry?): Int
+ /**
+ * Extends the lifetime of the currently showing pulsing notification so that the pulse lasts
+ * longer.
+ */
+ fun extendHeadsUp()
+
+ /** Returns when a HUN entry should be removed in milliseconds from now. */
+ fun getEarliestRemovalTime(key: String?): Long
+
+ /** Returns the top Heads Up Notification, which appears to show at first. */
+ fun getTopEntry(): NotificationEntry?
+
+ /**
+ * Gets the touchable region needed for heads up notifications. Returns null if no touchable
+ * region is required (ie: no heads up notification currently exists).
+ */
+ fun getTouchableRegion(): Region?
+
+ /**
+ * Whether or not there are any active alerting notifications.
+ *
+ * @return true if there is an alert, false otherwise
+ */
+ fun hasNotifications(): Boolean = false
+
+ /** Returns whether there are any pinned Heads Up Notifications or not. */
+ fun hasPinnedHeadsUp(): Boolean
+
+ /** Returns whether or not the given notification is alerting and managed by this manager. */
+ fun isAlerting(key: String): Boolean
+
+ fun isHeadsUpGoingAway(): Boolean
+
+ /** Returns if the given notification is snoozed or not. */
+ fun isSnoozed(packageName: String): Boolean
+
+ /** Returns whether the entry is (pinned and expanded) or (has an active remote input). */
+ fun isSticky(key: String?): Boolean
+
+ fun isTrackingHeadsUp(): Boolean
+
+ fun onExpandingFinished()
+
+ /** Removes the OnHeadUpChangedListener from the observer list. */
+ fun removeListener(listener: OnHeadsUpChangedListener)
+
+ /**
+ * Try to remove the notification. May not succeed if the notification has not been shown long
+ * enough and needs to be kept around.
+ *
+ * @param key the key of the notification to remove
+ * @param releaseImmediately force a remove regardless of earliest removal time
+ * @return true if notification is removed, false otherwise
+ */
+ fun removeNotification(key: String, releaseImmediately: Boolean): Boolean
+
+ /**
+ * Try to remove the notification. May not succeed if the notification has not been shown long
+ * enough and needs to be kept around.
+ *
+ * @param key the key of the notification to remove
+ * @param releaseImmediately force a remove regardless of earliest removal time
+ * @param animate if true, animate the removal
+ * @return true if notification is removed, false otherwise
+ */
+ fun removeNotification(key: String, releaseImmediately: Boolean, animate: Boolean): Boolean
+
+ /** Clears all managed notifications. */
+ fun releaseAllImmediately()
+
+ fun setAnimationStateHandler(handler: AnimationStateHandler)
+
+ /**
+ * Set an entry to be expanded and therefore stick in the heads up area if it's pinned until
+ * it's collapsed again.
+ */
+ fun setExpanded(entry: NotificationEntry, expanded: Boolean)
+
+ /**
+ * Sets whether an entry's guts are exposed and therefore it should stick in the heads up area
+ * if it's pinned until it's hidden again.
+ */
+ fun setGutsShown(entry: NotificationEntry, gutsShown: Boolean)
+
+ /**
+ * Set that we are exiting the headsUp pinned mode, but some notifications might still be
+ * animating out. This is used to keep the touchable regions in a reasonable state.
+ */
+ fun setHeadsUpGoingAway(headsUpGoingAway: Boolean)
+
+ /**
+ * Notifies that a remote input textbox in notification gets active or inactive.
+ *
+ * @param entry The entry of the target notification.
+ * @param remoteInputActive True to notify active, False to notify inactive.
+ */
+ fun setRemoteInputActive(entry: NotificationEntry, remoteInputActive: Boolean)
+
+ fun setTrackingHeadsUp(tracking: Boolean)
+
+ /** Sets the current user. */
+ fun setUser(user: Int)
+
+ /**
+ * Notes that the user took an action on an entry that might indirectly cause the system or the
+ * app to remove the notification.
+ *
+ * @param entry the entry that might be indirectly removed by the user's action
+ * @see
+ * com.android.systemui.statusbar.notification.collection.coordinator.HeadsUpCoordinator.mActionPressListener
+ * @see .canRemoveImmediately
+ */
+ fun setUserActionMayIndirectlyRemove(entry: NotificationEntry)
+
+ /**
+ * Decides whether a click is invalid for a notification, i.e. it has not been shown long enough
+ * that a user might have consciously clicked on it.
+ *
+ * @param key the key of the touched notification
+ * @return whether the touch is invalid and should be discarded
+ */
+ fun shouldSwallowClick(key: String): Boolean
+
+ /**
+ * Called when posting a new notification that should alert the user and appear on screen. Adds
+ * the notification to be managed.
+ *
+ * @param entry entry to show
+ */
+ fun showNotification(entry: NotificationEntry)
+
+ fun snooze()
+
+ /**
+ * Unpins all pinned Heads Up Notifications.
+ *
+ * @param userUnPinned The unpinned action is trigger by user real operation.
+ */
+ fun unpinAll(userUnPinned: Boolean)
+
+ fun updateNotification(key: String, alert: Boolean)
+}
+
+/** Sets the animation state of the HeadsUpManager. */
+interface AnimationStateHandler {
+ fun setHeadsUpGoingAwayAnimationsAllowed(allowed: Boolean)
+}
+
+/** Listener to register for HeadsUpNotification Phone changes. */
+interface OnHeadsUpPhoneListenerChange {
+ /**
+ * Called when a heads up notification is 'going away' or no longer 'going away'. See
+ * [HeadsUpManager.setHeadsUpGoingAway].
+ */
+ fun onHeadsUpGoingAwayStateChanged(headsUpGoingAway: Boolean)
+}
+
+/* No op impl of HeadsUpManager. */
+class HeadsUpManagerEmptyImpl @Inject constructor() : HeadsUpManager {
+ override val allEntries = Stream.empty<NotificationEntry>()
+ override fun addHeadsUpPhoneListener(listener: OnHeadsUpPhoneListenerChange) {}
+ override fun addListener(listener: OnHeadsUpChangedListener) {}
+ override fun addSwipedOutNotification(key: String) {}
+ override fun canRemoveImmediately(key: String) = false
+ override fun compare(a: NotificationEntry?, b: NotificationEntry?) = 0
+ override fun dump(pw: PrintWriter, args: Array<out String>) {}
+ override fun extendHeadsUp() {}
+ override fun getEarliestRemovalTime(key: String?) = 0L
+ override fun getTouchableRegion(): Region? = null
+ override fun getTopEntry() = null
+ override fun hasPinnedHeadsUp() = false
+ override fun isAlerting(key: String) = false
+ override fun isHeadsUpGoingAway() = false
+ override fun isSnoozed(packageName: String) = false
+ override fun isSticky(key: String?) = false
+ override fun isTrackingHeadsUp() = false
+ override fun onExpandingFinished() {}
+ override fun releaseAllImmediately() {}
+ override fun removeListener(listener: OnHeadsUpChangedListener) {}
+ override fun removeNotification(key: String, releaseImmediately: Boolean) = false
+ override fun removeNotification(key: String, releaseImmediately: Boolean, animate: Boolean) =
+ false
+ override fun setAnimationStateHandler(handler: AnimationStateHandler) {}
+ override fun setExpanded(entry: NotificationEntry, expanded: Boolean) {}
+ override fun setGutsShown(entry: NotificationEntry, gutsShown: Boolean) {}
+ override fun setHeadsUpGoingAway(headsUpGoingAway: Boolean) {}
+ override fun setRemoteInputActive(entry: NotificationEntry, remoteInputActive: Boolean) {}
+ override fun setTrackingHeadsUp(tracking: Boolean) {}
+ override fun setUser(user: Int) {}
+ override fun setUserActionMayIndirectlyRemove(entry: NotificationEntry) {}
+ override fun shouldSwallowClick(key: String): Boolean = false
+ override fun showNotification(entry: NotificationEntry) {}
+ override fun snooze() {}
+ override fun unpinAll(userUnPinned: Boolean) {}
+ override fun updateNotification(key: String, alert: Boolean) {}
+}
+
+@Module
+interface HeadsUpEmptyImplModule {
+ @Binds @SysUISingleton fun bindsHeadsUpManager(noOpHum: HeadsUpManagerEmptyImpl): HeadsUpManager
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/ResourcesSplitShadeStateController.kt b/packages/SystemUI/src/com/android/systemui/statusbar/policy/ResourcesSplitShadeStateController.kt
index c302d6a..859e636 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/ResourcesSplitShadeStateController.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/ResourcesSplitShadeStateController.kt
@@ -17,6 +17,7 @@
import android.content.res.Resources
import com.android.systemui.res.R
+import javax.inject.Inject
/**
* Fake SplitShadeStateController
@@ -24,7 +25,7 @@
* Identical behaviour to legacy implementation (that used LargeScreenUtils.kt) I.E., behaviour
* based solely on resources, no extra flag logic.
*/
-class ResourcesSplitShadeStateController : SplitShadeStateController {
+class ResourcesSplitShadeStateController @Inject constructor() : SplitShadeStateController {
override fun shouldUseSplitNotificationShade(resources: Resources): Boolean {
return resources.getBoolean(R.bool.config_use_split_notification_shade)
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/dagger/StatusBarPolicyModule.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/dagger/StatusBarPolicyModule.java
index a77c692..818ba95 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/dagger/StatusBarPolicyModule.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/dagger/StatusBarPolicyModule.java
@@ -70,6 +70,7 @@
import com.android.systemui.statusbar.policy.ZenModeControllerImpl;
import com.android.systemui.statusbar.policy.bluetooth.BluetoothRepository;
import com.android.systemui.statusbar.policy.bluetooth.BluetoothRepositoryImpl;
+import com.android.systemui.statusbar.policy.data.repository.DeviceProvisioningRepositoryModule;
import dagger.Binds;
import dagger.Module;
@@ -80,7 +81,7 @@
import javax.inject.Named;
/** Dagger Module for code in the statusbar.policy package. */
-@Module
+@Module(includes = { DeviceProvisioningRepositoryModule.class })
public interface StatusBarPolicyModule {
String DEVICE_STATE_ROTATION_LOCK_DEFAULTS = "DEVICE_STATE_ROTATION_LOCK_DEFAULTS";
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/data/repository/DeviceProvisioningRepository.kt b/packages/SystemUI/src/com/android/systemui/statusbar/policy/data/repository/DeviceProvisioningRepository.kt
new file mode 100644
index 0000000..1160d65
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/data/repository/DeviceProvisioningRepository.kt
@@ -0,0 +1,73 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.systemui.statusbar.policy.data.repository
+
+import com.android.systemui.common.coroutine.ConflatedCallbackFlow.conflatedCallbackFlow
+import com.android.systemui.statusbar.policy.DeviceProvisionedController
+import dagger.Binds
+import dagger.Module
+import javax.inject.Inject
+import kotlinx.coroutines.channels.awaitClose
+import kotlinx.coroutines.flow.Flow
+
+/** Tracks state related to device provisioning. */
+interface DeviceProvisioningRepository {
+ /**
+ * Whether this device has been provisioned.
+ *
+ * @see android.provider.Settings.Global.DEVICE_PROVISIONED
+ */
+ val isDeviceProvisioned: Flow<Boolean>
+
+ /** Whether Factory Reset Protection (FRP) is currently active, locking the device. */
+ val isFactoryResetProtectionActive: Flow<Boolean>
+}
+
+@Module
+interface DeviceProvisioningRepositoryModule {
+ @Binds fun bindsImpl(impl: DeviceProvisioningRepositoryImpl): DeviceProvisioningRepository
+}
+
+class DeviceProvisioningRepositoryImpl
+@Inject
+constructor(
+ private val deviceProvisionedController: DeviceProvisionedController,
+) : DeviceProvisioningRepository {
+
+ override val isDeviceProvisioned: Flow<Boolean> = conflatedCallbackFlow {
+ val listener =
+ object : DeviceProvisionedController.DeviceProvisionedListener {
+ override fun onDeviceProvisionedChanged() {
+ trySend(deviceProvisionedController.isDeviceProvisioned)
+ }
+ }
+ deviceProvisionedController.addCallback(listener)
+ trySend(deviceProvisionedController.isDeviceProvisioned)
+ awaitClose { deviceProvisionedController.removeCallback(listener) }
+ }
+
+ override val isFactoryResetProtectionActive: Flow<Boolean> = conflatedCallbackFlow {
+ val listener =
+ object : DeviceProvisionedController.DeviceProvisionedListener {
+ override fun onFrpActiveChanged() {
+ trySend(deviceProvisionedController.isFrpActive)
+ }
+ }
+ deviceProvisionedController.addCallback(listener)
+ trySend(deviceProvisionedController.isFrpActive)
+ awaitClose { deviceProvisionedController.removeCallback(listener) }
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/user/domain/interactor/UserInteractor.kt b/packages/SystemUI/src/com/android/systemui/user/domain/interactor/UserInteractor.kt
index ce9d6fd..dbc3bf3 100644
--- a/packages/SystemUI/src/com/android/systemui/user/domain/interactor/UserInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/user/domain/interactor/UserInteractor.kt
@@ -325,6 +325,7 @@
addAction(Intent.ACTION_USER_SWITCHED)
addAction(Intent.ACTION_USER_STOPPED)
addAction(Intent.ACTION_USER_UNLOCKED)
+ addAction(Intent.ACTION_LOCALE_CHANGED)
},
user = UserHandle.SYSTEM,
map = { intent, _ -> intent },
@@ -615,6 +616,7 @@
) {
val shouldRefreshAllUsers =
when (intent.action) {
+ Intent.ACTION_LOCALE_CHANGED -> true
Intent.ACTION_USER_SWITCHED -> {
dismissDialog()
val selectedUserId = intent.getIntExtra(Intent.EXTRA_USER_HANDLE, -1)
@@ -644,6 +646,11 @@
}
private fun restartSecondaryService(@UserIdInt userId: Int) {
+ // Do not start service for user that is marked for deletion.
+ if (!manager.aliveUsers.map { it.id }.contains(userId)) {
+ return
+ }
+
val intent = Intent(applicationContext, SystemUISecondaryUserService::class.java)
// Disconnect from the old secondary user's service
val secondaryUserId = repository.secondaryUserId
@@ -657,6 +664,7 @@
// Connect to the new secondary user's service (purely to ensure that a persistent
// SystemUI application is created for that user)
+
if (userId != Process.myUserHandle().identifier) {
applicationContext.startServiceAsUser(
intent,
diff --git a/packages/SystemUI/src/com/android/systemui/user/ui/viewmodel/UserSwitcherViewModel.kt b/packages/SystemUI/src/com/android/systemui/user/ui/viewmodel/UserSwitcherViewModel.kt
index d3f83b1..20f0fa8c 100644
--- a/packages/SystemUI/src/com/android/systemui/user/ui/viewmodel/UserSwitcherViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/user/ui/viewmodel/UserSwitcherViewModel.kt
@@ -68,6 +68,7 @@
private val hasCancelButtonBeenClicked = MutableStateFlow(false)
private val isFinishRequiredDueToExecutedAction = MutableStateFlow(false)
+ private val userSwitched = MutableStateFlow(false)
/**
* Whether the observer should finish the experience. Once consumed, [onFinished] must be called
@@ -89,6 +90,7 @@
fun onFinished() {
hasCancelButtonBeenClicked.value = false
isFinishRequiredDueToExecutedAction.value = false
+ userSwitched.value = false
}
/** Notifies that the user has clicked the "open menu" button. */
@@ -121,8 +123,9 @@
hasCancelButtonBeenClicked,
// If an executed action told us to finish, we should finish,
isFinishRequiredDueToExecutedAction,
- ) { cancelButtonClicked, executedActionFinish ->
- cancelButtonClicked || executedActionFinish
+ userSwitched,
+ ) { cancelButtonClicked, executedActionFinish, userSwitched ->
+ cancelButtonClicked || executedActionFinish || userSwitched
}
private fun toViewModel(
@@ -191,7 +194,10 @@
return if (!model.isSelectable) {
null
} else {
- { userInteractor.selectUser(model.id) }
+ {
+ userInteractor.selectUser(model.id)
+ userSwitched.value = true
+ }
}
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/util/ReferenceExt.kt b/packages/SystemUI/src/com/android/systemui/util/ReferenceExt.kt
new file mode 100644
index 0000000..ac04d31
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/util/ReferenceExt.kt
@@ -0,0 +1,50 @@
+package com.android.systemui.util
+
+import java.lang.ref.SoftReference
+import java.lang.ref.WeakReference
+import kotlin.properties.ReadWriteProperty
+import kotlin.reflect.KProperty
+
+/**
+ * Creates a Kotlin idiomatic weak reference.
+ *
+ * Usage:
+ * ```
+ * var weakReferenceObj: Object? by weakReference(null)
+ * weakReferenceObj = Object()
+ * ```
+ */
+fun <T> weakReference(obj: T? = null): ReadWriteProperty<Any?, T?> {
+ return object : ReadWriteProperty<Any?, T?> {
+ var weakRef = WeakReference<T?>(obj)
+ override fun getValue(thisRef: Any?, property: KProperty<*>): T? {
+ return weakRef.get()
+ }
+
+ override fun setValue(thisRef: Any?, property: KProperty<*>, value: T?) {
+ weakRef = WeakReference(value)
+ }
+ }
+}
+
+/**
+ * Creates a Kotlin idiomatic soft reference.
+ *
+ * Usage:
+ * ```
+ * var softReferenceObj: Object? by softReference(null)
+ * softReferenceObj = Object()
+ * ```
+ */
+fun <T> softReference(obj: T? = null): ReadWriteProperty<Any?, T?> {
+ return object : ReadWriteProperty<Any?, T?> {
+ var softRef = SoftReference<T?>(obj)
+ override fun getValue(thisRef: Any?, property: KProperty<*>): T? {
+ return softRef.get()
+ }
+
+ override fun setValue(thisRef: Any?, property: KProperty<*>, value: T?) {
+ softRef = SoftReference(value)
+ }
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/wallet/ui/WalletActivity.java b/packages/SystemUI/src/com/android/systemui/wallet/ui/WalletActivity.java
index 750b6f9..2132904 100644
--- a/packages/SystemUI/src/com/android/systemui/wallet/ui/WalletActivity.java
+++ b/packages/SystemUI/src/com/android/systemui/wallet/ui/WalletActivity.java
@@ -40,12 +40,13 @@
import com.android.keyguard.KeyguardUpdateMonitor;
import com.android.keyguard.KeyguardUpdateMonitorCallback;
import com.android.settingslib.Utils;
-import com.android.systemui.res.R;
import com.android.systemui.classifier.FalsingCollector;
import com.android.systemui.dagger.qualifiers.Background;
import com.android.systemui.dagger.qualifiers.Main;
+import com.android.systemui.keyguard.domain.interactor.KeyguardFaceAuthInteractor;
import com.android.systemui.plugins.ActivityStarter;
import com.android.systemui.plugins.FalsingManager;
+import com.android.systemui.res.R;
import com.android.systemui.settings.UserTracker;
import com.android.systemui.statusbar.phone.KeyguardDismissUtil;
import com.android.systemui.statusbar.phone.StatusBarKeyguardViewManager;
@@ -68,6 +69,7 @@
private final Executor mExecutor;
private final Handler mHandler;
private final FalsingManager mFalsingManager;
+ private final KeyguardFaceAuthInteractor mKeyguardFaceAuthInteractor;
private FalsingCollector mFalsingCollector;
private final UserTracker mUserTracker;
private final KeyguardUpdateMonitor mKeyguardUpdateMonitor;
@@ -91,7 +93,8 @@
UserTracker userTracker,
KeyguardUpdateMonitor keyguardUpdateMonitor,
StatusBarKeyguardViewManager keyguardViewManager,
- UiEventLogger uiEventLogger) {
+ UiEventLogger uiEventLogger,
+ KeyguardFaceAuthInteractor keyguardFaceAuthInteractor) {
mKeyguardStateController = keyguardStateController;
mKeyguardDismissUtil = keyguardDismissUtil;
mActivityStarter = activityStarter;
@@ -103,6 +106,7 @@
mKeyguardUpdateMonitor = keyguardUpdateMonitor;
mKeyguardViewManager = keyguardViewManager;
mUiEventLogger = uiEventLogger;
+ mKeyguardFaceAuthInteractor = keyguardFaceAuthInteractor;
}
@Override
@@ -209,6 +213,7 @@
true,
Utils.getColorAttrDefaultColor(
this, com.android.internal.R.attr.colorAccentPrimary));
+ mKeyguardFaceAuthInteractor.onWalletLaunched();
mKeyguardViewManager.requestFace(true);
}
diff --git a/packages/SystemUI/tests/src/com/android/TestMocksModule.kt b/packages/SystemUI/tests/src/com/android/TestMocksModule.kt
index 8990583..c1be44a 100644
--- a/packages/SystemUI/tests/src/com/android/TestMocksModule.kt
+++ b/packages/SystemUI/tests/src/com/android/TestMocksModule.kt
@@ -18,61 +18,94 @@
import android.app.ActivityManager
import android.app.admin.DevicePolicyManager
import android.os.UserManager
+import android.util.DisplayMetrics
+import com.android.internal.logging.MetricsLogger
import com.android.keyguard.KeyguardSecurityModel
import com.android.keyguard.KeyguardUpdateMonitor
import com.android.systemui.GuestResumeSessionReceiver
import com.android.systemui.demomode.DemoModeController
+import com.android.systemui.dump.DumpManager
+import com.android.systemui.keyguard.ScreenLifecycle
+import com.android.systemui.keyguard.WakefulnessLifecycle
import com.android.systemui.log.LogBuffer
import com.android.systemui.log.dagger.BroadcastDispatcherLog
import com.android.systemui.log.dagger.SceneFrameworkLog
+import com.android.systemui.media.controls.ui.MediaHierarchyManager
import com.android.systemui.plugins.ActivityStarter
import com.android.systemui.plugins.DarkIconDispatcher
import com.android.systemui.plugins.statusbar.StatusBarStateController
import com.android.systemui.statusbar.NotificationListener
+import com.android.systemui.statusbar.NotificationLockscreenUserManager
import com.android.systemui.statusbar.NotificationMediaManager
+import com.android.systemui.statusbar.NotificationShadeDepthController
+import com.android.systemui.statusbar.SysuiStatusBarStateController
import com.android.systemui.statusbar.notification.NotificationWakeUpCoordinator
+import com.android.systemui.statusbar.notification.stack.AmbientState
+import com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayoutController
+import com.android.systemui.statusbar.notification.stack.NotificationStackSizeCalculator
import com.android.systemui.statusbar.phone.DozeParameters
import com.android.systemui.statusbar.phone.KeyguardBypassController
+import com.android.systemui.statusbar.phone.LSShadeTransitionLogger
import com.android.systemui.statusbar.phone.ScreenOffAnimationController
-import com.android.systemui.statusbar.policy.ConfigurationController
+import com.android.systemui.statusbar.phone.ScrimController
import com.android.systemui.statusbar.policy.DeviceProvisionedController
-import com.android.systemui.statusbar.policy.SplitShadeStateController
import com.android.systemui.statusbar.window.StatusBarWindowController
import com.android.systemui.util.mockito.mock
import com.android.wm.shell.bubbles.Bubbles
+import dagger.Binds
import dagger.Module
import dagger.Provides
import java.util.Optional
-@Module
+@Module(includes = [TestMocksModule.Bindings::class])
data class TestMocksModule(
@get:Provides val activityStarter: ActivityStarter = mock(),
+ @get:Provides val ambientState: AmbientState = mock(),
@get:Provides val bubbles: Optional<Bubbles> = Optional.of(mock()),
- @get:Provides val configurationController: ConfigurationController = mock(),
@get:Provides val darkIconDispatcher: DarkIconDispatcher = mock(),
@get:Provides val demoModeController: DemoModeController = mock(),
@get:Provides val deviceProvisionedController: DeviceProvisionedController = mock(),
@get:Provides val dozeParameters: DozeParameters = mock(),
+ @get:Provides val dumpManager: DumpManager = mock(),
@get:Provides val guestResumeSessionReceiver: GuestResumeSessionReceiver = mock(),
@get:Provides val keyguardBypassController: KeyguardBypassController = mock(),
@get:Provides val keyguardSecurityModel: KeyguardSecurityModel = mock(),
@get:Provides val keyguardUpdateMonitor: KeyguardUpdateMonitor = mock(),
- @get:Provides val notifListener: NotificationListener = mock(),
- @get:Provides val notifMediaManager: NotificationMediaManager = mock(),
+ @get:Provides val mediaHierarchyManager: MediaHierarchyManager = mock(),
+ @get:Provides val notificationListener: NotificationListener = mock(),
+ @get:Provides val notificationLockscreenUserManager: NotificationLockscreenUserManager = mock(),
+ @get:Provides val notificationMediaManager: NotificationMediaManager = mock(),
+ @get:Provides val notificationShadeDepthController: NotificationShadeDepthController = mock(),
+ @get:Provides
+ val notificationStackScrollLayoutController: NotificationStackScrollLayoutController = mock(),
+ @get:Provides val notificationStackSizeCalculator: NotificationStackSizeCalculator = mock(),
+ @get:Provides val notificationWakeUpCoordinator: NotificationWakeUpCoordinator = mock(),
+ @get:Provides val screenLifecycle: ScreenLifecycle = mock(),
@get:Provides val screenOffAnimController: ScreenOffAnimationController = mock(),
- @get:Provides val splitShadeStateController: SplitShadeStateController = mock(),
- @get:Provides val statusBarStateController: StatusBarStateController = mock(),
+ @get:Provides val scrimController: ScrimController = mock(),
+ @get:Provides val statusBarStateController: SysuiStatusBarStateController = mock(),
@get:Provides val statusBarWindowController: StatusBarWindowController = mock(),
- @get:Provides val wakeUpCoordinator: NotificationWakeUpCoordinator = mock(),
+ @get:Provides val wakefulnessLifecycle: WakefulnessLifecycle = mock(),
// log buffers
@get:[Provides BroadcastDispatcherLog]
val broadcastDispatcherLogger: LogBuffer = mock(),
@get:[Provides SceneFrameworkLog]
val sceneLogger: LogBuffer = mock(),
+ @get:Provides val lsShadeTransitionLogger: LSShadeTransitionLogger = mock(),
// framework mocks
@get:Provides val activityManager: ActivityManager = mock(),
@get:Provides val devicePolicyManager: DevicePolicyManager = mock(),
+ @get:Provides val displayMetrics: DisplayMetrics = mock(),
+ @get:Provides val metricsLogger: MetricsLogger = mock(),
@get:Provides val userManager: UserManager = mock(),
-)
+) {
+ @Module
+ interface Bindings {
+ @Binds
+ fun bindStatusBarStateController(
+ sysuiStatusBarStateController: SysuiStatusBarStateController,
+ ): StatusBarStateController
+ }
+}
diff --git a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardPasswordViewControllerTest.kt b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardPasswordViewControllerTest.kt
index f943acd..d8a2c5f 100644
--- a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardPasswordViewControllerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardPasswordViewControllerTest.kt
@@ -25,7 +25,6 @@
import com.android.internal.util.LatencyTracker
import com.android.internal.widget.LockPatternUtils
import com.android.systemui.res.R
-import com.android.systemui.RoboPilotTest
import com.android.systemui.SysuiTestCase
import com.android.systemui.classifier.FalsingCollector
import com.android.systemui.flags.FakeFeatureFlags
@@ -47,7 +46,6 @@
import org.mockito.MockitoAnnotations
@SmallTest
-@RoboPilotTest
@RunWith(AndroidJUnit4::class)
@TestableLooper.RunWithLooper
class KeyguardPasswordViewControllerTest : SysuiTestCase() {
diff --git a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardPatternViewControllerTest.kt b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardPatternViewControllerTest.kt
index e090093..dc1618d 100644
--- a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardPatternViewControllerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardPatternViewControllerTest.kt
@@ -25,7 +25,6 @@
import com.android.internal.util.LatencyTracker
import com.android.internal.widget.LockPatternUtils
import com.android.systemui.res.R
-import com.android.systemui.RoboPilotTest
import com.android.systemui.SysuiTestCase
import com.android.systemui.classifier.FalsingCollector
import com.android.systemui.classifier.FalsingCollectorFake
@@ -53,7 +52,6 @@
import org.mockito.MockitoAnnotations
@SmallTest
-@RoboPilotTest
@RunWith(AndroidJUnit4::class)
@TestableLooper.RunWithLooper
class KeyguardPatternViewControllerTest : SysuiTestCase() {
diff --git a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardPinBasedInputViewControllerTest.java b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardPinBasedInputViewControllerTest.java
index 8322b37..4a24e4a 100644
--- a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardPinBasedInputViewControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardPinBasedInputViewControllerTest.java
@@ -31,14 +31,13 @@
import com.android.internal.util.LatencyTracker;
import com.android.internal.widget.LockPatternUtils;
import com.android.keyguard.KeyguardSecurityModel.SecurityMode;
-import com.android.systemui.res.R;
-import com.android.systemui.RoboPilotTest;
import com.android.systemui.SysuiTestCase;
import com.android.systemui.classifier.FalsingCollector;
import com.android.systemui.classifier.FalsingCollectorFake;
import com.android.systemui.classifier.SingleTapClassifier;
import com.android.systemui.flags.FakeFeatureFlags;
import com.android.systemui.flags.Flags;
+import com.android.systemui.res.R;
import org.junit.Before;
import org.junit.Test;
@@ -47,7 +46,6 @@
import org.mockito.MockitoAnnotations;
@SmallTest
-@RoboPilotTest
@RunWith(AndroidJUnit4.class)
@RunWithLooper
public class KeyguardPinBasedInputViewControllerTest extends SysuiTestCase {
diff --git a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardPinViewControllerTest.kt b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardPinViewControllerTest.kt
index 2f08804..9df4dd4 100644
--- a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardPinViewControllerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardPinViewControllerTest.kt
@@ -26,7 +26,6 @@
import com.android.internal.widget.LockPatternUtils
import com.android.keyguard.KeyguardSecurityModel.SecurityMode
import com.android.systemui.res.R
-import com.android.systemui.RoboPilotTest
import com.android.systemui.SysuiTestCase
import com.android.systemui.classifier.FalsingCollector
import com.android.systemui.classifier.FalsingCollectorFake
@@ -53,7 +52,6 @@
import org.mockito.MockitoAnnotations
@SmallTest
-@RoboPilotTest
@RunWith(AndroidJUnit4::class)
@TestableLooper.RunWithLooper
class KeyguardPinViewControllerTest : SysuiTestCase() {
diff --git a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardPresentationTest.java b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardPresentationTest.java
index f3a1b68..5102957 100644
--- a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardPresentationTest.java
+++ b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardPresentationTest.java
@@ -69,7 +69,8 @@
when(mMockKeyguardSliceView.getContext()).thenReturn(mContext);
when(mMockKeyguardStatusView.getContext()).thenReturn(mContext);
when(mMockKeyguardStatusView.findViewById(R.id.clock)).thenReturn(mMockKeyguardStatusView);
- when(mKeyguardStatusViewComponentFactory.build(any(KeyguardStatusView.class)))
+ when(mKeyguardStatusViewComponentFactory.build(any(KeyguardStatusView.class),
+ any(Display.class)))
.thenReturn(mKeyguardStatusViewComponent);
when(mKeyguardStatusViewComponent.getKeyguardClockSwitchController())
.thenReturn(mKeyguardClockSwitchController);
diff --git a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardSecurityContainerControllerTest.kt b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardSecurityContainerControllerTest.kt
index d54843d3..62f9a9d 100644
--- a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardSecurityContainerControllerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardSecurityContainerControllerTest.kt
@@ -36,7 +36,6 @@
import com.android.internal.widget.LockPatternUtils
import com.android.keyguard.KeyguardSecurityContainer.UserSwitcherViewMode.UserSwitcherCallback
import com.android.keyguard.KeyguardSecurityModel.SecurityMode
-import com.android.systemui.RoboPilotTest
import com.android.systemui.SysuiTestCase
import com.android.systemui.biometrics.FaceAuthAccessibilityDelegate
import com.android.systemui.biometrics.SideFpsController
@@ -100,7 +99,6 @@
import org.mockito.MockitoAnnotations
@SmallTest
-@RoboPilotTest
@RunWith(AndroidJUnit4::class)
@RunWithLooper
class KeyguardSecurityContainerControllerTest : SysuiTestCase() {
@@ -812,6 +810,7 @@
SceneKey.Bouncer,
flowOf(.5f),
false,
+ isUserInputOngoing = flowOf(false),
)
runCurrent()
sceneInteractor.onSceneChanged(SceneModel(SceneKey.Bouncer, null), "reason")
@@ -827,7 +826,8 @@
SceneKey.Bouncer,
SceneKey.Gone,
flowOf(.5f),
- false
+ false,
+ isUserInputOngoing = flowOf(false),
)
runCurrent()
sceneInteractor.onSceneChanged(SceneModel(SceneKey.Gone, null), "reason")
@@ -844,7 +844,8 @@
SceneKey.Gone,
SceneKey.Bouncer,
flowOf(.5f),
- false
+ false,
+ isUserInputOngoing = flowOf(false),
)
runCurrent()
sceneInteractor.onSceneChanged(SceneModel(SceneKey.Bouncer, null), "reason")
@@ -862,7 +863,8 @@
SceneKey.Bouncer,
SceneKey.Gone,
flowOf(.5f),
- false
+ false,
+ isUserInputOngoing = flowOf(false),
)
runCurrent()
sceneInteractor.onSceneChanged(SceneModel(SceneKey.Gone, null), "reason")
@@ -878,6 +880,7 @@
SceneKey.Lockscreen,
flowOf(.5f),
false,
+ isUserInputOngoing = flowOf(false),
)
runCurrent()
sceneInteractor.onSceneChanged(SceneModel(SceneKey.Lockscreen, null), "reason")
@@ -895,6 +898,7 @@
SceneKey.Gone,
flowOf(.5f),
false,
+ isUserInputOngoing = flowOf(false),
)
runCurrent()
sceneInteractor.onSceneChanged(SceneModel(SceneKey.Gone, null), "reason")
diff --git a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardSecurityContainerTest.java b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardSecurityContainerTest.java
index aad11d9..156e068 100644
--- a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardSecurityContainerTest.java
+++ b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardSecurityContainerTest.java
@@ -56,11 +56,10 @@
import androidx.test.ext.junit.runners.AndroidJUnit4;
import androidx.test.filters.SmallTest;
-import com.android.systemui.res.R;
-import com.android.systemui.RoboPilotTest;
import com.android.systemui.SysuiTestCase;
import com.android.systemui.classifier.FalsingA11yDelegate;
import com.android.systemui.plugins.FalsingManager;
+import com.android.systemui.res.R;
import com.android.systemui.statusbar.policy.UserSwitcherController;
import com.android.systemui.user.data.source.UserRecord;
import com.android.systemui.util.settings.GlobalSettings;
@@ -76,7 +75,6 @@
import java.util.ArrayList;
@SmallTest
-@RoboPilotTest
@RunWith(AndroidJUnit4.class)
@TestableLooper.RunWithLooper()
public class KeyguardSecurityContainerTest extends SysuiTestCase {
diff --git a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardSecurityViewFlipperControllerTest.java b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardSecurityViewFlipperControllerTest.java
index b02b1f9..7bb6ef1 100644
--- a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardSecurityViewFlipperControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardSecurityViewFlipperControllerTest.java
@@ -35,10 +35,9 @@
import androidx.test.filters.SmallTest;
import com.android.keyguard.KeyguardSecurityModel.SecurityMode;
-import com.android.systemui.res.R;
-import com.android.systemui.RoboPilotTest;
import com.android.systemui.SysuiTestCase;
import com.android.systemui.flags.FeatureFlags;
+import com.android.systemui.res.R;
import org.junit.Before;
import org.junit.Rule;
@@ -50,7 +49,6 @@
import org.mockito.junit.MockitoRule;
@SmallTest
-@RoboPilotTest
@RunWith(AndroidJUnit4.class)
@TestableLooper.RunWithLooper()
public class KeyguardSecurityViewFlipperControllerTest extends SysuiTestCase {
diff --git a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardSimPinViewControllerTest.kt b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardSimPinViewControllerTest.kt
index d0bb5a9..4290b8b 100644
--- a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardSimPinViewControllerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardSimPinViewControllerTest.kt
@@ -25,7 +25,6 @@
import com.android.internal.util.LatencyTracker
import com.android.internal.widget.LockPatternUtils
import com.android.systemui.res.R
-import com.android.systemui.RoboPilotTest
import com.android.systemui.SysuiTestCase
import com.android.systemui.classifier.FalsingCollector
import com.android.systemui.flags.FakeFeatureFlags
@@ -44,7 +43,6 @@
import org.mockito.MockitoAnnotations
@SmallTest
-@RoboPilotTest
@RunWith(AndroidJUnit4::class)
@TestableLooper.RunWithLooper
class KeyguardSimPinViewControllerTest : SysuiTestCase() {
diff --git a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardSimPukViewControllerTest.kt b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardSimPukViewControllerTest.kt
index 59cd26c..31ee641 100644
--- a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardSimPukViewControllerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardSimPukViewControllerTest.kt
@@ -25,7 +25,6 @@
import com.android.internal.util.LatencyTracker
import com.android.internal.widget.LockPatternUtils
import com.android.systemui.res.R
-import com.android.systemui.RoboPilotTest
import com.android.systemui.SysuiTestCase
import com.android.systemui.classifier.FalsingCollector
import com.android.systemui.flags.FakeFeatureFlags
@@ -40,7 +39,6 @@
import org.mockito.MockitoAnnotations
@SmallTest
-@RoboPilotTest
@RunWith(AndroidJUnit4::class)
@TestableLooper.RunWithLooper
class KeyguardSimPukViewControllerTest : SysuiTestCase() {
diff --git a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardStatusViewControllerTest.java b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardStatusViewControllerTest.java
index e4e2b0a..9a908d7 100644
--- a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardStatusViewControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardStatusViewControllerTest.java
@@ -29,9 +29,9 @@
import android.testing.TestableLooper;
import android.view.View;
-import com.android.systemui.res.R;
import com.android.systemui.plugins.ClockConfig;
import com.android.systemui.plugins.ClockController;
+import com.android.systemui.res.R;
import com.android.systemui.statusbar.notification.AnimatableProperty;
import com.android.systemui.statusbar.policy.ConfigurationController.ConfigurationListener;
@@ -81,7 +81,7 @@
public void updatePosition_primaryClockAnimation() {
ClockController mockClock = mock(ClockController.class);
when(mKeyguardClockSwitchController.getClock()).thenReturn(mockClock);
- when(mockClock.getConfig()).thenReturn(new ClockConfig("MOCK", false, true));
+ when(mockClock.getConfig()).thenReturn(new ClockConfig("MOCK", "", "", false, true));
mController.updatePosition(10, 15, 20f, true);
@@ -96,7 +96,7 @@
public void updatePosition_alternateClockAnimation() {
ClockController mockClock = mock(ClockController.class);
when(mKeyguardClockSwitchController.getClock()).thenReturn(mockClock);
- when(mockClock.getConfig()).thenReturn(new ClockConfig("MOCK", true, true));
+ when(mockClock.getConfig()).thenReturn(new ClockConfig("MOCK", "", "", true, true));
mController.updatePosition(10, 15, 20f, true);
diff --git a/packages/SystemUI/tests/src/com/android/keyguard/LockIconViewControllerBaseTest.java b/packages/SystemUI/tests/src/com/android/keyguard/LockIconViewControllerBaseTest.java
index 21a2822..d61ca69 100644
--- a/packages/SystemUI/tests/src/com/android/keyguard/LockIconViewControllerBaseTest.java
+++ b/packages/SystemUI/tests/src/com/android/keyguard/LockIconViewControllerBaseTest.java
@@ -39,10 +39,10 @@
import android.view.WindowManager;
import android.view.accessibility.AccessibilityManager;
-import com.android.systemui.res.R;
import com.android.systemui.SysuiTestCase;
import com.android.systemui.biometrics.AuthController;
import com.android.systemui.biometrics.AuthRippleController;
+import com.android.systemui.bouncer.domain.interactor.BouncerInteractor;
import com.android.systemui.bouncer.domain.interactor.PrimaryBouncerInteractor;
import com.android.systemui.doze.util.BurnInHelperKt;
import com.android.systemui.dump.DumpManager;
@@ -51,6 +51,8 @@
import com.android.systemui.keyguard.domain.interactor.KeyguardTransitionInteractorFactory;
import com.android.systemui.plugins.FalsingManager;
import com.android.systemui.plugins.statusbar.StatusBarStateController;
+import com.android.systemui.res.R;
+import com.android.systemui.scene.SceneTestUtils;
import com.android.systemui.statusbar.StatusBarState;
import com.android.systemui.statusbar.VibratorHelper;
import com.android.systemui.statusbar.policy.ConfigurationController;
@@ -75,6 +77,8 @@
protected MockitoSession mStaticMockSession;
+ protected final SceneTestUtils mSceneTestUtils = new SceneTestUtils(this);
+ protected @Mock BouncerInteractor mBouncerInteractor;
protected @Mock LockIconView mLockIconView;
protected @Mock AnimatedStateListDrawable mIconDrawable;
protected @Mock Context mContext;
@@ -93,6 +97,7 @@
protected @Mock AuthRippleController mAuthRippleController;
protected FakeExecutor mDelayableExecutor = new FakeExecutor(new FakeSystemClock());
protected FakeFeatureFlags mFeatureFlags;
+
protected @Mock PrimaryBouncerInteractor mPrimaryBouncerInteractor;
protected LockIconViewController mUnderTest;
@@ -148,6 +153,7 @@
mFeatureFlags.set(MIGRATE_LOCK_ICON, false);
mFeatureFlags.set(LOCKSCREEN_WALLPAPER_DREAM_ENABLED, false);
mFeatureFlags.set(LOCKSCREEN_ENABLE_LANDSCAPE, false);
+
mUnderTest = new LockIconViewController(
mStatusBarStateController,
mKeyguardUpdateMonitor,
@@ -168,7 +174,9 @@
KeyguardInteractorFactory.create(mFeatureFlags).getKeyguardInteractor(),
mFeatureFlags,
mPrimaryBouncerInteractor,
- mContext
+ mContext,
+ () -> mBouncerInteractor,
+ mSceneTestUtils.getSceneContainerFlags()
);
}
@@ -227,8 +235,8 @@
setupLockIconViewMocks();
}
- protected void init(boolean useMigrationFlag) {
- mFeatureFlags.set(DOZING_MIGRATION_1, useMigrationFlag);
+ protected void init(boolean useDozeMigrationFlag) {
+ mFeatureFlags.set(DOZING_MIGRATION_1, useDozeMigrationFlag);
mUnderTest.setLockIconView(mLockIconView);
}
}
diff --git a/packages/SystemUI/tests/src/com/android/keyguard/LockIconViewControllerTest.java b/packages/SystemUI/tests/src/com/android/keyguard/LockIconViewControllerTest.java
index 7b920939..4bacc3d 100644
--- a/packages/SystemUI/tests/src/com/android/keyguard/LockIconViewControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/keyguard/LockIconViewControllerTest.java
@@ -26,6 +26,7 @@
import static org.mockito.Mockito.anyBoolean;
import static org.mockito.Mockito.anyInt;
import static org.mockito.Mockito.eq;
+import static org.mockito.Mockito.never;
import static org.mockito.Mockito.reset;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
@@ -404,6 +405,49 @@
// THEN uses perform haptic feedback
verify(mVibrator).performHapticFeedback(any(), eq(UdfpsController.LONG_PRESS));
+ }
+ @Test
+ public void longPress_showBouncer_sceneContainerNotEnabled() {
+ init(/* useMigrationFlag= */ false);
+ mSceneTestUtils.getSceneContainerFlags().setEnabled(false);
+ mFeatureFlags.set(ONE_WAY_HAPTICS_API_MIGRATION, true);
+ when(mFalsingManager.isFalseLongTap(anyInt())).thenReturn(false);
+
+ // WHEN longPress
+ mUnderTest.onLongPress();
+
+ // THEN show primary bouncer via keyguard view controller, not scene container
+ verify(mKeyguardViewController).showPrimaryBouncer(anyBoolean());
+ verify(mBouncerInteractor, never()).showOrUnlockDevice(any());
+ }
+
+ @Test
+ public void longPress_showBouncer() {
+ init(/* useMigrationFlag= */ false);
+ mSceneTestUtils.getSceneContainerFlags().setEnabled(true);
+ mFeatureFlags.set(ONE_WAY_HAPTICS_API_MIGRATION, true);
+ when(mFalsingManager.isFalseLongTap(anyInt())).thenReturn(false);
+
+ // WHEN longPress
+ mUnderTest.onLongPress();
+
+ // THEN show primary bouncer
+ verify(mKeyguardViewController, never()).showPrimaryBouncer(anyBoolean());
+ verify(mBouncerInteractor).showOrUnlockDevice(any());
+ }
+
+ @Test
+ public void longPress_falsingTriggered_doesNotShowBouncer() {
+ init(/* useMigrationFlag= */ false);
+ mSceneTestUtils.getSceneContainerFlags().setEnabled(true);
+ mFeatureFlags.set(ONE_WAY_HAPTICS_API_MIGRATION, true);
+ when(mFalsingManager.isFalseLongTap(anyInt())).thenReturn(true);
+
+ // WHEN longPress
+ mUnderTest.onLongPress();
+
+ // THEN don't show primary bouncer
+ verify(mBouncerInteractor, never()).showOrUnlockDevice(any());
}
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/animation/ActivityLaunchAnimatorTest.kt b/packages/SystemUI/tests/src/com/android/systemui/animation/ActivityLaunchAnimatorTest.kt
index 59c7e76..8faf715 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/animation/ActivityLaunchAnimatorTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/animation/ActivityLaunchAnimatorTest.kt
@@ -166,6 +166,9 @@
waitForIdleSync()
verify(controller).onLaunchAnimationCancelled()
verify(controller, never()).onLaunchAnimationStart(anyBoolean())
+ verify(listener).onLaunchAnimationCancelled()
+ verify(listener, never()).onLaunchAnimationStart()
+ assertNull(runner.delegate)
}
@Test
@@ -176,6 +179,9 @@
waitForIdleSync()
verify(controller).onLaunchAnimationCancelled()
verify(controller, never()).onLaunchAnimationStart(anyBoolean())
+ verify(listener).onLaunchAnimationCancelled()
+ verify(listener, never()).onLaunchAnimationStart()
+ assertNull(runner.delegate)
}
@Test
@@ -194,6 +200,15 @@
}
}
+ @Test
+ fun disposeRunner_delegateDereferenced() {
+ val runner = activityLaunchAnimator.createRunner(controller)
+ assertNotNull(runner.delegate)
+ runner.dispose()
+ waitForIdleSync()
+ assertNull(runner.delegate)
+ }
+
private fun fakeWindow(): RemoteAnimationTarget {
val bounds = Rect(10 /* left */, 20 /* top */, 30 /* right */, 40 /* bottom */)
val taskInfo = ActivityManager.RunningTaskInfo()
diff --git a/packages/SystemUI/tests/src/com/android/systemui/authentication/data/repository/AuthenticationRepositoryTest.kt b/packages/SystemUI/tests/src/com/android/systemui/authentication/data/repository/AuthenticationRepositoryTest.kt
index 0283382..6ac84bc 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/authentication/data/repository/AuthenticationRepositoryTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/authentication/data/repository/AuthenticationRepositoryTest.kt
@@ -21,6 +21,7 @@
import android.app.admin.DevicePolicyManager
import android.content.Intent
import android.content.pm.UserInfo
+import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.filters.SmallTest
import com.android.internal.widget.LockPatternUtils
import com.android.keyguard.KeyguardSecurityModel
@@ -40,13 +41,12 @@
import org.junit.Before
import org.junit.Test
import org.junit.runner.RunWith
-import org.junit.runners.JUnit4
import org.mockito.ArgumentMatchers.anyInt
import org.mockito.Mock
import org.mockito.MockitoAnnotations
@SmallTest
-@RunWith(JUnit4::class)
+@RunWith(AndroidJUnit4::class)
class AuthenticationRepositoryTest : SysuiTestCase() {
@Mock private lateinit var lockPatternUtils: LockPatternUtils
diff --git a/packages/SystemUI/tests/src/com/android/systemui/authentication/domain/interactor/AuthenticationInteractorTest.kt b/packages/SystemUI/tests/src/com/android/systemui/authentication/domain/interactor/AuthenticationInteractorTest.kt
index a102890..2f5f460 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/authentication/domain/interactor/AuthenticationInteractorTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/authentication/domain/interactor/AuthenticationInteractorTest.kt
@@ -17,6 +17,7 @@
package com.android.systemui.authentication.domain.interactor
import android.app.admin.DevicePolicyManager
+import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.filters.SmallTest
import com.android.systemui.SysuiTestCase
import com.android.systemui.authentication.data.model.AuthenticationMethodModel as DataLayerAuthenticationMethodModel
@@ -35,11 +36,10 @@
import kotlinx.coroutines.test.runTest
import org.junit.Test
import org.junit.runner.RunWith
-import org.junit.runners.JUnit4
@OptIn(ExperimentalCoroutinesApi::class)
@SmallTest
-@RunWith(JUnit4::class)
+@RunWith(AndroidJUnit4::class)
class AuthenticationInteractorTest : SysuiTestCase() {
private val utils = SceneTestUtils(this)
diff --git a/packages/SystemUI/tests/src/com/android/systemui/biometrics/AuthControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/biometrics/AuthControllerTest.java
index 2bc0171..885abcb 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/biometrics/AuthControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/biometrics/AuthControllerTest.java
@@ -17,12 +17,15 @@
package com.android.systemui.biometrics;
import static android.hardware.biometrics.BiometricAuthenticator.TYPE_FINGERPRINT;
+
import static com.google.common.truth.Truth.assertThat;
+
import static junit.framework.Assert.assertEquals;
import static junit.framework.Assert.assertFalse;
import static junit.framework.Assert.assertNotSame;
import static junit.framework.Assert.assertNull;
import static junit.framework.Assert.assertTrue;
+
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.anyLong;
@@ -79,7 +82,6 @@
import com.android.internal.R;
import com.android.internal.jank.InteractionJankMonitor;
import com.android.internal.widget.LockPatternUtils;
-import com.android.systemui.RoboPilotTest;
import com.android.systemui.SysuiTestCase;
import com.android.systemui.biometrics.domain.interactor.LogContextInteractor;
import com.android.systemui.biometrics.domain.interactor.PromptCredentialInteractor;
@@ -114,7 +116,6 @@
@RunWith(AndroidJUnit4.class)
@RunWithLooper
@SmallTest
-@RoboPilotTest
public class AuthControllerTest extends SysuiTestCase {
private static final long REQUEST_ID = 22;
diff --git a/packages/SystemUI/tests/src/com/android/systemui/biometrics/AuthDialogPanelInteractionDetectorTest.kt b/packages/SystemUI/tests/src/com/android/systemui/biometrics/AuthDialogPanelInteractionDetectorTest.kt
index 7365460..d68a313 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/biometrics/AuthDialogPanelInteractionDetectorTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/biometrics/AuthDialogPanelInteractionDetectorTest.kt
@@ -16,36 +16,18 @@
package com.android.systemui.biometrics
-import android.app.ActivityManager
-import android.os.UserManager
import androidx.test.filters.SmallTest
-import com.android.internal.logging.UiEventLogger
-import com.android.keyguard.KeyguardUpdateMonitor
+import com.android.SysUITestModule
import com.android.systemui.SysuiTestCase
-import com.android.systemui.common.ui.data.repository.FakeConfigurationRepository
-import com.android.systemui.flags.FakeFeatureFlags
+import com.android.systemui.dagger.SysUISingleton
+import com.android.systemui.flags.FakeFeatureFlagsClassicModule
import com.android.systemui.flags.Flags
-import com.android.systemui.keyguard.data.repository.FakeKeyguardRepository
-import com.android.systemui.keyguard.domain.interactor.KeyguardInteractorFactory
-import com.android.systemui.plugins.ActivityStarter
-import com.android.systemui.scene.SceneTestUtils
-import com.android.systemui.scene.shared.flag.FakeSceneContainerFlags
import com.android.systemui.shade.data.repository.FakeShadeRepository
-import com.android.systemui.shade.domain.interactor.ShadeInteractor
-import com.android.systemui.statusbar.disableflags.data.repository.FakeDisableFlagsRepository
-import com.android.systemui.statusbar.notification.stack.domain.interactor.SharedNotificationContainerInteractor
-import com.android.systemui.statusbar.pipeline.mobile.data.repository.FakeUserSetupRepository
-import com.android.systemui.statusbar.policy.DeviceProvisionedController
-import com.android.systemui.statusbar.policy.ResourcesSplitShadeStateController
-import com.android.systemui.telephony.data.repository.FakeTelephonyRepository
-import com.android.systemui.telephony.domain.interactor.TelephonyInteractor
-import com.android.systemui.user.data.repository.FakeUserRepository
-import com.android.systemui.user.domain.interactor.GuestUserInteractor
-import com.android.systemui.user.domain.interactor.HeadlessSystemUserMode
-import com.android.systemui.user.domain.interactor.RefreshUsersScheduler
-import com.android.systemui.user.domain.interactor.UserInteractor
-import com.android.systemui.util.mockito.mock
+import com.android.systemui.user.domain.UserDomainLayerModule
+import dagger.BindsInstance
+import dagger.Component
import kotlinx.coroutines.ExperimentalCoroutinesApi
+import kotlinx.coroutines.test.TestScope
import kotlinx.coroutines.test.runCurrent
import kotlinx.coroutines.test.runTest
import org.junit.Before
@@ -58,91 +40,27 @@
@SmallTest
@OptIn(ExperimentalCoroutinesApi::class)
class AuthDialogPanelInteractionDetectorTest : SysuiTestCase() {
- private val utils = SceneTestUtils(this)
- private val testScope = utils.testScope
- private val testDispatcher = utils.testDispatcher
- private val disableFlagsRepository = FakeDisableFlagsRepository()
- private val featureFlags = FakeFeatureFlags()
- private val keyguardRepository = FakeKeyguardRepository()
- private val shadeRepository = FakeShadeRepository()
- private val sceneContainerFlags = FakeSceneContainerFlags()
- private val sceneInteractor = utils.sceneInteractor()
- private val userSetupRepository = FakeUserSetupRepository()
- private val userRepository = FakeUserRepository()
- private val configurationRepository = FakeConfigurationRepository()
- private val sharedNotificationContainerInteractor =
- SharedNotificationContainerInteractor(
- configurationRepository,
- mContext,
- ResourcesSplitShadeStateController()
- )
- private lateinit var detector: AuthDialogPanelInteractionDetector
- private lateinit var shadeInteractor: ShadeInteractor
- private lateinit var userInteractor: UserInteractor
+ private val testComponent: TestComponent =
+ DaggerAuthDialogPanelInteractionDetectorTest_TestComponent.factory()
+ .create(
+ test = this,
+ featureFlags =
+ FakeFeatureFlagsClassicModule {
+ set(Flags.FACE_AUTH_REFACTOR, false)
+ set(Flags.FULL_SCREEN_USER_SWITCHER, true)
+ },
+ )
@Mock private lateinit var action: Runnable
- @Mock private lateinit var activityManager: ActivityManager
- @Mock private lateinit var activityStarter: ActivityStarter
- @Mock private lateinit var deviceProvisionedController: DeviceProvisionedController
- @Mock private lateinit var guestInteractor: GuestUserInteractor
- @Mock private lateinit var headlessSystemUserMode: HeadlessSystemUserMode
- @Mock private lateinit var keyguardUpdateMonitor: KeyguardUpdateMonitor
- @Mock private lateinit var manager: UserManager
- @Mock private lateinit var uiEventLogger: UiEventLogger
+
+ private val testScope = testComponent.testScope
+ private val shadeRepository = testComponent.shadeRepository
+ private val detector = testComponent.detector
@Before
fun setUp() {
MockitoAnnotations.initMocks(this)
-
- featureFlags.set(Flags.FACE_AUTH_REFACTOR, false)
- featureFlags.set(Flags.FULL_SCREEN_USER_SWITCHER, true)
-
- val refreshUsersScheduler =
- RefreshUsersScheduler(
- applicationScope = testScope.backgroundScope,
- mainDispatcher = testDispatcher,
- repository = userRepository,
- )
- userInteractor =
- UserInteractor(
- applicationContext = context,
- repository = userRepository,
- activityStarter = activityStarter,
- keyguardInteractor =
- KeyguardInteractorFactory.create(featureFlags = featureFlags)
- .keyguardInteractor,
- featureFlags = featureFlags,
- manager = manager,
- headlessSystemUserMode = headlessSystemUserMode,
- applicationScope = testScope.backgroundScope,
- telephonyInteractor =
- TelephonyInteractor(
- repository = FakeTelephonyRepository(),
- ),
- broadcastDispatcher = fakeBroadcastDispatcher,
- keyguardUpdateMonitor = keyguardUpdateMonitor,
- backgroundDispatcher = testDispatcher,
- activityManager = activityManager,
- refreshUsersScheduler = refreshUsersScheduler,
- guestUserInteractor = guestInteractor,
- uiEventLogger = uiEventLogger,
- userRestrictionChecker = mock(),
- )
- shadeInteractor =
- ShadeInteractor(
- testScope.backgroundScope,
- disableFlagsRepository,
- sceneContainerFlags,
- { sceneInteractor },
- keyguardRepository,
- userSetupRepository,
- deviceProvisionedController,
- userInteractor,
- sharedNotificationContainerInteractor,
- shadeRepository,
- )
- detector = AuthDialogPanelInteractionDetector(testScope, { shadeInteractor })
}
@Test
@@ -215,4 +133,27 @@
// Clean up job
detector.disable()
}
+
+ @SysUISingleton
+ @Component(
+ modules =
+ [
+ SysUITestModule::class,
+ UserDomainLayerModule::class,
+ ]
+ )
+ interface TestComponent {
+
+ val detector: AuthDialogPanelInteractionDetector
+ val shadeRepository: FakeShadeRepository
+ val testScope: TestScope
+
+ @Component.Factory
+ interface Factory {
+ fun create(
+ @BindsInstance test: SysuiTestCase,
+ featureFlags: FakeFeatureFlagsClassicModule,
+ ): TestComponent
+ }
+ }
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/biometrics/BiometricDisplayListenerTest.java b/packages/SystemUI/tests/src/com/android/systemui/biometrics/BiometricDisplayListenerTest.java
index 8547fa3..714461b 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/biometrics/BiometricDisplayListenerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/biometrics/BiometricDisplayListenerTest.java
@@ -38,7 +38,6 @@
import androidx.test.ext.junit.runners.AndroidJUnit4;
import androidx.test.filters.SmallTest;
-import com.android.systemui.RoboPilotTest;
import com.android.systemui.SysuiTestCase;
import kotlin.Unit;
@@ -53,7 +52,6 @@
import org.mockito.MockitoAnnotations;
@SmallTest
-@RoboPilotTest
@RunWith(AndroidJUnit4.class)
@RunWithLooper(setAsMainLooper = true)
public class BiometricDisplayListenerTest extends SysuiTestCase {
diff --git a/packages/SystemUI/tests/src/com/android/systemui/biometrics/FaceHelpMessageDeferralTest.kt b/packages/SystemUI/tests/src/com/android/systemui/biometrics/FaceHelpMessageDeferralTest.kt
index ab5d8bea5..39f0d57 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/biometrics/FaceHelpMessageDeferralTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/biometrics/FaceHelpMessageDeferralTest.kt
@@ -19,7 +19,6 @@
import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.filters.SmallTest
import com.android.keyguard.logging.BiometricMessageDeferralLogger
-import com.android.systemui.RoboPilotTest
import com.android.systemui.SysuiTestCase
import com.android.systemui.dump.DumpManager
import org.junit.Assert.assertEquals
@@ -34,7 +33,6 @@
import org.mockito.MockitoAnnotations
@SmallTest
-@RoboPilotTest
@RunWith(AndroidJUnit4::class)
class FaceHelpMessageDeferralTest : SysuiTestCase() {
val threshold = .75f
diff --git a/packages/SystemUI/tests/src/com/android/systemui/biometrics/SideFpsControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/biometrics/SideFpsControllerTest.kt
index 57cf834..ef06e0e 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/biometrics/SideFpsControllerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/biometrics/SideFpsControllerTest.kt
@@ -53,7 +53,6 @@
import com.airbnb.lottie.LottieAnimationView
import com.android.keyguard.KeyguardUpdateMonitor
import com.android.systemui.res.R
-import com.android.systemui.RoboPilotTest
import com.android.systemui.SysuiTestCase
import com.android.systemui.SysuiTestableContext
import com.android.systemui.biometrics.data.repository.FakeDisplayStateRepository
@@ -98,7 +97,6 @@
private const val REAR_DISPLAY_MODE_DEVICE_STATE = 3
@SmallTest
-@RoboPilotTest
@RunWith(AndroidJUnit4::class)
@TestableLooper.RunWithLooper
class SideFpsControllerTest : SysuiTestCase() {
diff --git a/packages/SystemUI/tests/src/com/android/systemui/biometrics/UdfpsBpViewControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/biometrics/UdfpsBpViewControllerTest.kt
index 469f65a..e2aa984 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/biometrics/UdfpsBpViewControllerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/biometrics/UdfpsBpViewControllerTest.kt
@@ -19,7 +19,6 @@
import android.testing.TestableLooper
import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.filters.SmallTest
-import com.android.systemui.RoboPilotTest
import com.android.systemui.SysuiTestCase
import com.android.systemui.bouncer.domain.interactor.PrimaryBouncerInteractor
import com.android.systemui.dump.DumpManager
@@ -35,7 +34,6 @@
import org.mockito.junit.MockitoJUnit
@SmallTest
-@RoboPilotTest
@RunWith(AndroidJUnit4::class)
@TestableLooper.RunWithLooper
class UdfpsBpViewControllerTest : SysuiTestCase() {
diff --git a/packages/SystemUI/tests/src/com/android/systemui/biometrics/UdfpsControllerOverlayTest.kt b/packages/SystemUI/tests/src/com/android/systemui/biometrics/UdfpsControllerOverlayTest.kt
index 21e614f..e9e9624 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/biometrics/UdfpsControllerOverlayTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/biometrics/UdfpsControllerOverlayTest.kt
@@ -38,7 +38,6 @@
import androidx.test.filters.SmallTest
import com.android.keyguard.KeyguardUpdateMonitor
import com.android.systemui.res.R
-import com.android.systemui.RoboPilotTest
import com.android.systemui.SysuiTestCase
import com.android.systemui.animation.ActivityLaunchAnimator
import com.android.systemui.biometrics.shared.model.UdfpsOverlayParams
@@ -83,7 +82,6 @@
@ExperimentalCoroutinesApi
@SmallTest
-@RoboPilotTest
@RunWith(AndroidJUnit4::class)
@RunWithLooper(setAsMainLooper = true)
class UdfpsControllerOverlayTest : SysuiTestCase() {
diff --git a/packages/SystemUI/tests/src/com/android/systemui/biometrics/UdfpsControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/biometrics/UdfpsControllerTest.java
index ee3bd0d..a36f4e9 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/biometrics/UdfpsControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/biometrics/UdfpsControllerTest.java
@@ -20,12 +20,15 @@
import static android.view.MotionEvent.ACTION_DOWN;
import static android.view.MotionEvent.ACTION_MOVE;
import static android.view.MotionEvent.ACTION_UP;
+
import static com.android.internal.util.FunctionalUtils.ThrowingConsumer;
import static com.android.systemui.classifier.Classifier.UDFPS_AUTHENTICATION;
import static com.android.systemui.flags.Flags.ONE_WAY_HAPTICS_API_MIGRATION;
+
import static junit.framework.Assert.assertEquals;
import static junit.framework.Assert.assertFalse;
import static junit.framework.Assert.assertTrue;
+
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyBoolean;
import static org.mockito.ArgumentMatchers.anyFloat;
@@ -74,8 +77,6 @@
import com.android.internal.logging.InstanceIdSequence;
import com.android.internal.util.LatencyTracker;
import com.android.keyguard.KeyguardUpdateMonitor;
-import com.android.systemui.res.R;
-import com.android.systemui.RoboPilotTest;
import com.android.systemui.SysuiTestCase;
import com.android.systemui.animation.ActivityLaunchAnimator;
import com.android.systemui.biometrics.shared.model.UdfpsOverlayParams;
@@ -94,6 +95,7 @@
import com.android.systemui.log.SessionTracker;
import com.android.systemui.plugins.FalsingManager;
import com.android.systemui.plugins.statusbar.StatusBarStateController;
+import com.android.systemui.res.R;
import com.android.systemui.statusbar.LockscreenShadeTransitionController;
import com.android.systemui.statusbar.VibratorHelper;
import com.android.systemui.statusbar.phone.StatusBarKeyguardViewManager;
@@ -125,7 +127,6 @@
import javax.inject.Provider;
@SmallTest
-@RoboPilotTest
@RunWith(AndroidJUnit4.class)
@RunWithLooper(setAsMainLooper = true)
public class UdfpsControllerTest extends SysuiTestCase {
diff --git a/packages/SystemUI/tests/src/com/android/systemui/biometrics/UdfpsDialogMeasureAdapterTest.java b/packages/SystemUI/tests/src/com/android/systemui/biometrics/UdfpsDialogMeasureAdapterTest.java
index 280bfdf..cd9189b 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/biometrics/UdfpsDialogMeasureAdapterTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/biometrics/UdfpsDialogMeasureAdapterTest.java
@@ -27,7 +27,6 @@
import androidx.test.ext.junit.runners.AndroidJUnit4;
import androidx.test.filters.SmallTest;
-import com.android.systemui.RoboPilotTest;
import com.android.systemui.SysuiTestCase;
import org.junit.Test;
@@ -38,7 +37,6 @@
@RunWith(AndroidJUnit4.class)
@SmallTest
-@RoboPilotTest
public class UdfpsDialogMeasureAdapterTest extends SysuiTestCase {
@Test
public void testUdfpsBottomSpacerHeightForPortrait() {
diff --git a/packages/SystemUI/tests/src/com/android/systemui/biometrics/UdfpsDisplayModeTest.java b/packages/SystemUI/tests/src/com/android/systemui/biometrics/UdfpsDisplayModeTest.java
index 1afb223..5239966 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/biometrics/UdfpsDisplayModeTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/biometrics/UdfpsDisplayModeTest.java
@@ -30,7 +30,6 @@
import androidx.test.ext.junit.runners.AndroidJUnit4;
import androidx.test.filters.SmallTest;
-import com.android.systemui.RoboPilotTest;
import com.android.systemui.SysuiTestCase;
import com.android.systemui.util.concurrency.FakeExecution;
@@ -41,7 +40,6 @@
import org.mockito.MockitoAnnotations;
@SmallTest
-@RoboPilotTest
@RunWith(AndroidJUnit4.class)
@RunWithLooper(setAsMainLooper = true)
public class UdfpsDisplayModeTest extends SysuiTestCase {
diff --git a/packages/SystemUI/tests/src/com/android/systemui/biometrics/UdfpsKeyguardViewLegacyControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/biometrics/UdfpsKeyguardViewLegacyControllerTest.java
index 8508f45..b018a3e 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/biometrics/UdfpsKeyguardViewLegacyControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/biometrics/UdfpsKeyguardViewLegacyControllerTest.java
@@ -31,14 +31,12 @@
import androidx.test.ext.junit.runners.AndroidJUnit4;
import androidx.test.filters.SmallTest;
-import com.android.systemui.RoboPilotTest;
import com.android.systemui.statusbar.StatusBarState;
import org.junit.Test;
import org.junit.runner.RunWith;
@SmallTest
-@RoboPilotTest
@RunWith(AndroidJUnit4.class)
@TestableLooper.RunWithLooper(setAsMainLooper = true)
diff --git a/packages/SystemUI/tests/src/com/android/systemui/biometrics/UdfpsKeyguardViewLegacyControllerWithCoroutinesTest.kt b/packages/SystemUI/tests/src/com/android/systemui/biometrics/UdfpsKeyguardViewLegacyControllerWithCoroutinesTest.kt
index 17f435b..da4548b 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/biometrics/UdfpsKeyguardViewLegacyControllerWithCoroutinesTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/biometrics/UdfpsKeyguardViewLegacyControllerWithCoroutinesTest.kt
@@ -21,7 +21,6 @@
import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.filters.SmallTest
import com.android.keyguard.KeyguardSecurityModel
-import com.android.systemui.RoboPilotTest
import com.android.systemui.bouncer.data.repository.KeyguardBouncerRepository
import com.android.systemui.bouncer.data.repository.KeyguardBouncerRepositoryImpl
import com.android.systemui.bouncer.domain.interactor.AlternateBouncerInteractor
@@ -58,7 +57,6 @@
@RunWith(AndroidJUnit4::class)
@SmallTest
-@RoboPilotTest
@TestableLooper.RunWithLooper
@kotlinx.coroutines.ExperimentalCoroutinesApi
class UdfpsKeyguardViewLegacyControllerWithCoroutinesTest :
diff --git a/packages/SystemUI/tests/src/com/android/systemui/biometrics/UdfpsShellTest.kt b/packages/SystemUI/tests/src/com/android/systemui/biometrics/UdfpsShellTest.kt
index 6d55254..8b374ae 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/biometrics/UdfpsShellTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/biometrics/UdfpsShellTest.kt
@@ -21,7 +21,6 @@
import android.view.MotionEvent
import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.filters.SmallTest
-import com.android.systemui.RoboPilotTest
import com.android.systemui.SysuiTestCase
import com.android.systemui.biometrics.UdfpsController.UdfpsOverlayController
import com.android.systemui.statusbar.commandline.CommandRegistry
@@ -40,7 +39,6 @@
import org.mockito.junit.MockitoJUnit
@SmallTest
-@RoboPilotTest
@RunWith(AndroidJUnit4::class)
@TestableLooper.RunWithLooper
class UdfpsShellTest : SysuiTestCase() {
diff --git a/packages/SystemUI/tests/src/com/android/systemui/biometrics/UdfpsViewTest.kt b/packages/SystemUI/tests/src/com/android/systemui/biometrics/UdfpsViewTest.kt
index ebadfc7..0c8e7a5 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/biometrics/UdfpsViewTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/biometrics/UdfpsViewTest.kt
@@ -26,7 +26,6 @@
import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.filters.SmallTest
import com.android.systemui.res.R
-import com.android.systemui.RoboPilotTest
import com.android.systemui.SysuiTestCase
import com.android.systemui.biometrics.shared.model.UdfpsOverlayParams
import com.android.systemui.util.mockito.any
@@ -50,7 +49,6 @@
private const val SENSOR_RADIUS = 10
@SmallTest
-@RoboPilotTest
@RunWith(AndroidJUnit4::class)
@TestableLooper.RunWithLooper
class UdfpsViewTest : SysuiTestCase() {
diff --git a/packages/SystemUI/tests/src/com/android/systemui/bouncer/domain/interactor/AlternateBouncerInteractorTest.kt b/packages/SystemUI/tests/src/com/android/systemui/bouncer/domain/interactor/AlternateBouncerInteractorTest.kt
index 0d17270..2d8adca 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/bouncer/domain/interactor/AlternateBouncerInteractorTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/bouncer/domain/interactor/AlternateBouncerInteractorTest.kt
@@ -19,7 +19,6 @@
import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.filters.SmallTest
import com.android.keyguard.KeyguardUpdateMonitor
-import com.android.systemui.RoboPilotTest
import com.android.systemui.SysuiTestCase
import com.android.systemui.bouncer.data.repository.KeyguardBouncerRepository
import com.android.systemui.bouncer.data.repository.KeyguardBouncerRepositoryImpl
@@ -43,7 +42,6 @@
@OptIn(ExperimentalCoroutinesApi::class)
@SmallTest
-@RoboPilotTest
@RunWith(AndroidJUnit4::class)
class AlternateBouncerInteractorTest : SysuiTestCase() {
private lateinit var underTest: AlternateBouncerInteractor
diff --git a/packages/SystemUI/tests/src/com/android/systemui/bouncer/domain/interactor/BouncerInteractorTest.kt b/packages/SystemUI/tests/src/com/android/systemui/bouncer/domain/interactor/BouncerInteractorTest.kt
index a9ba36a..915661b 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/bouncer/domain/interactor/BouncerInteractorTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/bouncer/domain/interactor/BouncerInteractorTest.kt
@@ -16,6 +16,7 @@
package com.android.systemui.bouncer.domain.interactor
+import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.filters.SmallTest
import com.android.systemui.SysuiTestCase
import com.android.systemui.authentication.data.model.AuthenticationMethodModel
@@ -38,11 +39,10 @@
import org.junit.Before
import org.junit.Test
import org.junit.runner.RunWith
-import org.junit.runners.JUnit4
@OptIn(ExperimentalCoroutinesApi::class)
@SmallTest
-@RunWith(JUnit4::class)
+@RunWith(AndroidJUnit4::class)
class BouncerInteractorTest : SysuiTestCase() {
private val utils = SceneTestUtils(this)
diff --git a/packages/SystemUI/tests/src/com/android/systemui/bouncer/domain/interactor/PrimaryBouncerCallbackInteractorTest.kt b/packages/SystemUI/tests/src/com/android/systemui/bouncer/domain/interactor/PrimaryBouncerCallbackInteractorTest.kt
index a81ca86..4aea4f3 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/bouncer/domain/interactor/PrimaryBouncerCallbackInteractorTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/bouncer/domain/interactor/PrimaryBouncerCallbackInteractorTest.kt
@@ -19,7 +19,6 @@
import android.view.View
import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.filters.SmallTest
-import com.android.systemui.RoboPilotTest
import com.android.systemui.SysuiTestCase
import org.junit.Before
import org.junit.Test
@@ -29,7 +28,6 @@
import org.mockito.MockitoAnnotations
@SmallTest
-@RoboPilotTest
@RunWith(AndroidJUnit4::class)
class PrimaryBouncerCallbackInteractorTest : SysuiTestCase() {
private val mPrimaryBouncerCallbackInteractor = PrimaryBouncerCallbackInteractor()
diff --git a/packages/SystemUI/tests/src/com/android/systemui/bouncer/domain/interactor/PrimaryBouncerInteractorWithCoroutinesTest.kt b/packages/SystemUI/tests/src/com/android/systemui/bouncer/domain/interactor/PrimaryBouncerInteractorWithCoroutinesTest.kt
index cb0b74f..2018e61 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/bouncer/domain/interactor/PrimaryBouncerInteractorWithCoroutinesTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/bouncer/domain/interactor/PrimaryBouncerInteractorWithCoroutinesTest.kt
@@ -21,7 +21,6 @@
import androidx.test.filters.SmallTest
import com.android.keyguard.KeyguardSecurityModel
import com.android.keyguard.KeyguardUpdateMonitor
-import com.android.systemui.RoboPilotTest
import com.android.systemui.SysuiTestCase
import com.android.systemui.bouncer.data.repository.FakeKeyguardBouncerRepository
import com.android.systemui.bouncer.ui.BouncerView
@@ -43,7 +42,6 @@
import org.mockito.MockitoAnnotations
@SmallTest
-@RoboPilotTest
@RunWith(AndroidJUnit4::class)
class PrimaryBouncerInteractorWithCoroutinesTest : SysuiTestCase() {
private lateinit var repository: FakeKeyguardBouncerRepository
diff --git a/packages/SystemUI/tests/src/com/android/systemui/bouncer/ui/viewmodel/AuthMethodBouncerViewModelTest.kt b/packages/SystemUI/tests/src/com/android/systemui/bouncer/ui/viewmodel/AuthMethodBouncerViewModelTest.kt
index b5177e1..8e1f5ac 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/bouncer/ui/viewmodel/AuthMethodBouncerViewModelTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/bouncer/ui/viewmodel/AuthMethodBouncerViewModelTest.kt
@@ -16,6 +16,7 @@
package com.android.systemui.bouncer.ui.viewmodel
+import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.filters.SmallTest
import com.android.systemui.SysuiTestCase
import com.android.systemui.authentication.data.model.AuthenticationMethodModel
@@ -29,10 +30,9 @@
import kotlinx.coroutines.test.runTest
import org.junit.Test
import org.junit.runner.RunWith
-import org.junit.runners.JUnit4
@SmallTest
-@RunWith(JUnit4::class)
+@RunWith(AndroidJUnit4::class)
class AuthMethodBouncerViewModelTest : SysuiTestCase() {
private val utils = SceneTestUtils(this)
diff --git a/packages/SystemUI/tests/src/com/android/systemui/bouncer/ui/viewmodel/BouncerViewModelTest.kt b/packages/SystemUI/tests/src/com/android/systemui/bouncer/ui/viewmodel/BouncerViewModelTest.kt
index b75355a..2c97809 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/bouncer/ui/viewmodel/BouncerViewModelTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/bouncer/ui/viewmodel/BouncerViewModelTest.kt
@@ -16,6 +16,7 @@
package com.android.systemui.bouncer.ui.viewmodel
+import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.filters.SmallTest
import com.android.systemui.SysuiTestCase
import com.android.systemui.authentication.data.model.AuthenticationMethodModel as DataLayerAuthenticationMethodModel
@@ -35,11 +36,10 @@
import kotlinx.coroutines.test.runTest
import org.junit.Test
import org.junit.runner.RunWith
-import org.junit.runners.JUnit4
@OptIn(ExperimentalCoroutinesApi::class)
@SmallTest
-@RunWith(JUnit4::class)
+@RunWith(AndroidJUnit4::class)
class BouncerViewModelTest : SysuiTestCase() {
private val utils = SceneTestUtils(this)
diff --git a/packages/SystemUI/tests/src/com/android/systemui/bouncer/ui/viewmodel/KeyguardBouncerViewModelTest.kt b/packages/SystemUI/tests/src/com/android/systemui/bouncer/ui/viewmodel/KeyguardBouncerViewModelTest.kt
index 333bd21..802f8e6 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/bouncer/ui/viewmodel/KeyguardBouncerViewModelTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/bouncer/ui/viewmodel/KeyguardBouncerViewModelTest.kt
@@ -21,7 +21,6 @@
import androidx.test.filters.SmallTest
import com.android.keyguard.KeyguardSecurityModel
import com.android.keyguard.KeyguardUpdateMonitor
-import com.android.systemui.RoboPilotTest
import com.android.systemui.SysuiTestCase
import com.android.systemui.bouncer.data.repository.FakeKeyguardBouncerRepository
import com.android.systemui.bouncer.domain.interactor.PrimaryBouncerCallbackInteractor
@@ -50,7 +49,6 @@
import org.mockito.MockitoAnnotations
@SmallTest
-@RoboPilotTest
@RunWith(AndroidJUnit4::class)
@kotlinx.coroutines.ExperimentalCoroutinesApi
class KeyguardBouncerViewModelTest : SysuiTestCase() {
diff --git a/packages/SystemUI/tests/src/com/android/systemui/bouncer/ui/viewmodel/PasswordBouncerViewModelTest.kt b/packages/SystemUI/tests/src/com/android/systemui/bouncer/ui/viewmodel/PasswordBouncerViewModelTest.kt
index 0926399..ba8dcef 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/bouncer/ui/viewmodel/PasswordBouncerViewModelTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/bouncer/ui/viewmodel/PasswordBouncerViewModelTest.kt
@@ -16,6 +16,7 @@
package com.android.systemui.bouncer.ui.viewmodel
+import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.filters.SmallTest
import com.android.systemui.SysuiTestCase
import com.android.systemui.authentication.data.model.AuthenticationMethodModel
@@ -35,11 +36,10 @@
import org.junit.Before
import org.junit.Test
import org.junit.runner.RunWith
-import org.junit.runners.JUnit4
@OptIn(ExperimentalCoroutinesApi::class)
@SmallTest
-@RunWith(JUnit4::class)
+@RunWith(AndroidJUnit4::class)
class PasswordBouncerViewModelTest : SysuiTestCase() {
private val utils = SceneTestUtils(this)
diff --git a/packages/SystemUI/tests/src/com/android/systemui/bouncer/ui/viewmodel/PatternBouncerViewModelTest.kt b/packages/SystemUI/tests/src/com/android/systemui/bouncer/ui/viewmodel/PatternBouncerViewModelTest.kt
index 2e7c9aa..bfaa6ed 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/bouncer/ui/viewmodel/PatternBouncerViewModelTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/bouncer/ui/viewmodel/PatternBouncerViewModelTest.kt
@@ -16,6 +16,7 @@
package com.android.systemui.bouncer.ui.viewmodel
+import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.filters.SmallTest
import com.android.systemui.SysuiTestCase
import com.android.systemui.authentication.data.model.AuthenticationMethodModel
@@ -38,11 +39,10 @@
import org.junit.Before
import org.junit.Test
import org.junit.runner.RunWith
-import org.junit.runners.JUnit4
@OptIn(ExperimentalCoroutinesApi::class)
@SmallTest
-@RunWith(JUnit4::class)
+@RunWith(AndroidJUnit4::class)
class PatternBouncerViewModelTest : SysuiTestCase() {
private val utils = SceneTestUtils(this)
diff --git a/packages/SystemUI/tests/src/com/android/systemui/bouncer/ui/viewmodel/PinBouncerViewModelTest.kt b/packages/SystemUI/tests/src/com/android/systemui/bouncer/ui/viewmodel/PinBouncerViewModelTest.kt
index 255bbe3..7873899 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/bouncer/ui/viewmodel/PinBouncerViewModelTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/bouncer/ui/viewmodel/PinBouncerViewModelTest.kt
@@ -16,6 +16,7 @@
package com.android.systemui.bouncer.ui.viewmodel
+import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.filters.SmallTest
import com.android.systemui.SysuiTestCase
import com.android.systemui.authentication.data.model.AuthenticationMethodModel
@@ -37,11 +38,10 @@
import org.junit.Before
import org.junit.Test
import org.junit.runner.RunWith
-import org.junit.runners.JUnit4
@OptIn(ExperimentalCoroutinesApi::class)
@SmallTest
-@RunWith(JUnit4::class)
+@RunWith(AndroidJUnit4::class)
class PinBouncerViewModelTest : SysuiTestCase() {
private val utils = SceneTestUtils(this)
@@ -92,7 +92,7 @@
underTest.onShown()
- assertThat(message?.text).isEqualTo(ENTER_YOUR_PIN)
+ assertThat(message?.text).ignoringCase().isEqualTo(ENTER_YOUR_PIN)
assertThat(pin).isEmpty()
assertThat(currentScene).isEqualTo(SceneModel(SceneKey.Bouncer))
assertThat(underTest.authenticationMethod)
@@ -209,7 +209,7 @@
underTest.onAuthenticateButtonClicked()
assertThat(pin).isEmpty()
- assertThat(message?.text).isEqualTo(WRONG_PIN)
+ assertThat(message?.text).ignoringCase().isEqualTo(WRONG_PIN)
assertThat(currentScene).isEqualTo(SceneModel(SceneKey.Bouncer))
}
@@ -227,7 +227,7 @@
underTest.onPinButtonClicked(4)
underTest.onPinButtonClicked(5) // PIN is now wrong!
underTest.onAuthenticateButtonClicked()
- assertThat(message?.text).isEqualTo(WRONG_PIN)
+ assertThat(message?.text).ignoringCase().isEqualTo(WRONG_PIN)
assertThat(pin).isEmpty()
assertThat(currentScene).isEqualTo(SceneModel(SceneKey.Bouncer))
@@ -273,7 +273,7 @@
) // PIN is now wrong!
assertThat(pin).isEmpty()
- assertThat(message?.text).isEqualTo(WRONG_PIN)
+ assertThat(message?.text).ignoringCase().isEqualTo(WRONG_PIN)
assertThat(currentScene).isEqualTo(SceneModel(SceneKey.Bouncer))
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/bouncer/ui/viewmodel/PinInputViewModelTest.kt b/packages/SystemUI/tests/src/com/android/systemui/bouncer/ui/viewmodel/PinInputViewModelTest.kt
index 4c279ea..55016bb 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/bouncer/ui/viewmodel/PinInputViewModelTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/bouncer/ui/viewmodel/PinInputViewModelTest.kt
@@ -1,5 +1,6 @@
package com.android.systemui.bouncer.ui.viewmodel
+import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.filters.SmallTest
import com.android.systemui.SysuiTestCase
import com.android.systemui.bouncer.ui.viewmodel.EntryToken.ClearAll
@@ -16,14 +17,13 @@
import org.junit.Assert.assertThrows
import org.junit.Test
import org.junit.runner.RunWith
-import org.junit.runners.JUnit4
/**
* This test uses a mnemonic code to create and verify PinInput instances: strings of digits [0-9]
* for [Digit] tokens, as well as a `C` for the [ClearAll] token.
*/
@SmallTest
-@RunWith(JUnit4::class)
+@RunWith(AndroidJUnit4::class)
class PinInputViewModelTest : SysuiTestCase() {
@Test
diff --git a/packages/SystemUI/tests/src/com/android/systemui/communal/data/repository/CommunalWidgetRepositoryImplTest.kt b/packages/SystemUI/tests/src/com/android/systemui/communal/data/repository/CommunalWidgetRepositoryImplTest.kt
index 7fa828f..3df9cbb 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/communal/data/repository/CommunalWidgetRepositoryImplTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/communal/data/repository/CommunalWidgetRepositoryImplTest.kt
@@ -9,7 +9,6 @@
import android.os.UserManager
import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.filters.SmallTest
-import com.android.systemui.RoboPilotTest
import com.android.systemui.SysuiTestCase
import com.android.systemui.broadcast.BroadcastDispatcher
import com.android.systemui.coroutines.collectLastValue
@@ -40,7 +39,6 @@
@OptIn(ExperimentalCoroutinesApi::class)
@SmallTest
-@RoboPilotTest
@RunWith(AndroidJUnit4::class)
class CommunalWidgetRepositoryImplTest : SysuiTestCase() {
@Mock private lateinit var appWidgetManager: AppWidgetManager
diff --git a/packages/SystemUI/tests/src/com/android/systemui/communal/domain/interactor/CommunalInteractorTest.kt b/packages/SystemUI/tests/src/com/android/systemui/communal/domain/interactor/CommunalInteractorTest.kt
index ddf788e..cdc42e0 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/communal/domain/interactor/CommunalInteractorTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/communal/domain/interactor/CommunalInteractorTest.kt
@@ -19,7 +19,6 @@
import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.filters.SmallTest
-import com.android.systemui.RoboPilotTest
import com.android.systemui.SysuiTestCase
import com.android.systemui.communal.data.repository.FakeCommunalRepository
import com.android.systemui.communal.data.repository.FakeCommunalWidgetRepository
@@ -37,7 +36,6 @@
import org.mockito.MockitoAnnotations
@SmallTest
-@RoboPilotTest
@OptIn(ExperimentalCoroutinesApi::class)
@RunWith(AndroidJUnit4::class)
class CommunalInteractorTest : SysuiTestCase() {
diff --git a/packages/SystemUI/tests/src/com/android/systemui/communal/ui/view/layout/blueprints/DefaultCommunalBlueprintTest.kt b/packages/SystemUI/tests/src/com/android/systemui/communal/ui/view/layout/blueprints/DefaultCommunalBlueprintTest.kt
index a10eb29..41a8be9 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/communal/ui/view/layout/blueprints/DefaultCommunalBlueprintTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/communal/ui/view/layout/blueprints/DefaultCommunalBlueprintTest.kt
@@ -5,7 +5,6 @@
import androidx.constraintlayout.widget.ConstraintSet
import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.filters.SmallTest
-import com.android.systemui.RoboPilotTest
import com.android.systemui.SysuiTestCase
import com.android.systemui.communal.ui.view.layout.sections.DefaultCommunalWidgetSection
import org.junit.Before
@@ -15,7 +14,6 @@
import org.mockito.Mockito.verify
import org.mockito.MockitoAnnotations
-@RoboPilotTest
@RunWith(AndroidJUnit4::class)
@TestableLooper.RunWithLooper(setAsMainLooper = true)
@SmallTest
diff --git a/packages/SystemUI/tests/src/com/android/systemui/deviceentry/data/repository/DeviceEntryRepositoryTest.kt b/packages/SystemUI/tests/src/com/android/systemui/deviceentry/data/repository/DeviceEntryRepositoryTest.kt
index 8e8cbe4..679dfef 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/deviceentry/data/repository/DeviceEntryRepositoryTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/deviceentry/data/repository/DeviceEntryRepositoryTest.kt
@@ -1,6 +1,7 @@
package com.android.systemui.deviceentry.data.repository
import android.content.pm.UserInfo
+import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.filters.SmallTest
import com.android.internal.widget.LockPatternUtils
import com.android.systemui.SysuiTestCase
@@ -19,14 +20,13 @@
import org.junit.Before
import org.junit.Test
import org.junit.runner.RunWith
-import org.junit.runners.JUnit4
import org.mockito.Mock
import org.mockito.Mockito
import org.mockito.MockitoAnnotations
@OptIn(ExperimentalCoroutinesApi::class)
@SmallTest
-@RunWith(JUnit4::class)
+@RunWith(AndroidJUnit4::class)
class DeviceEntryRepositoryTest : SysuiTestCase() {
@Mock private lateinit var lockPatternUtils: LockPatternUtils
diff --git a/packages/SystemUI/tests/src/com/android/systemui/deviceentry/domain/interactor/DeviceEntryInteractorTest.kt b/packages/SystemUI/tests/src/com/android/systemui/deviceentry/domain/interactor/DeviceEntryInteractorTest.kt
index 55582e1..c4cd8a4 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/deviceentry/domain/interactor/DeviceEntryInteractorTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/deviceentry/domain/interactor/DeviceEntryInteractorTest.kt
@@ -1,5 +1,6 @@
package com.android.systemui.deviceentry.domain.interactor
+import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.filters.SmallTest
import com.android.systemui.SysuiTestCase
import com.android.systemui.authentication.data.model.AuthenticationMethodModel
@@ -14,11 +15,10 @@
import kotlinx.coroutines.test.runTest
import org.junit.Test
import org.junit.runner.RunWith
-import org.junit.runners.JUnit4
@OptIn(ExperimentalCoroutinesApi::class)
@SmallTest
-@RunWith(JUnit4::class)
+@RunWith(AndroidJUnit4::class)
class DeviceEntryInteractorTest : SysuiTestCase() {
private val utils = SceneTestUtils(this)
diff --git a/packages/SystemUI/tests/src/com/android/systemui/dreams/DreamOverlayAnimationsControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/dreams/DreamOverlayAnimationsControllerTest.kt
index 781ad6b..8a35ef1 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/dreams/DreamOverlayAnimationsControllerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/dreams/DreamOverlayAnimationsControllerTest.kt
@@ -6,7 +6,6 @@
import android.view.View
import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.filters.SmallTest
-import com.android.systemui.RoboPilotTest
import com.android.systemui.SysuiTestCase
import com.android.systemui.complication.ComplicationHostViewController
import com.android.systemui.keyguard.ui.viewmodel.DreamingToLockscreenTransitionViewModel
@@ -30,7 +29,6 @@
import org.mockito.Mockito.verify
import org.mockito.MockitoAnnotations
-@RoboPilotTest
@SmallTest
@RunWith(AndroidJUnit4::class)
class DreamOverlayAnimationsControllerTest : SysuiTestCase() {
diff --git a/packages/SystemUI/tests/src/com/android/systemui/dreams/DreamOverlayCallbackControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/dreams/DreamOverlayCallbackControllerTest.kt
index 21192fa..2c6c793 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/dreams/DreamOverlayCallbackControllerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/dreams/DreamOverlayCallbackControllerTest.kt
@@ -17,7 +17,6 @@
import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.filters.SmallTest
-import com.android.systemui.RoboPilotTest
import com.android.systemui.SysuiTestCase
import com.google.common.truth.Truth.assertThat
import org.junit.Before
@@ -30,7 +29,6 @@
import org.mockito.Mockito.verify
import org.mockito.MockitoAnnotations
-@RoboPilotTest
@SmallTest
@RunWith(AndroidJUnit4::class)
class DreamOverlayCallbackControllerTest : SysuiTestCase() {
diff --git a/packages/SystemUI/tests/src/com/android/systemui/dreams/DreamOverlayContainerViewControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/dreams/DreamOverlayContainerViewControllerTest.java
index 7c36642..2af6566 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/dreams/DreamOverlayContainerViewControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/dreams/DreamOverlayContainerViewControllerTest.java
@@ -38,7 +38,6 @@
import com.android.dream.lowlight.LowLightTransitionCoordinator;
import com.android.keyguard.BouncerPanelExpansionCalculator;
-import com.android.systemui.RoboPilotTest;
import com.android.systemui.SysuiTestCase;
import com.android.systemui.bouncer.domain.interactor.PrimaryBouncerCallbackInteractor;
import com.android.systemui.bouncer.domain.interactor.PrimaryBouncerCallbackInteractor.PrimaryBouncerExpansionCallback;
@@ -53,7 +52,6 @@
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
-@RoboPilotTest
@SmallTest
@RunWith(AndroidJUnit4.class)
public class DreamOverlayContainerViewControllerTest extends SysuiTestCase {
diff --git a/packages/SystemUI/tests/src/com/android/systemui/dreams/DreamOverlayNotificationCountProviderTest.java b/packages/SystemUI/tests/src/com/android/systemui/dreams/DreamOverlayNotificationCountProviderTest.java
index be7638e..d379dc6 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/dreams/DreamOverlayNotificationCountProviderTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/dreams/DreamOverlayNotificationCountProviderTest.java
@@ -26,7 +26,6 @@
import androidx.test.ext.junit.runners.AndroidJUnit4;
import androidx.test.filters.SmallTest;
-import com.android.systemui.RoboPilotTest;
import com.android.systemui.SysuiTestCase;
import com.android.systemui.statusbar.NotificationListener;
import com.android.systemui.statusbar.NotificationListener.NotificationHandler;
@@ -38,7 +37,6 @@
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
-@RoboPilotTest
@SmallTest
@RunWith(AndroidJUnit4.class)
public class DreamOverlayNotificationCountProviderTest extends SysuiTestCase {
diff --git a/packages/SystemUI/tests/src/com/android/systemui/dreams/DreamOverlayServiceTest.java b/packages/SystemUI/tests/src/com/android/systemui/dreams/DreamOverlayServiceTest.java
index 8379f73..e5f9972 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/dreams/DreamOverlayServiceTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/dreams/DreamOverlayServiceTest.java
@@ -49,7 +49,6 @@
import com.android.internal.logging.UiEventLogger;
import com.android.keyguard.KeyguardUpdateMonitor;
-import com.android.systemui.RoboPilotTest;
import com.android.systemui.SysuiTestCase;
import com.android.systemui.complication.ComplicationLayoutEngine;
import com.android.systemui.dreams.complication.HideComplicationTouchHandler;
@@ -72,7 +71,6 @@
import org.mockito.Mockito;
import org.mockito.MockitoAnnotations;
-@RoboPilotTest
@SmallTest
@RunWith(AndroidJUnit4.class)
public class DreamOverlayServiceTest extends SysuiTestCase {
diff --git a/packages/SystemUI/tests/src/com/android/systemui/dreams/DreamOverlayStateControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/dreams/DreamOverlayStateControllerTest.java
index 2ef227c..365f67b 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/dreams/DreamOverlayStateControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/dreams/DreamOverlayStateControllerTest.java
@@ -29,7 +29,6 @@
import androidx.test.ext.junit.runners.AndroidJUnit4;
import androidx.test.filters.SmallTest;
-import com.android.systemui.RoboPilotTest;
import com.android.systemui.SysuiTestCase;
import com.android.systemui.complication.Complication;
import com.android.systemui.flags.FeatureFlags;
@@ -48,7 +47,6 @@
import java.util.Collection;
-@RoboPilotTest
@SmallTest
@RunWith(AndroidJUnit4.class)
public class DreamOverlayStateControllerTest extends SysuiTestCase {
diff --git a/packages/SystemUI/tests/src/com/android/systemui/dreams/DreamOverlayStatusBarItemsProviderTest.java b/packages/SystemUI/tests/src/com/android/systemui/dreams/DreamOverlayStatusBarItemsProviderTest.java
index 12cb332..7ff345c 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/dreams/DreamOverlayStatusBarItemsProviderTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/dreams/DreamOverlayStatusBarItemsProviderTest.java
@@ -24,7 +24,6 @@
import androidx.test.ext.junit.runners.AndroidJUnit4;
import androidx.test.filters.SmallTest;
-import com.android.systemui.RoboPilotTest;
import com.android.systemui.SysuiTestCase;
import org.junit.Before;
@@ -36,7 +35,6 @@
import java.util.List;
import java.util.concurrent.Executor;
-@RoboPilotTest
@SmallTest
@RunWith(AndroidJUnit4.class)
public class DreamOverlayStatusBarItemsProviderTest extends SysuiTestCase {
diff --git a/packages/SystemUI/tests/src/com/android/systemui/dreams/DreamOverlayStatusBarViewControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/dreams/DreamOverlayStatusBarViewControllerTest.java
index 9566e81..39db2be 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/dreams/DreamOverlayStatusBarViewControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/dreams/DreamOverlayStatusBarViewControllerTest.java
@@ -46,11 +46,10 @@
import androidx.test.ext.junit.runners.AndroidJUnit4;
import androidx.test.filters.SmallTest;
-import com.android.systemui.res.R;
-import com.android.systemui.RoboPilotTest;
import com.android.systemui.SysuiTestCase;
import com.android.systemui.log.LogBuffer;
import com.android.systemui.log.core.FakeLogBuffer;
+import com.android.systemui.res.R;
import com.android.systemui.settings.UserTracker;
import com.android.systemui.statusbar.policy.IndividualSensorPrivacyController;
import com.android.systemui.statusbar.policy.NextAlarmController;
@@ -72,7 +71,6 @@
import java.util.Optional;
import java.util.concurrent.Executor;
-@RoboPilotTest
@SmallTest
@RunWith(AndroidJUnit4.class)
public class DreamOverlayStatusBarViewControllerTest extends SysuiTestCase {
diff --git a/packages/SystemUI/tests/src/com/android/systemui/dreams/complication/HideComplicationTouchHandlerTest.java b/packages/SystemUI/tests/src/com/android/systemui/dreams/complication/HideComplicationTouchHandlerTest.java
index d32788d..315a24b 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/dreams/complication/HideComplicationTouchHandlerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/dreams/complication/HideComplicationTouchHandlerTest.java
@@ -30,7 +30,6 @@
import androidx.test.ext.junit.runners.AndroidJUnit4;
import androidx.test.filters.SmallTest;
-import com.android.systemui.RoboPilotTest;
import com.android.systemui.SysuiTestCase;
import com.android.systemui.complication.Complication;
import com.android.systemui.dreams.DreamOverlayStateController;
@@ -49,7 +48,6 @@
import org.mockito.Mockito;
import org.mockito.MockitoAnnotations;
-@RoboPilotTest
@SmallTest
@RunWith(AndroidJUnit4.class)
public class HideComplicationTouchHandlerTest extends SysuiTestCase {
diff --git a/packages/SystemUI/tests/src/com/android/systemui/dreams/conditions/AssistantAttentionConditionTest.java b/packages/SystemUI/tests/src/com/android/systemui/dreams/conditions/AssistantAttentionConditionTest.java
index 4a7700f..e0c6ab2 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/dreams/conditions/AssistantAttentionConditionTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/dreams/conditions/AssistantAttentionConditionTest.java
@@ -26,7 +26,6 @@
import androidx.test.ext.junit.runners.AndroidJUnit4;
import androidx.test.filters.SmallTest;
-import com.android.systemui.RoboPilotTest;
import com.android.systemui.SysuiTestCase;
import com.android.systemui.assist.AssistManager;
import com.android.systemui.assist.AssistManager.VisualQueryAttentionListener;
@@ -41,7 +40,6 @@
import kotlinx.coroutines.CoroutineScope;
-@RoboPilotTest
@SmallTest
@RunWith(AndroidJUnit4.class)
public class AssistantAttentionConditionTest extends SysuiTestCase {
diff --git a/packages/SystemUI/tests/src/com/android/systemui/dreams/conditions/DreamConditionTest.java b/packages/SystemUI/tests/src/com/android/systemui/dreams/conditions/DreamConditionTest.java
index cd2efde..480754c 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/dreams/conditions/DreamConditionTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/dreams/conditions/DreamConditionTest.java
@@ -31,7 +31,6 @@
import com.android.keyguard.KeyguardUpdateMonitor;
import com.android.keyguard.KeyguardUpdateMonitorCallback;
-import com.android.systemui.RoboPilotTest;
import com.android.systemui.SysuiTestCase;
import com.android.systemui.shared.condition.Condition;
@@ -44,7 +43,6 @@
import kotlinx.coroutines.CoroutineScope;
-@RoboPilotTest
@SmallTest
@RunWith(AndroidJUnit4.class)
public class DreamConditionTest extends SysuiTestCase {
diff --git a/packages/SystemUI/tests/src/com/android/systemui/dreams/touch/BouncerSwipeTouchHandlerTest.java b/packages/SystemUI/tests/src/com/android/systemui/dreams/touch/BouncerSwipeTouchHandlerTest.java
index ffcaeee..3d1efa5 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/dreams/touch/BouncerSwipeTouchHandlerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/dreams/touch/BouncerSwipeTouchHandlerTest.java
@@ -17,6 +17,7 @@
package com.android.systemui.dreams.touch;
import static com.google.common.truth.Truth.assertThat;
+
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyFloat;
import static org.mockito.ArgumentMatchers.eq;
@@ -40,7 +41,6 @@
import com.android.internal.logging.UiEventLogger;
import com.android.internal.widget.LockPatternUtils;
-import com.android.systemui.RoboPilotTest;
import com.android.systemui.SysuiTestCase;
import com.android.systemui.bouncer.shared.constants.KeyguardBouncerConstants;
import com.android.systemui.dreams.touch.scrim.ScrimController;
@@ -64,7 +64,6 @@
import java.util.Collections;
import java.util.Optional;
-@RoboPilotTest
@SmallTest
@RunWith(AndroidJUnit4.class)
public class BouncerSwipeTouchHandlerTest extends SysuiTestCase {
diff --git a/packages/SystemUI/tests/src/com/android/systemui/dreams/touch/ShadeTouchHandlerTest.java b/packages/SystemUI/tests/src/com/android/systemui/dreams/touch/ShadeTouchHandlerTest.java
index ff6d97d..6aa821f 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/dreams/touch/ShadeTouchHandlerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/dreams/touch/ShadeTouchHandlerTest.java
@@ -27,7 +27,6 @@
import androidx.test.ext.junit.runners.AndroidJUnit4;
import androidx.test.filters.SmallTest;
-import com.android.systemui.RoboPilotTest;
import com.android.systemui.SysuiTestCase;
import com.android.systemui.shade.ShadeViewController;
import com.android.systemui.shared.system.InputChannelCompat;
@@ -43,7 +42,6 @@
import java.util.Optional;
-@RoboPilotTest
@SmallTest
@RunWith(AndroidJUnit4.class)
public class ShadeTouchHandlerTest extends SysuiTestCase {
diff --git a/packages/SystemUI/tests/src/com/android/systemui/dreams/touch/scrim/BouncerlessScrimControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/dreams/touch/scrim/BouncerlessScrimControllerTest.java
index da39381..017fdbe 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/dreams/touch/scrim/BouncerlessScrimControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/dreams/touch/scrim/BouncerlessScrimControllerTest.java
@@ -26,7 +26,6 @@
import androidx.test.ext.junit.runners.AndroidJUnit4;
import androidx.test.filters.SmallTest;
-import com.android.systemui.RoboPilotTest;
import com.android.systemui.SysuiTestCase;
import com.android.systemui.shade.ShadeExpansionChangeEvent;
import com.android.systemui.util.concurrency.FakeExecutor;
@@ -38,7 +37,6 @@
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
-@RoboPilotTest
@SmallTest
@RunWith(AndroidJUnit4.class)
public class BouncerlessScrimControllerTest extends SysuiTestCase {
diff --git a/packages/SystemUI/tests/src/com/android/systemui/dreams/touch/scrim/ScrimManagerTest.java b/packages/SystemUI/tests/src/com/android/systemui/dreams/touch/scrim/ScrimManagerTest.java
index 81f6fe3..4ee4a60 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/dreams/touch/scrim/ScrimManagerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/dreams/touch/scrim/ScrimManagerTest.java
@@ -25,7 +25,6 @@
import androidx.test.ext.junit.runners.AndroidJUnit4;
import androidx.test.filters.SmallTest;
-import com.android.systemui.RoboPilotTest;
import com.android.systemui.SysuiTestCase;
import com.android.systemui.statusbar.policy.KeyguardStateController;
import com.android.systemui.util.concurrency.FakeExecutor;
@@ -38,7 +37,6 @@
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
-@RoboPilotTest
@SmallTest
@RunWith(AndroidJUnit4.class)
public class ScrimManagerTest extends SysuiTestCase {
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/KeyguardViewMediatorTest.java b/packages/SystemUI/tests/src/com/android/systemui/keyguard/KeyguardViewMediatorTest.java
index 291dda20..a646823 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/KeyguardViewMediatorTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/KeyguardViewMediatorTest.java
@@ -16,7 +16,6 @@
package com.android.systemui.keyguard;
-import static android.os.PowerManager.WAKE_REASON_WAKE_MOTION;
import static android.provider.Settings.Secure.LOCK_SCREEN_LOCK_AFTER_TIMEOUT;
import static android.view.WindowManager.TRANSIT_OLD_KEYGUARD_GOING_AWAY;
import static android.view.WindowManagerPolicyConstants.OFF_BECAUSE_OF_TIMEOUT;
@@ -635,29 +634,6 @@
}
@Test
- public void lockAfterSpecifiedAfterDreamStarted() {
- int currentUserId = 99;
- int userSpecificTimeout = 5999;
- KeyguardUpdateMonitor.setCurrentUser(currentUserId);
-
- // set mDeviceInteractive to true
- mViewMediator.onStartedWakingUp(WAKE_REASON_WAKE_MOTION, false);
- mFeatureFlags.set(Flags.LOCKSCREEN_WITHOUT_SECURE_LOCK_WHEN_DREAMING, false);
- when(mLockPatternUtils.isSecure(currentUserId)).thenReturn(true);
- when(mDevicePolicyManager.getMaximumTimeToLock(null, currentUserId)).thenReturn(0L);
- when(mSecureSettings.getIntForUser(LOCK_SCREEN_LOCK_AFTER_TIMEOUT,
- KEYGUARD_LOCK_AFTER_DELAY_DEFAULT, currentUserId)).thenReturn(userSpecificTimeout);
- mSystemClock.setElapsedRealtime(0L);
- ArgumentCaptor<PendingIntent> pendingIntent = ArgumentCaptor.forClass(PendingIntent.class);
-
- mViewMediator.onDreamingStarted();
-
- verify(mAlarmManager).setExactAndAllowWhileIdle(eq(AlarmManager.ELAPSED_REALTIME_WAKEUP),
- eq(Long.valueOf(userSpecificTimeout)), pendingIntent.capture());
- assertEquals(DELAYED_KEYGUARD_ACTION, pendingIntent.getValue().getIntent().getAction());
- }
-
- @Test
public void testHideSurfaceBehindKeyguardMarksKeyguardNotGoingAway() {
mViewMediator.hideSurfaceBehindKeyguard();
@@ -1023,7 +999,6 @@
mViewMediator.setShowingLocked(false);
when(mKeyguardStateController.isShowing()).thenReturn(false);
- mFeatureFlags.set(Flags.LOCKSCREEN_WITHOUT_SECURE_LOCK_WHEN_DREAMING, false);
mViewMediator.onDreamingStarted();
assertFalse(mViewMediator.isShowingAndNotOccluded());
}
@@ -1034,7 +1009,6 @@
mViewMediator.setShowingLocked(true);
when(mKeyguardStateController.isShowing()).thenReturn(true);
- mFeatureFlags.set(Flags.LOCKSCREEN_WITHOUT_SECURE_LOCK_WHEN_DREAMING, true);
mViewMediator.onDreamingStarted();
assertTrue(mViewMediator.isShowingAndNotOccluded());
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/quickaffordance/CameraQuickAffordanceConfigTest.kt b/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/quickaffordance/CameraQuickAffordanceConfigTest.kt
index cfee3b8..e20d3af 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/quickaffordance/CameraQuickAffordanceConfigTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/quickaffordance/CameraQuickAffordanceConfigTest.kt
@@ -23,7 +23,6 @@
import android.content.pm.PackageManager
import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.filters.SmallTest
-import com.android.systemui.RoboPilotTest
import com.android.systemui.SysuiTestCase
import com.android.systemui.camera.CameraGestureHelper
import com.android.systemui.settings.UserTracker
@@ -43,7 +42,6 @@
@OptIn(ExperimentalCoroutinesApi::class)
@SmallTest
-@RoboPilotTest
@RunWith(AndroidJUnit4::class)
class CameraQuickAffordanceConfigTest : SysuiTestCase() {
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/quickaffordance/DoNotDisturbQuickAffordanceConfigTest.kt b/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/quickaffordance/DoNotDisturbQuickAffordanceConfigTest.kt
index 49168d0..faf9751 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/quickaffordance/DoNotDisturbQuickAffordanceConfigTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/quickaffordance/DoNotDisturbQuickAffordanceConfigTest.kt
@@ -26,7 +26,6 @@
import androidx.test.filters.SmallTest
import com.android.settingslib.notification.EnableZenModeDialog
import com.android.systemui.res.R
-import com.android.systemui.RoboPilotTest
import com.android.systemui.SysuiTestCase
import com.android.systemui.animation.Expandable
import com.android.systemui.common.shared.model.ContentDescription
@@ -61,7 +60,6 @@
@OptIn(ExperimentalCoroutinesApi::class)
@SmallTest
-@RoboPilotTest
@RunWith(AndroidJUnit4::class)
class DoNotDisturbQuickAffordanceConfigTest : SysuiTestCase() {
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/quickaffordance/FakeKeyguardQuickAffordanceConfig.kt b/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/quickaffordance/FakeKeyguardQuickAffordanceConfig.kt
index c85c7f6..548b564 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/quickaffordance/FakeKeyguardQuickAffordanceConfig.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/quickaffordance/FakeKeyguardQuickAffordanceConfig.kt
@@ -17,7 +17,6 @@
package com.android.systemui.keyguard.data.quickaffordance
-import com.android.systemui.RoboPilotTest
import com.android.systemui.animation.Expandable
import com.android.systemui.keyguard.data.quickaffordance.KeyguardQuickAffordanceConfig.OnTriggeredResult
import kotlinx.coroutines.flow.Flow
@@ -25,7 +24,6 @@
import kotlinx.coroutines.yield
/** Fake implementation of a quick affordance data source. */
-@RoboPilotTest
class FakeKeyguardQuickAffordanceConfig(
override val key: String,
private val pickerName: String = key,
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/quickaffordance/FlashlightQuickAffordanceConfigTest.kt b/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/quickaffordance/FlashlightQuickAffordanceConfigTest.kt
index c3e28ae..4ae144c 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/quickaffordance/FlashlightQuickAffordanceConfigTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/quickaffordance/FlashlightQuickAffordanceConfigTest.kt
@@ -21,7 +21,6 @@
import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.filters.SmallTest
import com.android.systemui.res.R
-import com.android.systemui.RoboPilotTest
import com.android.systemui.common.shared.model.Icon
import com.android.systemui.keyguard.shared.quickaffordance.ActivationState
import com.android.systemui.statusbar.policy.FlashlightController
@@ -42,7 +41,6 @@
@OptIn(ExperimentalCoroutinesApi::class)
@SmallTest
-@RoboPilotTest
@RunWith(AndroidJUnit4::class)
class FlashlightQuickAffordanceConfigTest : LeakCheckedTest() {
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/quickaffordance/HomeControlsKeyguardQuickAffordanceConfigTest.kt b/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/quickaffordance/HomeControlsKeyguardQuickAffordanceConfigTest.kt
index ef56a98..7d68cc0 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/quickaffordance/HomeControlsKeyguardQuickAffordanceConfigTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/quickaffordance/HomeControlsKeyguardQuickAffordanceConfigTest.kt
@@ -20,7 +20,6 @@
import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.filters.SmallTest
import com.android.systemui.res.R
-import com.android.systemui.RoboPilotTest
import com.android.systemui.SysuiTestCase
import com.android.systemui.animation.Expandable
import com.android.systemui.controls.controller.ControlsController
@@ -41,7 +40,6 @@
import org.mockito.MockitoAnnotations
@SmallTest
-@RoboPilotTest
@RunWith(AndroidJUnit4::class)
class HomeControlsKeyguardQuickAffordanceConfigTest : SysuiTestCase() {
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/quickaffordance/KeyguardQuickAffordanceLegacySettingSyncerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/quickaffordance/KeyguardQuickAffordanceLegacySettingSyncerTest.kt
index 4f071bd..1e80fb6 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/quickaffordance/KeyguardQuickAffordanceLegacySettingSyncerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/quickaffordance/KeyguardQuickAffordanceLegacySettingSyncerTest.kt
@@ -23,7 +23,6 @@
import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.filters.SmallTest
import com.android.systemui.res.R
-import com.android.systemui.RoboPilotTest
import com.android.systemui.SysuiTestCase
import com.android.systemui.settings.FakeUserTracker
import com.android.systemui.shared.keyguard.shared.model.KeyguardQuickAffordanceSlots
@@ -49,7 +48,6 @@
@OptIn(ExperimentalCoroutinesApi::class)
@SmallTest
-@RoboPilotTest
@RunWith(AndroidJUnit4::class)
class KeyguardQuickAffordanceLegacySettingSyncerTest : SysuiTestCase() {
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/quickaffordance/KeyguardQuickAffordanceLocalUserSelectionManagerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/quickaffordance/KeyguardQuickAffordanceLocalUserSelectionManagerTest.kt
index bd0b71d..99a0185 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/quickaffordance/KeyguardQuickAffordanceLocalUserSelectionManagerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/quickaffordance/KeyguardQuickAffordanceLocalUserSelectionManagerTest.kt
@@ -23,7 +23,6 @@
import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.filters.SmallTest
import com.android.systemui.res.R
-import com.android.systemui.RoboPilotTest
import com.android.systemui.SysuiTestCase
import com.android.systemui.backup.BackupHelper
import com.android.systemui.settings.FakeUserTracker
@@ -53,7 +52,6 @@
@OptIn(ExperimentalCoroutinesApi::class)
@SmallTest
-@RoboPilotTest
@RunWith(AndroidJUnit4::class)
class KeyguardQuickAffordanceLocalUserSelectionManagerTest : SysuiTestCase() {
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/quickaffordance/KeyguardQuickAffordanceRemoteUserSelectionManagerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/quickaffordance/KeyguardQuickAffordanceRemoteUserSelectionManagerTest.kt
index 0797d07..a1c9f87 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/quickaffordance/KeyguardQuickAffordanceRemoteUserSelectionManagerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/quickaffordance/KeyguardQuickAffordanceRemoteUserSelectionManagerTest.kt
@@ -21,7 +21,6 @@
import android.os.UserHandle
import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.filters.SmallTest
-import com.android.systemui.RoboPilotTest
import com.android.systemui.SysuiTestCase
import com.android.systemui.settings.FakeUserTracker
import com.android.systemui.shared.customization.data.content.FakeCustomizationProviderClient
@@ -44,7 +43,6 @@
@OptIn(ExperimentalCoroutinesApi::class)
@SmallTest
-@RoboPilotTest
@RunWith(AndroidJUnit4::class)
class KeyguardQuickAffordanceRemoteUserSelectionManagerTest : SysuiTestCase() {
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/quickaffordance/MuteQuickAffordanceConfigTest.kt b/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/quickaffordance/MuteQuickAffordanceConfigTest.kt
index d8c0341..b15352b 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/quickaffordance/MuteQuickAffordanceConfigTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/quickaffordance/MuteQuickAffordanceConfigTest.kt
@@ -21,7 +21,6 @@
import android.media.AudioManager
import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.filters.SmallTest
-import com.android.systemui.RoboPilotTest
import com.android.systemui.SysuiTestCase
import com.android.systemui.settings.UserFileManager
import com.android.systemui.settings.UserTracker
@@ -46,7 +45,6 @@
@OptIn(ExperimentalCoroutinesApi::class)
@SmallTest
-@RoboPilotTest
@RunWith(AndroidJUnit4::class)
class MuteQuickAffordanceConfigTest : SysuiTestCase() {
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/quickaffordance/QrCodeScannerKeyguardQuickAffordanceConfigTest.kt b/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/quickaffordance/QrCodeScannerKeyguardQuickAffordanceConfigTest.kt
index 9d983b8..521dea3 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/quickaffordance/QrCodeScannerKeyguardQuickAffordanceConfigTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/quickaffordance/QrCodeScannerKeyguardQuickAffordanceConfigTest.kt
@@ -20,7 +20,6 @@
import android.content.Intent
import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.filters.SmallTest
-import com.android.systemui.RoboPilotTest
import com.android.systemui.SysuiTestCase
import com.android.systemui.keyguard.data.quickaffordance.KeyguardQuickAffordanceConfig.OnTriggeredResult
import com.android.systemui.qrcodescanner.controller.QRCodeScannerController
@@ -40,7 +39,6 @@
import org.mockito.MockitoAnnotations
@SmallTest
-@RoboPilotTest
@RunWith(AndroidJUnit4::class)
class QrCodeScannerKeyguardQuickAffordanceConfigTest : SysuiTestCase() {
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/quickaffordance/QuickAccessWalletKeyguardQuickAffordanceConfigTest.kt b/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/quickaffordance/QuickAccessWalletKeyguardQuickAffordanceConfigTest.kt
index 613c4ce..02db0d7 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/quickaffordance/QuickAccessWalletKeyguardQuickAffordanceConfigTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/quickaffordance/QuickAccessWalletKeyguardQuickAffordanceConfigTest.kt
@@ -24,7 +24,6 @@
import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.filters.SmallTest
import com.android.systemui.res.R
-import com.android.systemui.RoboPilotTest
import com.android.systemui.SysuiTestCase
import com.android.systemui.animation.ActivityLaunchAnimator
import com.android.systemui.animation.Expandable
@@ -51,7 +50,6 @@
@OptIn(ExperimentalCoroutinesApi::class)
@SmallTest
-@RoboPilotTest
@RunWith(AndroidJUnit4::class)
class QuickAccessWalletKeyguardQuickAffordanceConfigTest : SysuiTestCase() {
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/quickaffordance/VideoCameraQuickAffordanceConfigTest.kt b/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/quickaffordance/VideoCameraQuickAffordanceConfigTest.kt
index 1414bac..a9b9c90 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/quickaffordance/VideoCameraQuickAffordanceConfigTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/quickaffordance/VideoCameraQuickAffordanceConfigTest.kt
@@ -21,7 +21,6 @@
import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.filters.SmallTest
import com.android.systemui.ActivityIntentHelper
-import com.android.systemui.RoboPilotTest
import com.android.systemui.SysuiTestCase
import com.android.systemui.camera.CameraIntentsWrapper
import com.android.systemui.coroutines.collectLastValue
@@ -45,7 +44,6 @@
@OptIn(ExperimentalCoroutinesApi::class)
@SmallTest
-@RoboPilotTest
@RunWith(AndroidJUnit4::class)
class VideoCameraQuickAffordanceConfigTest : SysuiTestCase() {
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/repository/BiometricSettingsRepositoryTest.kt b/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/repository/BiometricSettingsRepositoryTest.kt
index 944b059..d8cdf29 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/repository/BiometricSettingsRepositoryTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/repository/BiometricSettingsRepositoryTest.kt
@@ -32,7 +32,6 @@
import com.android.internal.widget.LockPatternUtils.StrongAuthTracker.STRONG_AUTH_REQUIRED_AFTER_BOOT
import com.android.internal.widget.LockPatternUtils.StrongAuthTracker.STRONG_AUTH_REQUIRED_AFTER_TIMEOUT
import com.android.internal.widget.LockPatternUtils.StrongAuthTracker.STRONG_AUTH_REQUIRED_AFTER_USER_LOCKDOWN
-import com.android.systemui.RoboPilotTest
import com.android.systemui.SysuiTestCase
import com.android.systemui.biometrics.AuthController
import com.android.systemui.biometrics.data.repository.FaceSensorInfo
@@ -79,7 +78,6 @@
@OptIn(ExperimentalCoroutinesApi::class)
@SmallTest
-@RoboPilotTest
@TestableLooper.RunWithLooper(setAsMainLooper = true)
@RunWith(AndroidJUnit4::class)
class BiometricSettingsRepositoryTest : SysuiTestCase() {
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/repository/DeviceEntryFaceAuthRepositoryTest.kt b/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/repository/DeviceEntryFaceAuthRepositoryTest.kt
index 307204da..819d08a 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/repository/DeviceEntryFaceAuthRepositoryTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/repository/DeviceEntryFaceAuthRepositoryTest.kt
@@ -44,7 +44,6 @@
import com.android.keyguard.FaceAuthUiEvent.FACE_AUTH_TRIGGERED_SWIPE_UP_ON_BOUNCER
import com.android.keyguard.KeyguardUpdateMonitor
import com.android.systemui.res.R
-import com.android.systemui.RoboPilotTest
import com.android.systemui.SysuiTestCase
import com.android.systemui.biometrics.data.repository.FakeDisplayStateRepository
import com.android.systemui.biometrics.data.repository.FakeFacePropertyRepository
@@ -122,7 +121,6 @@
@OptIn(ExperimentalCoroutinesApi::class)
@SmallTest
-@RoboPilotTest
@RunWith(AndroidJUnit4::class)
class DeviceEntryFaceAuthRepositoryTest : SysuiTestCase() {
private lateinit var underTest: DeviceEntryFaceAuthRepositoryImpl
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/repository/DeviceEntryFingerprintAuthRepositoryTest.kt b/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/repository/DeviceEntryFingerprintAuthRepositoryTest.kt
index def016a..a58bc52 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/repository/DeviceEntryFingerprintAuthRepositoryTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/repository/DeviceEntryFingerprintAuthRepositoryTest.kt
@@ -22,7 +22,6 @@
import androidx.test.filters.SmallTest
import com.android.keyguard.KeyguardUpdateMonitor
import com.android.keyguard.KeyguardUpdateMonitorCallback
-import com.android.systemui.RoboPilotTest
import com.android.systemui.SysuiTestCase
import com.android.systemui.biometrics.AuthController
import com.android.systemui.coroutines.collectLastValue
@@ -49,7 +48,6 @@
@OptIn(ExperimentalCoroutinesApi::class)
@SmallTest
-@RoboPilotTest
@RunWith(AndroidJUnit4::class)
class DeviceEntryFingerprintAuthRepositoryTest : SysuiTestCase() {
@Mock private lateinit var keyguardUpdateMonitor: KeyguardUpdateMonitor
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/repository/DevicePostureRepositoryTest.kt b/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/repository/DevicePostureRepositoryTest.kt
index 7eb8a26..9be5558 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/repository/DevicePostureRepositoryTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/repository/DevicePostureRepositoryTest.kt
@@ -18,7 +18,6 @@
import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.filters.SmallTest
-import com.android.systemui.RoboPilotTest
import com.android.systemui.SysuiTestCase
import com.android.systemui.coroutines.collectLastValue
import com.android.systemui.keyguard.shared.model.DevicePosture
@@ -39,7 +38,6 @@
@OptIn(ExperimentalCoroutinesApi::class)
@SmallTest
-@RoboPilotTest
@RunWith(AndroidJUnit4::class)
class DevicePostureRepositoryTest : SysuiTestCase() {
private lateinit var underTest: DevicePostureRepository
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/repository/KeyguardQuickAffordanceRepositoryTest.kt b/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/repository/KeyguardQuickAffordanceRepositoryTest.kt
index 126b841..567e0a9 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/repository/KeyguardQuickAffordanceRepositoryTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/repository/KeyguardQuickAffordanceRepositoryTest.kt
@@ -22,7 +22,6 @@
import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.filters.SmallTest
import com.android.systemui.res.R
-import com.android.systemui.RoboPilotTest
import com.android.systemui.SysuiTestCase
import com.android.systemui.coroutines.collectLastValue
import com.android.systemui.keyguard.data.quickaffordance.FakeKeyguardQuickAffordanceConfig
@@ -56,7 +55,6 @@
@OptIn(ExperimentalCoroutinesApi::class)
@SmallTest
-@RoboPilotTest
@RunWith(AndroidJUnit4::class)
class KeyguardQuickAffordanceRepositoryTest : SysuiTestCase() {
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/repository/KeyguardRepositoryImplTest.kt b/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/repository/KeyguardRepositoryImplTest.kt
index 7983e30..b9119e1 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/repository/KeyguardRepositoryImplTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/repository/KeyguardRepositoryImplTest.kt
@@ -22,7 +22,6 @@
import androidx.test.filters.SmallTest
import com.android.keyguard.KeyguardUpdateMonitor
import com.android.keyguard.KeyguardUpdateMonitorCallback
-import com.android.systemui.RoboPilotTest
import com.android.systemui.SysuiTestCase
import com.android.systemui.biometrics.AuthController
import com.android.systemui.common.shared.model.Position
@@ -64,7 +63,6 @@
@OptIn(ExperimentalCoroutinesApi::class)
@SmallTest
-@RoboPilotTest
@RunWith(AndroidJUnit4::class)
class KeyguardRepositoryImplTest : SysuiTestCase() {
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/repository/LightRevealScrimRepositoryTest.kt b/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/repository/LightRevealScrimRepositoryTest.kt
index 4942cf8..799bd5a 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/repository/LightRevealScrimRepositoryTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/repository/LightRevealScrimRepositoryTest.kt
@@ -20,7 +20,6 @@
import android.testing.TestableLooper
import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.filters.SmallTest
-import com.android.systemui.RoboPilotTest
import com.android.systemui.SysuiTestCase
import com.android.systemui.animation.AnimatorTestRule
import com.android.systemui.coroutines.collectLastValue
@@ -46,7 +45,6 @@
import org.mockito.MockitoAnnotations
@SmallTest
-@RoboPilotTest
@OptIn(ExperimentalCoroutinesApi::class)
@RunWith(AndroidJUnit4::class)
class LightRevealScrimRepositoryTest : SysuiTestCase() {
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/repository/TrustRepositoryTest.kt b/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/repository/TrustRepositoryTest.kt
index 7f784d8..ee47c58f4 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/repository/TrustRepositoryTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/repository/TrustRepositoryTest.kt
@@ -21,7 +21,6 @@
import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.filters.SmallTest
import com.android.keyguard.logging.TrustRepositoryLogger
-import com.android.systemui.RoboPilotTest
import com.android.systemui.SysuiTestCase
import com.android.systemui.coroutines.FlowValue
import com.android.systemui.coroutines.collectLastValue
@@ -46,7 +45,6 @@
@OptIn(ExperimentalCoroutinesApi::class)
@SmallTest
-@RoboPilotTest
@RunWith(AndroidJUnit4::class)
class TrustRepositoryTest : SysuiTestCase() {
@Mock private lateinit var trustManager: TrustManager
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/KeyguardDismissActionInteractorTest.kt b/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/KeyguardDismissActionInteractorTest.kt
index 181cc88..d6e19cb 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/KeyguardDismissActionInteractorTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/KeyguardDismissActionInteractorTest.kt
@@ -19,7 +19,6 @@
import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.filters.SmallTest
-import com.android.systemui.RoboPilotTest
import com.android.systemui.SysuiTestCase
import com.android.systemui.coroutines.collectLastValue
import com.android.systemui.keyguard.data.repository.FakeKeyguardRepository
@@ -43,7 +42,6 @@
@OptIn(ExperimentalCoroutinesApi::class)
@SmallTest
-@RoboPilotTest
@RunWith(AndroidJUnit4::class)
class KeyguardDismissActionInteractorTest : SysuiTestCase() {
private lateinit var keyguardRepository: FakeKeyguardRepository
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/KeyguardDismissInteractorTest.kt b/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/KeyguardDismissInteractorTest.kt
index c407b14..a5cfbbf 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/KeyguardDismissInteractorTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/KeyguardDismissInteractorTest.kt
@@ -22,7 +22,6 @@
import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.filters.SmallTest
import com.android.keyguard.TrustGrantFlags
-import com.android.systemui.RoboPilotTest
import com.android.systemui.SysuiTestCase
import com.android.systemui.coroutines.collectLastValue
import com.android.systemui.keyguard.shared.model.DismissAction
@@ -40,7 +39,6 @@
import org.mockito.MockitoAnnotations
@SmallTest
-@RoboPilotTest
@RunWith(AndroidJUnit4::class)
class KeyguardDismissInteractorTest : SysuiTestCase() {
private lateinit var dispatcher: TestDispatcher
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/KeyguardFaceAuthInteractorTest.kt b/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/KeyguardFaceAuthInteractorTest.kt
index b527510..06eb0dd 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/KeyguardFaceAuthInteractorTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/KeyguardFaceAuthInteractorTest.kt
@@ -28,8 +28,10 @@
import com.android.keyguard.KeyguardSecurityModel
import com.android.keyguard.KeyguardUpdateMonitor
import com.android.systemui.SysuiTestCase
+import com.android.systemui.biometrics.data.repository.FaceSensorInfo
import com.android.systemui.biometrics.data.repository.FakeFacePropertyRepository
import com.android.systemui.biometrics.shared.model.LockoutMode
+import com.android.systemui.biometrics.shared.model.SensorStrength
import com.android.systemui.bouncer.data.repository.FakeKeyguardBouncerRepository
import com.android.systemui.bouncer.domain.interactor.AlternateBouncerInteractor
import com.android.systemui.bouncer.domain.interactor.PrimaryBouncerCallbackInteractor
@@ -156,7 +158,6 @@
fakeDeviceEntryFingerprintAuthRepository,
fakeUserRepository,
facePropertyRepository,
- fakeKeyguardRepository,
faceWakeUpTriggersConfig,
powerInteractor,
)
@@ -440,6 +441,43 @@
}
@Test
+ fun faceAuthIsRequestedWhenWalletIsLaunchedAndIfFaceAuthIsStrong() =
+ testScope.runTest {
+ underTest.start()
+ facePropertyRepository.setSensorInfo(FaceSensorInfo(1, SensorStrength.STRONG))
+
+ underTest.onWalletLaunched()
+
+ runCurrent()
+ assertThat(faceAuthRepository.runningAuthRequest.value)
+ .isEqualTo(Pair(FaceAuthUiEvent.FACE_AUTH_TRIGGERED_OCCLUDING_APP_REQUESTED, true))
+ }
+
+ @Test
+ fun faceAuthIsNotTriggeredIfFaceAuthIsWeak() =
+ testScope.runTest {
+ underTest.start()
+ facePropertyRepository.setSensorInfo(FaceSensorInfo(1, SensorStrength.WEAK))
+
+ underTest.onWalletLaunched()
+
+ runCurrent()
+ assertThat(faceAuthRepository.runningAuthRequest.value).isNull()
+ }
+
+ @Test
+ fun faceAuthIsNotTriggeredIfFaceAuthIsConvenience() =
+ testScope.runTest {
+ underTest.start()
+ facePropertyRepository.setSensorInfo(FaceSensorInfo(1, SensorStrength.CONVENIENCE))
+
+ underTest.onWalletLaunched()
+
+ runCurrent()
+ assertThat(faceAuthRepository.runningAuthRequest.value).isNull()
+ }
+
+ @Test
fun faceUnlockIsDisabledWhenFpIsLockedOut() =
testScope.runTest {
underTest.start()
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/KeyguardInteractorTest.kt b/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/KeyguardInteractorTest.kt
index ca52cdb..9ee22c8 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/KeyguardInteractorTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/KeyguardInteractorTest.kt
@@ -20,7 +20,6 @@
import android.app.StatusBarManager
import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.filters.SmallTest
-import com.android.systemui.RoboPilotTest
import com.android.systemui.SysuiTestCase
import com.android.systemui.bouncer.data.repository.FakeKeyguardBouncerRepository
import com.android.systemui.common.ui.data.repository.FakeConfigurationRepository
@@ -47,7 +46,6 @@
@OptIn(ExperimentalCoroutinesApi::class)
@SmallTest
-@RoboPilotTest
@RunWith(AndroidJUnit4::class)
class KeyguardInteractorTest : SysuiTestCase() {
@@ -206,7 +204,8 @@
fromScene = SceneKey.Gone,
toScene = SceneKey.Lockscreen,
progress = flowOf(0f),
- isUserInputDriven = false,
+ isInitiatedByUserInput = false,
+ isUserInputOngoing = flowOf(false),
)
runCurrent()
assertThat(isAnimate).isFalse()
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/KeyguardLongPressInteractorTest.kt b/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/KeyguardLongPressInteractorTest.kt
index 13025a0..0c74a38 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/KeyguardLongPressInteractorTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/KeyguardLongPressInteractorTest.kt
@@ -22,7 +22,6 @@
import androidx.test.filters.SmallTest
import com.android.internal.logging.UiEventLogger
import com.android.systemui.res.R
-import com.android.systemui.RoboPilotTest
import com.android.systemui.SysuiTestCase
import com.android.systemui.coroutines.collectLastValue
import com.android.systemui.flags.FakeFeatureFlags
@@ -51,7 +50,6 @@
@OptIn(ExperimentalCoroutinesApi::class)
@SmallTest
-@RoboPilotTest
@RunWith(AndroidJUnit4::class)
class KeyguardLongPressInteractorTest : SysuiTestCase() {
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/KeyguardQuickAffordanceInteractorTest.kt b/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/KeyguardQuickAffordanceInteractorTest.kt
index 8c13bb4..347d580 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/KeyguardQuickAffordanceInteractorTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/KeyguardQuickAffordanceInteractorTest.kt
@@ -23,7 +23,6 @@
import androidx.test.filters.SmallTest
import com.android.internal.widget.LockPatternUtils
import com.android.systemui.res.R
-import com.android.systemui.RoboPilotTest
import com.android.systemui.SysuiTestCase
import com.android.systemui.animation.DialogLaunchAnimator
import com.android.systemui.common.shared.model.ContentDescription
@@ -73,7 +72,6 @@
@OptIn(ExperimentalCoroutinesApi::class)
@SmallTest
-@RoboPilotTest
@RunWith(AndroidJUnit4::class)
class KeyguardQuickAffordanceInteractorTest : SysuiTestCase() {
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/KeyguardSurfaceBehindInteractorTest.kt b/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/KeyguardSurfaceBehindInteractorTest.kt
index fdcc66b..71fcf6f 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/KeyguardSurfaceBehindInteractorTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/KeyguardSurfaceBehindInteractorTest.kt
@@ -18,7 +18,6 @@
import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.filters.SmallTest
-import com.android.systemui.RoboPilotTest
import com.android.systemui.SysuiTestCase
import com.android.systemui.coroutines.collectValues
import com.android.systemui.keyguard.data.repository.FakeKeyguardSurfaceBehindRepository
@@ -41,7 +40,6 @@
import org.mockito.MockitoAnnotations.initMocks
@SmallTest
-@RoboPilotTest
@RunWith(AndroidJUnit4::class)
@kotlinx.coroutines.ExperimentalCoroutinesApi
class KeyguardSurfaceBehindInteractorTest : SysuiTestCase() {
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/KeyguardTransitionInteractorTest.kt b/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/KeyguardTransitionInteractorTest.kt
index fa93253..29b546b 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/KeyguardTransitionInteractorTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/KeyguardTransitionInteractorTest.kt
@@ -19,7 +19,6 @@
import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.filters.SmallTest
-import com.android.systemui.RoboPilotTest
import com.android.systemui.SysuiTestCase
import com.android.systemui.coroutines.collectValues
import com.android.systemui.keyguard.data.repository.FakeKeyguardTransitionRepository
@@ -42,7 +41,6 @@
import org.junit.runner.RunWith
@SmallTest
-@RoboPilotTest
@RunWith(AndroidJUnit4::class)
@kotlinx.coroutines.ExperimentalCoroutinesApi
class KeyguardTransitionInteractorTest : SysuiTestCase() {
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/LightRevealScrimInteractorTest.kt b/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/LightRevealScrimInteractorTest.kt
index 906d948..c02add1 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/LightRevealScrimInteractorTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/LightRevealScrimInteractorTest.kt
@@ -18,7 +18,6 @@
import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.filters.SmallTest
-import com.android.systemui.RoboPilotTest
import com.android.systemui.SysuiTestCase
import com.android.systemui.keyguard.data.repository.FakeKeyguardTransitionRepository
import com.android.systemui.keyguard.data.repository.FakeLightRevealScrimRepository
@@ -45,7 +44,6 @@
import org.mockito.Spy
@SmallTest
-@RoboPilotTest
@OptIn(ExperimentalCoroutinesApi::class)
@RunWith(AndroidJUnit4::class)
class LightRevealScrimInteractorTest : SysuiTestCase() {
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/WindowManagerLockscreenVisibilityInteractorTest.kt b/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/WindowManagerLockscreenVisibilityInteractorTest.kt
index 73ecae5..16f2fa2 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/WindowManagerLockscreenVisibilityInteractorTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/WindowManagerLockscreenVisibilityInteractorTest.kt
@@ -18,7 +18,6 @@
import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.filters.SmallTest
-import com.android.systemui.RoboPilotTest
import com.android.systemui.SysuiTestCase
import com.android.systemui.coroutines.collectValues
import com.android.systemui.keyguard.data.repository.FakeKeyguardTransitionRepository
@@ -38,7 +37,6 @@
import org.mockito.MockitoAnnotations.initMocks
@SmallTest
-@RoboPilotTest
@RunWith(AndroidJUnit4::class)
@kotlinx.coroutines.ExperimentalCoroutinesApi
class WindowManagerLockscreenVisibilityInteractorTest : SysuiTestCase() {
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/binder/KeyguardSurfaceBehindParamsApplierTest.kt b/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/binder/KeyguardSurfaceBehindParamsApplierTest.kt
index a22f603..5b29a86 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/binder/KeyguardSurfaceBehindParamsApplierTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/binder/KeyguardSurfaceBehindParamsApplierTest.kt
@@ -20,7 +20,6 @@
import android.view.RemoteAnimationTarget
import androidx.test.filters.SmallTest
import com.android.keyguard.KeyguardViewController
-import com.android.systemui.RoboPilotTest
import com.android.systemui.SysuiTestCase
import com.android.systemui.animation.AnimatorTestRule
import com.android.systemui.keyguard.domain.interactor.KeyguardSurfaceBehindInteractor
@@ -41,7 +40,6 @@
import org.mockito.MockitoAnnotations
@SmallTest
-@RoboPilotTest
@RunWithLooper(setAsMainLooper = true)
@kotlinx.coroutines.ExperimentalCoroutinesApi
class KeyguardSurfaceBehindParamsApplierTest : SysuiTestCase() {
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/binder/WindowManagerLockscreenVisibilityManagerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/binder/WindowManagerLockscreenVisibilityManagerTest.kt
index 7a17435..9b2db3e 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/binder/WindowManagerLockscreenVisibilityManagerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/binder/WindowManagerLockscreenVisibilityManagerTest.kt
@@ -19,7 +19,6 @@
import android.app.IActivityTaskManager
import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.filters.SmallTest
-import com.android.systemui.RoboPilotTest
import com.android.systemui.SysuiTestCase
import com.android.systemui.keyguard.WindowManagerLockscreenVisibilityManager
import com.android.systemui.statusbar.policy.KeyguardStateController
@@ -35,7 +34,6 @@
import org.mockito.MockitoAnnotations
@SmallTest
-@RoboPilotTest
@RunWith(AndroidJUnit4::class)
@kotlinx.coroutines.ExperimentalCoroutinesApi
class WindowManagerLockscreenVisibilityManagerTest : SysuiTestCase() {
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/viewmodel/AlternateBouncerViewModelTest.kt b/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/viewmodel/AlternateBouncerViewModelTest.kt
new file mode 100644
index 0000000..1768f8c
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/viewmodel/AlternateBouncerViewModelTest.kt
@@ -0,0 +1,197 @@
+/*
+ * Copyright (C) 2023 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.keyguard.ui.viewmodel
+
+import androidx.test.filters.SmallTest
+import com.android.systemui.SysuiTestCase
+import com.android.systemui.coroutines.collectLastValue
+import com.android.systemui.coroutines.collectValues
+import com.android.systemui.keyguard.data.repository.FakeKeyguardTransitionRepository
+import com.android.systemui.keyguard.domain.interactor.KeyguardTransitionInteractor
+import com.android.systemui.keyguard.domain.interactor.KeyguardTransitionInteractorFactory
+import com.android.systemui.keyguard.shared.model.KeyguardState
+import com.android.systemui.keyguard.shared.model.TransitionState
+import com.android.systemui.keyguard.shared.model.TransitionStep
+import com.android.systemui.plugins.FalsingManager
+import com.android.systemui.statusbar.phone.StatusBarKeyguardViewManager
+import com.google.common.collect.Range
+import com.google.common.truth.Truth.assertThat
+import kotlinx.coroutines.ExperimentalCoroutinesApi
+import kotlinx.coroutines.test.TestScope
+import kotlinx.coroutines.test.UnconfinedTestDispatcher
+import kotlinx.coroutines.test.runTest
+import org.junit.Before
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.junit.runners.JUnit4
+import org.mockito.Mock
+import org.mockito.MockitoAnnotations
+
+@ExperimentalCoroutinesApi
+@RunWith(JUnit4::class)
+@SmallTest
+class AlternateBouncerViewModelTest : SysuiTestCase() {
+
+ private lateinit var testScope: TestScope
+
+ @Mock private lateinit var statusBarKeyguardViewManager: StatusBarKeyguardViewManager
+ @Mock private lateinit var falsingManager: FalsingManager
+
+ private lateinit var transitionRepository: FakeKeyguardTransitionRepository
+ private lateinit var transitionInteractor: KeyguardTransitionInteractor
+ private lateinit var underTest: AlternateBouncerViewModel
+
+ @Before
+ fun setup() {
+ MockitoAnnotations.initMocks(this)
+ testScope = TestScope()
+
+ val transitionInteractorWithDependencies =
+ KeyguardTransitionInteractorFactory.create(testScope.backgroundScope)
+ transitionInteractor = transitionInteractorWithDependencies.keyguardTransitionInteractor
+ transitionRepository = transitionInteractorWithDependencies.repository
+ underTest =
+ AlternateBouncerViewModel(
+ statusBarKeyguardViewManager,
+ transitionInteractor,
+ falsingManager,
+ )
+ }
+
+ @Test
+ fun transitionToAlternateBouncer_scrimAlphaUpdate() =
+ runTest(UnconfinedTestDispatcher()) {
+ val scrimAlphas by collectValues(underTest.scrimAlpha)
+
+ transitionRepository.sendTransitionStep(
+ stepToAlternateBouncer(0f, TransitionState.STARTED)
+ )
+ transitionRepository.sendTransitionStep(stepToAlternateBouncer(.4f))
+ transitionRepository.sendTransitionStep(stepToAlternateBouncer(.6f))
+ transitionRepository.sendTransitionStep(stepToAlternateBouncer(1f))
+
+ assertThat(scrimAlphas.size).isEqualTo(4)
+ scrimAlphas.forEach { assertThat(it).isIn(Range.closed(0f, 1f)) }
+ }
+
+ @Test
+ fun transitionFromAlternateBouncer_scrimAlphaUpdate() =
+ runTest(UnconfinedTestDispatcher()) {
+ val scrimAlphas by collectValues(underTest.scrimAlpha)
+
+ transitionRepository.sendTransitionStep(
+ stepFromAlternateBouncer(0f, TransitionState.STARTED)
+ )
+ transitionRepository.sendTransitionStep(stepFromAlternateBouncer(.4f))
+ transitionRepository.sendTransitionStep(stepFromAlternateBouncer(.6f))
+ transitionRepository.sendTransitionStep(stepFromAlternateBouncer(1f))
+
+ assertThat(scrimAlphas.size).isEqualTo(4)
+ scrimAlphas.forEach { assertThat(it).isIn(Range.closed(0f, 1f)) }
+ }
+
+ @Test
+ fun clickListenerUpdate() =
+ runTest(UnconfinedTestDispatcher()) {
+ val clickListener by collectLastValue(underTest.onClickListener)
+
+ // keyguard state => ALTERNATE_BOUNCER
+ transitionRepository.sendTransitionStep(
+ stepToAlternateBouncer(0f, TransitionState.STARTED)
+ )
+ assertThat(clickListener).isNull()
+ transitionRepository.sendTransitionStep(stepToAlternateBouncer(.3f))
+ assertThat(clickListener).isNull()
+ transitionRepository.sendTransitionStep(stepToAlternateBouncer(.6f))
+ assertThat(clickListener).isNull()
+ transitionRepository.sendTransitionStep(stepToAlternateBouncer(1f))
+ assertThat(clickListener).isNotNull()
+
+ // ALTERNATE_BOUNCER -> keyguard state
+ transitionRepository.sendTransitionStep(
+ stepFromAlternateBouncer(0f, TransitionState.STARTED)
+ )
+ assertThat(clickListener).isNotNull()
+ transitionRepository.sendTransitionStep(stepFromAlternateBouncer(.3f))
+ assertThat(clickListener).isNull()
+ transitionRepository.sendTransitionStep(stepFromAlternateBouncer(.6f))
+ assertThat(clickListener).isNull()
+ transitionRepository.sendTransitionStep(stepFromAlternateBouncer(1f))
+ assertThat(clickListener).isNull()
+ }
+
+ @Test
+ fun forcePluginOpen() =
+ runTest(UnconfinedTestDispatcher()) {
+ val forcePluginOpen by collectLastValue(underTest.forcePluginOpen)
+ transitionRepository.sendTransitionStep(
+ stepToAlternateBouncer(0f, TransitionState.STARTED)
+ )
+ transitionRepository.sendTransitionStep(stepToAlternateBouncer(.3f))
+ transitionRepository.sendTransitionStep(stepToAlternateBouncer(.6f))
+ transitionRepository.sendTransitionStep(stepToAlternateBouncer(1f))
+ assertThat(forcePluginOpen).isTrue()
+
+ transitionRepository.sendTransitionStep(
+ stepFromAlternateBouncer(0f, TransitionState.STARTED)
+ )
+ transitionRepository.sendTransitionStep(stepFromAlternateBouncer(.3f))
+ transitionRepository.sendTransitionStep(stepFromAlternateBouncer(.6f))
+ transitionRepository.sendTransitionStep(stepFromAlternateBouncer(1f))
+ assertThat(forcePluginOpen).isFalse()
+ }
+
+ private fun stepToAlternateBouncer(
+ value: Float,
+ state: TransitionState = TransitionState.RUNNING
+ ): TransitionStep {
+ return step(
+ from = KeyguardState.LOCKSCREEN,
+ to = KeyguardState.ALTERNATE_BOUNCER,
+ value = value,
+ transitionState = state,
+ )
+ }
+
+ private fun stepFromAlternateBouncer(
+ value: Float,
+ state: TransitionState = TransitionState.RUNNING
+ ): TransitionStep {
+ return step(
+ from = KeyguardState.ALTERNATE_BOUNCER,
+ to = KeyguardState.LOCKSCREEN,
+ value = value,
+ transitionState = state,
+ )
+ }
+
+ private fun step(
+ from: KeyguardState,
+ to: KeyguardState,
+ value: Float,
+ transitionState: TransitionState
+ ): TransitionStep {
+ return TransitionStep(
+ from = from,
+ to = to,
+ value = value,
+ transitionState = transitionState,
+ ownerName = "AlternateBouncerViewModelTest"
+ )
+ }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/viewmodel/DreamingToLockscreenTransitionViewModelTest.kt b/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/viewmodel/DreamingToLockscreenTransitionViewModelTest.kt
index bfc6f31..6d47aed 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/viewmodel/DreamingToLockscreenTransitionViewModelTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/viewmodel/DreamingToLockscreenTransitionViewModelTest.kt
@@ -18,7 +18,6 @@
import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.filters.SmallTest
-import com.android.systemui.RoboPilotTest
import com.android.systemui.SysuiTestCase
import com.android.systemui.keyguard.data.repository.FakeKeyguardTransitionRepository
import com.android.systemui.keyguard.domain.interactor.KeyguardTransitionInteractorFactory
@@ -46,7 +45,6 @@
import org.junit.runner.RunWith
@SmallTest
-@RoboPilotTest
@RunWith(AndroidJUnit4::class)
class DreamingToLockscreenTransitionViewModelTest : SysuiTestCase() {
private lateinit var underTest: DreamingToLockscreenTransitionViewModel
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/viewmodel/GoneToDreamingTransitionViewModelTest.kt b/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/viewmodel/GoneToDreamingTransitionViewModelTest.kt
index 75c8bff..cf20129 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/viewmodel/GoneToDreamingTransitionViewModelTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/viewmodel/GoneToDreamingTransitionViewModelTest.kt
@@ -18,7 +18,6 @@
import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.filters.SmallTest
-import com.android.systemui.RoboPilotTest
import com.android.systemui.SysuiTestCase
import com.android.systemui.keyguard.data.repository.FakeKeyguardTransitionRepository
import com.android.systemui.keyguard.domain.interactor.KeyguardTransitionInteractorFactory
@@ -37,7 +36,6 @@
import org.junit.runner.RunWith
@SmallTest
-@RoboPilotTest
@RunWith(AndroidJUnit4::class)
class GoneToDreamingTransitionViewModelTest : SysuiTestCase() {
private lateinit var underTest: GoneToDreamingTransitionViewModel
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenSceneViewModelTest.kt b/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenSceneViewModelTest.kt
index 6e94691..7de28de 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenSceneViewModelTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenSceneViewModelTest.kt
@@ -16,6 +16,7 @@
package com.android.systemui.keyguard.ui.viewmodel
+import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.filters.SmallTest
import com.android.systemui.SysuiTestCase
import com.android.systemui.authentication.data.model.AuthenticationMethodModel
@@ -28,10 +29,9 @@
import kotlinx.coroutines.test.runTest
import org.junit.Test
import org.junit.runner.RunWith
-import org.junit.runners.JUnit4
@SmallTest
-@RunWith(JUnit4::class)
+@RunWith(AndroidJUnit4::class)
class LockscreenSceneViewModelTest : SysuiTestCase() {
private val utils = SceneTestUtils(this)
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenToDreamingTransitionViewModelTest.kt b/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenToDreamingTransitionViewModelTest.kt
index 12fe07f..89a1d2b 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenToDreamingTransitionViewModelTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenToDreamingTransitionViewModelTest.kt
@@ -18,7 +18,6 @@
import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.filters.SmallTest
-import com.android.systemui.RoboPilotTest
import com.android.systemui.SysuiTestCase
import com.android.systemui.keyguard.data.repository.FakeKeyguardTransitionRepository
import com.android.systemui.keyguard.domain.interactor.KeyguardTransitionInteractorFactory
@@ -37,7 +36,6 @@
import org.junit.runner.RunWith
@SmallTest
-@RoboPilotTest
@RunWith(AndroidJUnit4::class)
class LockscreenToDreamingTransitionViewModelTest : SysuiTestCase() {
private lateinit var underTest: LockscreenToDreamingTransitionViewModel
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenToOccludedTransitionViewModelTest.kt b/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenToOccludedTransitionViewModelTest.kt
index 83ae631..41f8856 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenToOccludedTransitionViewModelTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenToOccludedTransitionViewModelTest.kt
@@ -18,7 +18,6 @@
import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.filters.SmallTest
-import com.android.systemui.RoboPilotTest
import com.android.systemui.SysuiTestCase
import com.android.systemui.keyguard.data.repository.FakeKeyguardTransitionRepository
import com.android.systemui.keyguard.domain.interactor.KeyguardTransitionInteractorFactory
@@ -37,7 +36,6 @@
import org.junit.runner.RunWith
@SmallTest
-@RoboPilotTest
@RunWith(AndroidJUnit4::class)
class LockscreenToOccludedTransitionViewModelTest : SysuiTestCase() {
private lateinit var underTest: LockscreenToOccludedTransitionViewModel
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/viewmodel/OccludedToLockscreenTransitionViewModelTest.kt b/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/viewmodel/OccludedToLockscreenTransitionViewModelTest.kt
index 8860399..ec95cb8 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/viewmodel/OccludedToLockscreenTransitionViewModelTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/viewmodel/OccludedToLockscreenTransitionViewModelTest.kt
@@ -18,7 +18,6 @@
import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.filters.SmallTest
-import com.android.systemui.RoboPilotTest
import com.android.systemui.SysuiTestCase
import com.android.systemui.keyguard.data.repository.FakeKeyguardTransitionRepository
import com.android.systemui.keyguard.domain.interactor.KeyguardTransitionInteractorFactory
@@ -37,7 +36,6 @@
import org.junit.runner.RunWith
@SmallTest
-@RoboPilotTest
@RunWith(AndroidJUnit4::class)
class OccludedToLockscreenTransitionViewModelTest : SysuiTestCase() {
private lateinit var underTest: OccludedToLockscreenTransitionViewModel
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/viewmodel/PrimaryBouncerToGoneTransitionViewModelTest.kt b/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/viewmodel/PrimaryBouncerToGoneTransitionViewModelTest.kt
index da372ea..9364097 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/viewmodel/PrimaryBouncerToGoneTransitionViewModelTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/viewmodel/PrimaryBouncerToGoneTransitionViewModelTest.kt
@@ -18,7 +18,6 @@
import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.filters.SmallTest
-import com.android.systemui.RoboPilotTest
import com.android.systemui.SysuiTestCase
import com.android.systemui.bouncer.domain.interactor.PrimaryBouncerInteractor
import com.android.systemui.coroutines.collectValues
@@ -46,7 +45,6 @@
import org.mockito.MockitoAnnotations
@SmallTest
-@RoboPilotTest
@RunWith(AndroidJUnit4::class)
class PrimaryBouncerToGoneTransitionViewModelTest : SysuiTestCase() {
private lateinit var underTest: PrimaryBouncerToGoneTransitionViewModel
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/viewmodel/UdfpsAodViewModelTest.kt b/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/viewmodel/UdfpsAodViewModelTest.kt
index 9ab9b3d..32acefe 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/viewmodel/UdfpsAodViewModelTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/viewmodel/UdfpsAodViewModelTest.kt
@@ -18,7 +18,6 @@
import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.filters.SmallTest
-import com.android.systemui.RoboPilotTest
import com.android.systemui.SysuiTestCase
import com.android.systemui.bouncer.data.repository.KeyguardBouncerRepository
import com.android.systemui.common.ui.data.repository.FakeConfigurationRepository
@@ -46,7 +45,6 @@
@ExperimentalCoroutinesApi
@SmallTest
-@RoboPilotTest
@RunWith(AndroidJUnit4::class)
class UdfpsAodViewModelTest : SysuiTestCase() {
private val defaultPadding = 12
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/QSImplTest.java b/packages/SystemUI/tests/src/com/android/systemui/qs/QSImplTest.java
index d57765c..c8c134a 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/QSImplTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/QSImplTest.java
@@ -16,6 +16,8 @@
package com.android.systemui.qs;
+import static android.app.StatusBarManager.DISABLE2_QUICK_SETTINGS;
+
import static com.android.systemui.statusbar.StatusBarState.KEYGUARD;
import static com.android.systemui.statusbar.StatusBarState.SHADE;
@@ -41,6 +43,7 @@
import android.os.Bundle;
import android.testing.AndroidTestingRunner;
import android.testing.TestableLooper.RunWithLooper;
+import android.view.Display;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
@@ -49,7 +52,6 @@
import androidx.test.filters.SmallTest;
import com.android.keyguard.BouncerPanelExpansionCalculator;
-import com.android.systemui.res.R;
import com.android.systemui.SysuiTestCase;
import com.android.systemui.dump.DumpManager;
import com.android.systemui.flags.FeatureFlagsClassic;
@@ -60,6 +62,7 @@
import com.android.systemui.qs.footer.ui.binder.FooterActionsViewBinder;
import com.android.systemui.qs.footer.ui.viewmodel.FooterActionsViewModel;
import com.android.systemui.qs.logging.QSLogger;
+import com.android.systemui.res.R;
import com.android.systemui.settings.FakeDisplayTracker;
import com.android.systemui.shade.transition.LargeScreenShadeInterpolator;
import com.android.systemui.statusbar.CommandQueue;
@@ -110,6 +113,9 @@
@Mock private FeatureFlagsClassic mFeatureFlags;
private View mQsView;
+ private final CommandQueue mCommandQueue =
+ new CommandQueue(mContext, new FakeDisplayTracker(mContext));
+
private QSImpl mUnderTest;
@@ -120,6 +126,16 @@
mUnderTest.onComponentCreated(mQsComponent, null);
}
+ /*
+ * Regression test for b/303180152.
+ */
+ @Test
+ public void testDisableCallbackOnDisabledQuickSettingsUponCreationDoesntCrash() {
+ QSImpl other = instantiate();
+ mCommandQueue.disable(Display.DEFAULT_DISPLAY, 0, DISABLE2_QUICK_SETTINGS);
+
+ other.onComponentCreated(mQsComponent, null);
+ }
@Test
public void testSaveState() {
@@ -473,7 +489,6 @@
private QSImpl instantiate() {
MockitoAnnotations.initMocks(this);
- CommandQueue commandQueue = new CommandQueue(mContext, new FakeDisplayTracker(mContext));
setupQsComponent();
setUpViews();
@@ -484,11 +499,11 @@
return new QSImpl(
new RemoteInputQuickSettingsDisabler(
mContext,
- commandQueue,
+ mCommandQueue,
new ResourcesSplitShadeStateController(),
mock(ConfigurationController.class)),
mStatusBarStateController,
- commandQueue,
+ mCommandQueue,
mQSMediaHost,
mQQSMediaHost,
mBypassController,
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/QSPanelControllerBaseTest.java b/packages/SystemUI/tests/src/com/android/systemui/qs/QSPanelControllerBaseTest.java
index e2ac7bc..b825c08 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/QSPanelControllerBaseTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/QSPanelControllerBaseTest.java
@@ -23,6 +23,7 @@
import static org.mockito.ArgumentMatchers.anyBoolean;
import static org.mockito.ArgumentMatchers.anyFloat;
import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.clearInvocations;
import static org.mockito.Mockito.doAnswer;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.reset;
@@ -42,7 +43,6 @@
import com.android.internal.logging.UiEventLogger;
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
import com.android.internal.logging.testing.UiEventLoggerFake;
-import com.android.systemui.res.R;
import com.android.systemui.SysuiTestCase;
import com.android.systemui.dump.DumpManager;
import com.android.systemui.media.controls.ui.MediaHost;
@@ -50,6 +50,7 @@
import com.android.systemui.qs.customize.QSCustomizerController;
import com.android.systemui.qs.logging.QSLogger;
import com.android.systemui.qs.tileimpl.QSTileImpl;
+import com.android.systemui.res.R;
import com.android.systemui.statusbar.policy.ResourcesSplitShadeStateController;
import com.android.systemui.util.animation.DisappearParameters;
@@ -341,11 +342,92 @@
}
@Test
- public void onViewDetached_removesJustTheAssociatedCallback() {
+ public void onDestroy_removesJustTheAssociatedCallback() {
+ QSPanelControllerBase.TileRecord record = mController.mRecords.get(0);
+
+ mController.destroy();
+ verify(mQSTile).removeCallback(record.callback);
+ verify(mQSTile, never()).removeCallbacks();
+
+ assertThat(mController.mRecords).isEmpty();
+ }
+
+ @Test
+ public void onViewDettached_callbackNotRemoved() {
QSPanelControllerBase.TileRecord record = mController.mRecords.get(0);
mController.onViewDetached();
- verify(mQSTile).removeCallback(record.callback);
+ verify(mQSTile, never()).removeCallback(record.callback);
verify(mQSTile, never()).removeCallbacks();
}
+
+ @Test
+ public void onInit_qsHostCallbackAdded() {
+ verify(mQSHost).addCallback(any());
+ }
+
+ @Test
+ public void onViewDettached_qsHostCallbackNotRemoved() {
+ mController.onViewDetached();
+ verify(mQSHost, never()).removeCallback(any());
+ }
+
+ @Test
+ public void onDestroy_qsHostCallbackRemoved() {
+ mController.destroy();
+ verify(mQSHost).removeCallback(any());
+ }
+
+ @Test
+ public void setTiles_sameTiles_doesntRemoveAndReaddViews() {
+ when(mQSHost.getTiles()).thenReturn(List.of(mQSTile, mOtherTile));
+ mController.setTiles();
+
+ clearInvocations(mQSPanel);
+
+ mController.setTiles();
+ verify(mQSPanel, never()).removeTile(any());
+ verify(mQSPanel, never()).addTile(any());
+ }
+
+ @Test
+ public void setTiles_differentTiles_allTilesRemovedAndNewTilesAdded() {
+ when(mQSHost.getTiles()).thenReturn(List.of(mQSTile, mOtherTile));
+ mController.setTiles();
+
+ clearInvocations(mQSPanel);
+
+ when(mQSHost.getTiles()).thenReturn(List.of(mQSTile));
+ mController.setTiles();
+
+ verify(mQSPanel, times(2)).removeTile(any());
+ verify(mQSPanel).addTile(any());
+ }
+
+ @Test
+ public void detachAndReattach_sameTiles_doesntRemoveAndReAddViews() {
+ when(mQSHost.getTiles()).thenReturn(List.of(mQSTile, mOtherTile));
+ mController.setTiles();
+
+ clearInvocations(mQSPanel);
+
+ mController.onViewDetached();
+ mController.onViewAttached();
+ verify(mQSPanel, never()).removeTile(any());
+ verify(mQSPanel, never()).addTile(any());
+ }
+
+ @Test
+ public void setTiles_sameTilesDifferentOrder_removesAndReadds() {
+ when(mQSHost.getTiles()).thenReturn(List.of(mQSTile, mOtherTile));
+ mController.setTiles();
+
+ clearInvocations(mQSPanel);
+
+ when(mQSHost.getTiles()).thenReturn(List.of(mOtherTile, mQSTile));
+ mController.setTiles();
+
+ verify(mQSPanel, times(2)).removeTile(any());
+ verify(mQSPanel, times(2)).addTile(any());
+ }
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/pipeline/data/repository/AutoAddSettingsRepositoryTest.kt b/packages/SystemUI/tests/src/com/android/systemui/qs/pipeline/data/repository/AutoAddSettingsRepositoryTest.kt
index 9a55f72..d277fca 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/pipeline/data/repository/AutoAddSettingsRepositoryTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/pipeline/data/repository/AutoAddSettingsRepositoryTest.kt
@@ -19,7 +19,6 @@
import android.provider.Settings
import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.filters.SmallTest
-import com.android.systemui.RoboPilotTest
import com.android.systemui.SysuiTestCase
import com.android.systemui.coroutines.collectLastValue
import com.android.systemui.qs.pipeline.shared.TileSpec
@@ -39,7 +38,6 @@
@OptIn(ExperimentalCoroutinesApi::class)
@SmallTest
-@RoboPilotTest
@RunWith(AndroidJUnit4::class)
class AutoAddSettingsRepositoryTest : SysuiTestCase() {
private val secureSettings = FakeSettings()
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/pipeline/data/repository/CustomTileAddedSharedPreferencesRepositoryTest.kt b/packages/SystemUI/tests/src/com/android/systemui/qs/pipeline/data/repository/CustomTileAddedSharedPreferencesRepositoryTest.kt
index 30f5811..3db676d 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/pipeline/data/repository/CustomTileAddedSharedPreferencesRepositoryTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/pipeline/data/repository/CustomTileAddedSharedPreferencesRepositoryTest.kt
@@ -20,7 +20,6 @@
import android.content.SharedPreferences
import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.filters.SmallTest
-import com.android.systemui.RoboPilotTest
import com.android.systemui.SysuiTestCase
import com.android.systemui.settings.UserFileManager
import com.android.systemui.util.FakeSharedPreferences
@@ -30,7 +29,6 @@
import org.junit.runner.RunWith
@SmallTest
-@RoboPilotTest
@RunWith(AndroidJUnit4::class)
class CustomTileAddedSharedPreferencesRepositoryTest : SysuiTestCase() {
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/pipeline/data/repository/InstalledTilesComponentRepositoryImplTest.kt b/packages/SystemUI/tests/src/com/android/systemui/qs/pipeline/data/repository/InstalledTilesComponentRepositoryImplTest.kt
index 995de66..070e07a 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/pipeline/data/repository/InstalledTilesComponentRepositoryImplTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/pipeline/data/repository/InstalledTilesComponentRepositoryImplTest.kt
@@ -32,7 +32,6 @@
import android.testing.TestableLooper
import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.filters.SmallTest
-import com.android.systemui.RoboPilotTest
import com.android.systemui.SysuiTestCase
import com.android.systemui.coroutines.collectLastValue
import com.android.systemui.util.mockito.any
@@ -62,7 +61,6 @@
import org.mockito.MockitoAnnotations
@SmallTest
-@RoboPilotTest
@RunWith(AndroidJUnit4::class)
@TestableLooper.RunWithLooper
@OptIn(ExperimentalCoroutinesApi::class)
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/pipeline/data/repository/QSSettingsRestoredBroadcastRepositoryTest.kt b/packages/SystemUI/tests/src/com/android/systemui/qs/pipeline/data/repository/QSSettingsRestoredBroadcastRepositoryTest.kt
index dc09a33..ff8a9bd 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/pipeline/data/repository/QSSettingsRestoredBroadcastRepositoryTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/pipeline/data/repository/QSSettingsRestoredBroadcastRepositoryTest.kt
@@ -4,7 +4,6 @@
import android.provider.Settings
import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.filters.SmallTest
-import com.android.systemui.RoboPilotTest
import com.android.systemui.SysuiTestCase
import com.android.systemui.broadcast.FakeBroadcastDispatcher
import com.android.systemui.coroutines.collectLastValue
@@ -24,7 +23,6 @@
@SmallTest
@OptIn(ExperimentalCoroutinesApi::class)
@RunWith(AndroidJUnit4::class)
-@RoboPilotTest
class QSSettingsRestoredBroadcastRepositoryTest : SysuiTestCase() {
private val dispatcher = StandardTestDispatcher()
private val testScope = TestScope(dispatcher)
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/pipeline/data/repository/TileSpecSettingsRepositoryTest.kt b/packages/SystemUI/tests/src/com/android/systemui/qs/pipeline/data/repository/TileSpecSettingsRepositoryTest.kt
index 08adebb..f7c3b21 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/pipeline/data/repository/TileSpecSettingsRepositoryTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/pipeline/data/repository/TileSpecSettingsRepositoryTest.kt
@@ -20,7 +20,6 @@
import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.filters.SmallTest
import com.android.systemui.res.R
-import com.android.systemui.RoboPilotTest
import com.android.systemui.SysuiTestCase
import com.android.systemui.coroutines.collectLastValue
import com.android.systemui.qs.pipeline.shared.TileSpec
@@ -40,7 +39,6 @@
import org.mockito.MockitoAnnotations
@SmallTest
-@RoboPilotTest
@RunWith(AndroidJUnit4::class)
@OptIn(ExperimentalCoroutinesApi::class)
class TileSpecSettingsRepositoryTest : SysuiTestCase() {
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/pipeline/data/repository/TilesSettingConverterTest.kt b/packages/SystemUI/tests/src/com/android/systemui/qs/pipeline/data/repository/TilesSettingConverterTest.kt
index 2087623..9516c21 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/pipeline/data/repository/TilesSettingConverterTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/pipeline/data/repository/TilesSettingConverterTest.kt
@@ -2,14 +2,12 @@
import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.filters.SmallTest
-import com.android.systemui.RoboPilotTest
import com.android.systemui.SysuiTestCase
import com.android.systemui.qs.pipeline.shared.TileSpec
import com.google.common.truth.Truth.assertThat
import org.junit.Test
import org.junit.runner.RunWith
-@RoboPilotTest
@SmallTest
@RunWith(AndroidJUnit4::class)
class TilesSettingConverterTest : SysuiTestCase() {
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/pipeline/data/repository/UserAutoAddRepositoryTest.kt b/packages/SystemUI/tests/src/com/android/systemui/qs/pipeline/data/repository/UserAutoAddRepositoryTest.kt
index 81fd72b..36e860e 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/pipeline/data/repository/UserAutoAddRepositoryTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/pipeline/data/repository/UserAutoAddRepositoryTest.kt
@@ -3,7 +3,6 @@
import android.provider.Settings
import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.filters.SmallTest
-import com.android.systemui.RoboPilotTest
import com.android.systemui.SysuiTestCase
import com.android.systemui.coroutines.collectLastValue
import com.android.systemui.qs.pipeline.data.model.RestoreData
@@ -24,7 +23,6 @@
import org.mockito.MockitoAnnotations
@OptIn(ExperimentalCoroutinesApi::class)
-@RoboPilotTest
@SmallTest
@RunWith(AndroidJUnit4::class)
class UserAutoAddRepositoryTest : SysuiTestCase() {
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/pipeline/data/repository/UserTileSpecRepositoryTest.kt b/packages/SystemUI/tests/src/com/android/systemui/qs/pipeline/data/repository/UserTileSpecRepositoryTest.kt
index 389580c1..d4a9fab 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/pipeline/data/repository/UserTileSpecRepositoryTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/pipeline/data/repository/UserTileSpecRepositoryTest.kt
@@ -3,7 +3,6 @@
import android.provider.Settings
import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.filters.SmallTest
-import com.android.systemui.RoboPilotTest
import com.android.systemui.SysuiTestCase
import com.android.systemui.coroutines.collectLastValue
import com.android.systemui.qs.pipeline.data.model.RestoreData
@@ -23,7 +22,6 @@
import org.mockito.Mock
import org.mockito.MockitoAnnotations
-@RoboPilotTest
@SmallTest
@OptIn(ExperimentalCoroutinesApi::class)
@RunWith(AndroidJUnit4::class)
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/pipeline/domain/autoaddable/AutoAddableSettingListTest.kt b/packages/SystemUI/tests/src/com/android/systemui/qs/pipeline/domain/autoaddable/AutoAddableSettingListTest.kt
index 15e401d..4454a3c 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/pipeline/domain/autoaddable/AutoAddableSettingListTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/pipeline/domain/autoaddable/AutoAddableSettingListTest.kt
@@ -20,7 +20,6 @@
import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.filters.SmallTest
import com.android.systemui.res.R
-import com.android.systemui.RoboPilotTest
import com.android.systemui.SysuiTestCase
import com.android.systemui.qs.pipeline.shared.TileSpec
import com.android.systemui.util.mockito.mock
@@ -29,7 +28,6 @@
import org.junit.runner.RunWith
@SmallTest
-@RoboPilotTest
@RunWith(AndroidJUnit4::class)
class AutoAddableSettingListTest : SysuiTestCase() {
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/pipeline/domain/autoaddable/AutoAddableSettingTest.kt b/packages/SystemUI/tests/src/com/android/systemui/qs/pipeline/domain/autoaddable/AutoAddableSettingTest.kt
index 7c6dd24..d153e9d 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/pipeline/domain/autoaddable/AutoAddableSettingTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/pipeline/domain/autoaddable/AutoAddableSettingTest.kt
@@ -18,7 +18,6 @@
import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.filters.SmallTest
-import com.android.systemui.RoboPilotTest
import com.android.systemui.SysuiTestCase
import com.android.systemui.coroutines.collectLastValue
import com.android.systemui.coroutines.collectValues
@@ -36,7 +35,6 @@
@OptIn(ExperimentalCoroutinesApi::class)
@SmallTest
-@RoboPilotTest
@RunWith(AndroidJUnit4::class)
class AutoAddableSettingTest : SysuiTestCase() {
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/pipeline/domain/autoaddable/CallbackControllerAutoAddableTest.kt b/packages/SystemUI/tests/src/com/android/systemui/qs/pipeline/domain/autoaddable/CallbackControllerAutoAddableTest.kt
index 469eee3..ec139e4 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/pipeline/domain/autoaddable/CallbackControllerAutoAddableTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/pipeline/domain/autoaddable/CallbackControllerAutoAddableTest.kt
@@ -18,7 +18,6 @@
import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.filters.SmallTest
-import com.android.systemui.RoboPilotTest
import com.android.systemui.SysuiTestCase
import com.android.systemui.coroutines.collectLastValue
import com.android.systemui.qs.pipeline.domain.model.AutoAddSignal
@@ -36,7 +35,6 @@
@OptIn(ExperimentalCoroutinesApi::class)
@SmallTest
-@RoboPilotTest
@RunWith(AndroidJUnit4::class)
class CallbackControllerAutoAddableTest : SysuiTestCase() {
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/pipeline/domain/autoaddable/CastAutoAddableTest.kt b/packages/SystemUI/tests/src/com/android/systemui/qs/pipeline/domain/autoaddable/CastAutoAddableTest.kt
index b6eaa39..4fae532 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/pipeline/domain/autoaddable/CastAutoAddableTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/pipeline/domain/autoaddable/CastAutoAddableTest.kt
@@ -18,7 +18,6 @@
import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.filters.SmallTest
-import com.android.systemui.RoboPilotTest
import com.android.systemui.SysuiTestCase
import com.android.systemui.coroutines.collectLastValue
import com.android.systemui.qs.pipeline.domain.model.AutoAddSignal
@@ -42,7 +41,6 @@
@OptIn(ExperimentalCoroutinesApi::class)
@SmallTest
-@RoboPilotTest
@RunWith(AndroidJUnit4::class)
class CastAutoAddableTest : SysuiTestCase() {
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/pipeline/domain/autoaddable/DataSaverAutoAddableTest.kt b/packages/SystemUI/tests/src/com/android/systemui/qs/pipeline/domain/autoaddable/DataSaverAutoAddableTest.kt
index a755fbb..9e2d1f8 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/pipeline/domain/autoaddable/DataSaverAutoAddableTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/pipeline/domain/autoaddable/DataSaverAutoAddableTest.kt
@@ -18,7 +18,6 @@
import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.filters.SmallTest
-import com.android.systemui.RoboPilotTest
import com.android.systemui.SysuiTestCase
import com.android.systemui.coroutines.collectLastValue
import com.android.systemui.qs.pipeline.domain.model.AutoAddSignal
@@ -41,7 +40,6 @@
@OptIn(ExperimentalCoroutinesApi::class)
@SmallTest
-@RoboPilotTest
@RunWith(AndroidJUnit4::class)
class DataSaverAutoAddableTest : SysuiTestCase() {
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/pipeline/domain/autoaddable/DeviceControlsAutoAddableTest.kt b/packages/SystemUI/tests/src/com/android/systemui/qs/pipeline/domain/autoaddable/DeviceControlsAutoAddableTest.kt
index daacca51..0116bd9 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/pipeline/domain/autoaddable/DeviceControlsAutoAddableTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/pipeline/domain/autoaddable/DeviceControlsAutoAddableTest.kt
@@ -18,7 +18,6 @@
import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.filters.SmallTest
-import com.android.systemui.RoboPilotTest
import com.android.systemui.SysuiTestCase
import com.android.systemui.coroutines.collectLastValue
import com.android.systemui.qs.pipeline.domain.model.AutoAddSignal
@@ -44,7 +43,6 @@
@OptIn(ExperimentalCoroutinesApi::class)
@SmallTest
-@RoboPilotTest
@RunWith(AndroidJUnit4::class)
class DeviceControlsAutoAddableTest : SysuiTestCase() {
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/pipeline/domain/autoaddable/HotspotAutoAddableTest.kt b/packages/SystemUI/tests/src/com/android/systemui/qs/pipeline/domain/autoaddable/HotspotAutoAddableTest.kt
index 4b5f7f6..e7ea9a6 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/pipeline/domain/autoaddable/HotspotAutoAddableTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/pipeline/domain/autoaddable/HotspotAutoAddableTest.kt
@@ -18,7 +18,6 @@
import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.filters.SmallTest
-import com.android.systemui.RoboPilotTest
import com.android.systemui.SysuiTestCase
import com.android.systemui.coroutines.collectLastValue
import com.android.systemui.qs.pipeline.domain.model.AutoAddSignal
@@ -41,7 +40,6 @@
@OptIn(ExperimentalCoroutinesApi::class)
@SmallTest
-@RoboPilotTest
@RunWith(AndroidJUnit4::class)
class HotspotAutoAddableTest : SysuiTestCase() {
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/pipeline/domain/autoaddable/NightDisplayAutoAddableTest.kt b/packages/SystemUI/tests/src/com/android/systemui/qs/pipeline/domain/autoaddable/NightDisplayAutoAddableTest.kt
index 32d9db2..20fd360 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/pipeline/domain/autoaddable/NightDisplayAutoAddableTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/pipeline/domain/autoaddable/NightDisplayAutoAddableTest.kt
@@ -19,7 +19,6 @@
import android.hardware.display.NightDisplayListener
import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.filters.SmallTest
-import com.android.systemui.RoboPilotTest
import com.android.systemui.SysuiTestCase
import com.android.systemui.coroutines.collectLastValue
import com.android.systemui.dagger.NightDisplayListenerModule
@@ -50,7 +49,6 @@
@OptIn(ExperimentalCoroutinesApi::class)
@SmallTest
-@RoboPilotTest
@RunWith(AndroidJUnit4::class)
class NightDisplayAutoAddableTest : SysuiTestCase() {
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/pipeline/domain/autoaddable/ReduceBrightColorsAutoAddableTest.kt b/packages/SystemUI/tests/src/com/android/systemui/qs/pipeline/domain/autoaddable/ReduceBrightColorsAutoAddableTest.kt
index fb513a6..19ac63c 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/pipeline/domain/autoaddable/ReduceBrightColorsAutoAddableTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/pipeline/domain/autoaddable/ReduceBrightColorsAutoAddableTest.kt
@@ -18,7 +18,6 @@
import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.filters.SmallTest
-import com.android.systemui.RoboPilotTest
import com.android.systemui.SysuiTestCase
import com.android.systemui.coroutines.collectLastValue
import com.android.systemui.qs.ReduceBrightColorsController
@@ -44,7 +43,6 @@
@OptIn(ExperimentalCoroutinesApi::class)
@SmallTest
-@RoboPilotTest
@RunWith(AndroidJUnit4::class)
class ReduceBrightColorsAutoAddableTest : SysuiTestCase() {
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/pipeline/domain/autoaddable/SafetyCenterAutoAddableTest.kt b/packages/SystemUI/tests/src/com/android/systemui/qs/pipeline/domain/autoaddable/SafetyCenterAutoAddableTest.kt
index 5ce15fa..d645ee3 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/pipeline/domain/autoaddable/SafetyCenterAutoAddableTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/pipeline/domain/autoaddable/SafetyCenterAutoAddableTest.kt
@@ -21,7 +21,6 @@
import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.filters.SmallTest
import com.android.systemui.res.R
-import com.android.systemui.RoboPilotTest
import com.android.systemui.SysuiTestCase
import com.android.systemui.coroutines.collectLastValue
import com.android.systemui.coroutines.collectValues
@@ -52,7 +51,6 @@
@OptIn(ExperimentalCoroutinesApi::class)
@SmallTest
-@RoboPilotTest
@RunWith(AndroidJUnit4::class)
class SafetyCenterAutoAddableTest : SysuiTestCase() {
private val testDispatcher = StandardTestDispatcher()
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/pipeline/domain/autoaddable/WalletAutoAddableTest.kt b/packages/SystemUI/tests/src/com/android/systemui/qs/pipeline/domain/autoaddable/WalletAutoAddableTest.kt
index 1c8cb54..83ff35d 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/pipeline/domain/autoaddable/WalletAutoAddableTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/pipeline/domain/autoaddable/WalletAutoAddableTest.kt
@@ -18,7 +18,6 @@
import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.filters.SmallTest
-import com.android.systemui.RoboPilotTest
import com.android.systemui.SysuiTestCase
import com.android.systemui.coroutines.collectLastValue
import com.android.systemui.qs.pipeline.domain.model.AutoAddSignal
@@ -38,7 +37,6 @@
@OptIn(ExperimentalCoroutinesApi::class)
@SmallTest
-@RoboPilotTest
@RunWith(AndroidJUnit4::class)
class WalletAutoAddableTest : SysuiTestCase() {
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/pipeline/domain/autoaddable/WorkTileAutoAddableTest.kt b/packages/SystemUI/tests/src/com/android/systemui/qs/pipeline/domain/autoaddable/WorkTileAutoAddableTest.kt
index de1d29fd..adccc84 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/pipeline/domain/autoaddable/WorkTileAutoAddableTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/pipeline/domain/autoaddable/WorkTileAutoAddableTest.kt
@@ -23,7 +23,6 @@
import android.content.pm.UserInfo.FLAG_PROFILE
import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.filters.SmallTest
-import com.android.systemui.RoboPilotTest
import com.android.systemui.SysuiTestCase
import com.android.systemui.coroutines.collectLastValue
import com.android.systemui.qs.pipeline.domain.model.AutoAddSignal
@@ -41,7 +40,6 @@
@OptIn(ExperimentalCoroutinesApi::class)
@SmallTest
-@RoboPilotTest
@RunWith(AndroidJUnit4::class)
class WorkTileAutoAddableTest : SysuiTestCase() {
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/pipeline/domain/interactor/AutoAddInteractorTest.kt b/packages/SystemUI/tests/src/com/android/systemui/qs/pipeline/domain/interactor/AutoAddInteractorTest.kt
index bb18115..41a7ec0 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/pipeline/domain/interactor/AutoAddInteractorTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/pipeline/domain/interactor/AutoAddInteractorTest.kt
@@ -18,7 +18,6 @@
import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.filters.SmallTest
-import com.android.systemui.RoboPilotTest
import com.android.systemui.SysuiTestCase
import com.android.systemui.coroutines.collectLastValue
import com.android.systemui.dump.DumpManager
@@ -47,7 +46,6 @@
import org.mockito.MockitoAnnotations
@SmallTest
-@RoboPilotTest
@RunWith(AndroidJUnit4::class)
@OptIn(ExperimentalCoroutinesApi::class)
class AutoAddInteractorTest : SysuiTestCase() {
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/pipeline/domain/interactor/CurrentTilesInteractorImplTest.kt b/packages/SystemUI/tests/src/com/android/systemui/qs/pipeline/domain/interactor/CurrentTilesInteractorImplTest.kt
index a750524..a89338a 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/pipeline/domain/interactor/CurrentTilesInteractorImplTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/pipeline/domain/interactor/CurrentTilesInteractorImplTest.kt
@@ -24,7 +24,6 @@
import android.service.quicksettings.Tile
import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.filters.SmallTest
-import com.android.systemui.RoboPilotTest
import com.android.systemui.SysuiTestCase
import com.android.systemui.coroutines.collectLastValue
import com.android.systemui.dump.nano.SystemUIProtoDump
@@ -71,7 +70,6 @@
import org.mockito.MockitoAnnotations
@SmallTest
-@RoboPilotTest
@RunWith(AndroidJUnit4::class)
@OptIn(ExperimentalCoroutinesApi::class)
class CurrentTilesInteractorImplTest : SysuiTestCase() {
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/pipeline/domain/interactor/PanelInteractorImplTest.kt b/packages/SystemUI/tests/src/com/android/systemui/qs/pipeline/domain/interactor/PanelInteractorImplTest.kt
index 151b256..0d97115 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/pipeline/domain/interactor/PanelInteractorImplTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/pipeline/domain/interactor/PanelInteractorImplTest.kt
@@ -17,7 +17,6 @@
import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.filters.SmallTest
-import com.android.systemui.RoboPilotTest
import com.android.systemui.SysuiTestCase
import com.android.systemui.shade.ShadeController
import org.junit.Before
@@ -27,7 +26,6 @@
import org.mockito.Mockito.verify
import org.mockito.MockitoAnnotations
-@RoboPilotTest
@RunWith(AndroidJUnit4::class)
@SmallTest
class PanelInteractorImplTest : SysuiTestCase() {
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/pipeline/domain/interactor/RestoreReconciliationInteractorTest.kt b/packages/SystemUI/tests/src/com/android/systemui/qs/pipeline/domain/interactor/RestoreReconciliationInteractorTest.kt
index 2e6b50b..f73cab8 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/pipeline/domain/interactor/RestoreReconciliationInteractorTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/pipeline/domain/interactor/RestoreReconciliationInteractorTest.kt
@@ -2,7 +2,6 @@
import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.filters.SmallTest
-import com.android.systemui.RoboPilotTest
import com.android.systemui.SysuiTestCase
import com.android.systemui.coroutines.collectLastValue
import com.android.systemui.qs.pipeline.data.model.RestoreData
@@ -20,7 +19,6 @@
import org.junit.runner.RunWith
import org.mockito.MockitoAnnotations
-@RoboPilotTest
@RunWith(AndroidJUnit4::class)
@SmallTest
class RestoreReconciliationInteractorTest : SysuiTestCase() {
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/pipeline/shared/TileSpecTest.kt b/packages/SystemUI/tests/src/com/android/systemui/qs/pipeline/shared/TileSpecTest.kt
index 34c4c98..558e769 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/pipeline/shared/TileSpecTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/pipeline/shared/TileSpecTest.kt
@@ -19,14 +19,12 @@
import android.content.ComponentName
import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.filters.SmallTest
-import com.android.systemui.RoboPilotTest
import com.android.systemui.SysuiTestCase
import com.google.common.truth.Truth.assertThat
import org.junit.Test
import org.junit.runner.RunWith
@SmallTest
-@RoboPilotTest
@RunWith(AndroidJUnit4::class)
class TileSpecTest : SysuiTestCase() {
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/base/actions/QSTileIntentUserActionHandlerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/base/actions/QSTileIntentUserActionHandlerTest.kt
index 06b7a9f..5659f01 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/base/actions/QSTileIntentUserActionHandlerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/base/actions/QSTileIntentUserActionHandlerTest.kt
@@ -19,7 +19,6 @@
import android.content.Intent
import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.filters.SmallTest
-import com.android.systemui.RoboPilotTest
import com.android.systemui.SysuiTestCase
import com.android.systemui.plugins.ActivityStarter
import org.junit.Before
@@ -32,7 +31,6 @@
import org.mockito.MockitoAnnotations
@SmallTest
-@RoboPilotTest
@RunWith(AndroidJUnit4::class)
class QSTileIntentUserActionHandlerTest : SysuiTestCase() {
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/base/analytics/QSTileAnalyticsTest.kt b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/base/analytics/QSTileAnalyticsTest.kt
index 2c4e10e..9861606 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/base/analytics/QSTileAnalyticsTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/base/analytics/QSTileAnalyticsTest.kt
@@ -20,7 +20,6 @@
import androidx.test.filters.SmallTest
import com.android.internal.logging.InstanceId
import com.android.internal.logging.UiEventLogger
-import com.android.systemui.RoboPilotTest
import com.android.systemui.SysuiTestCase
import com.android.systemui.qs.QSEvent
import com.android.systemui.qs.tiles.viewmodel.QSTileConfigTestBuilder
@@ -34,7 +33,6 @@
import org.mockito.MockitoAnnotations
@SmallTest
-@RoboPilotTest
@RunWith(AndroidJUnit4::class)
class QSTileAnalyticsTest : SysuiTestCase() {
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/base/interactor/DisabledByPolicyInteractorTest.kt b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/base/interactor/DisabledByPolicyInteractorTest.kt
index 4f25d12..a6199c2 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/base/interactor/DisabledByPolicyInteractorTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/base/interactor/DisabledByPolicyInteractorTest.kt
@@ -24,7 +24,6 @@
import androidx.test.filters.SmallTest
import com.android.settingslib.RestrictedLockUtils
import com.android.settingslib.RestrictedLockUtils.EnforcedAdmin
-import com.android.systemui.RoboPilotTest
import com.android.systemui.SysuiTestCase
import com.android.systemui.plugins.ActivityStarter
import com.android.systemui.util.mockito.any
@@ -46,7 +45,6 @@
import org.mockito.MockitoAnnotations
@SmallTest
-@RoboPilotTest
@RunWith(AndroidJUnit4::class)
class DisabledByPolicyInteractorTest : SysuiTestCase() {
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/base/logging/QSTileLoggerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/base/logging/QSTileLoggerTest.kt
index 4401e0d..f1fcee3 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/base/logging/QSTileLoggerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/base/logging/QSTileLoggerTest.kt
@@ -18,7 +18,6 @@
import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.filters.SmallTest
-import com.android.systemui.RoboPilotTest
import com.android.systemui.SysuiTestCase
import com.android.systemui.common.shared.model.ContentDescription
import com.android.systemui.common.shared.model.Icon
@@ -39,7 +38,6 @@
import org.mockito.MockitoAnnotations
@SmallTest
-@RoboPilotTest
@RunWith(AndroidJUnit4::class)
class QSTileLoggerTest : SysuiTestCase() {
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/viewmodel/QSTileViewModelInterfaceComplianceTest.kt b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/viewmodel/QSTileViewModelInterfaceComplianceTest.kt
index 4760dfa..2084aeb 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/viewmodel/QSTileViewModelInterfaceComplianceTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/viewmodel/QSTileViewModelInterfaceComplianceTest.kt
@@ -20,7 +20,6 @@
import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.filters.MediumTest
import com.android.internal.logging.InstanceId
-import com.android.systemui.RoboPilotTest
import com.android.systemui.SysuiTestCase
import com.android.systemui.classifier.FalsingManagerFake
import com.android.systemui.common.shared.model.ContentDescription
@@ -49,7 +48,6 @@
// TODO(b/299909368): Add more tests
@MediumTest
-@RoboPilotTest
@RunWith(AndroidJUnit4::class)
@TestableLooper.RunWithLooper(setAsMainLooper = true)
class QSTileViewModelInterfaceComplianceTest : SysuiTestCase() {
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/ui/viewmodel/QuickSettingsSceneViewModelTest.kt b/packages/SystemUI/tests/src/com/android/systemui/qs/ui/viewmodel/QuickSettingsSceneViewModelTest.kt
index f1c99d7..58e36be 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/ui/viewmodel/QuickSettingsSceneViewModelTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/ui/viewmodel/QuickSettingsSceneViewModelTest.kt
@@ -16,6 +16,7 @@
package com.android.systemui.qs.ui.viewmodel
+import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.filters.SmallTest
import com.android.systemui.SysuiTestCase
import com.android.systemui.authentication.data.model.AuthenticationMethodModel
@@ -38,11 +39,10 @@
import org.junit.Before
import org.junit.Test
import org.junit.runner.RunWith
-import org.junit.runners.JUnit4
@OptIn(ExperimentalCoroutinesApi::class)
@SmallTest
-@RunWith(JUnit4::class)
+@RunWith(AndroidJUnit4::class)
class QuickSettingsSceneViewModelTest : SysuiTestCase() {
private val utils = SceneTestUtils(this)
diff --git a/packages/SystemUI/tests/src/com/android/systemui/scene/SceneFrameworkIntegrationTest.kt b/packages/SystemUI/tests/src/com/android/systemui/scene/SceneFrameworkIntegrationTest.kt
index 91f3865..2e16577 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/scene/SceneFrameworkIntegrationTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/scene/SceneFrameworkIntegrationTest.kt
@@ -18,6 +18,7 @@
package com.android.systemui.scene
+import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.filters.SmallTest
import com.android.systemui.SysuiTestCase
import com.android.systemui.authentication.data.repository.FakeAuthenticationRepository
@@ -51,6 +52,7 @@
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.Job
import kotlinx.coroutines.flow.MutableStateFlow
+import kotlinx.coroutines.flow.flowOf
import kotlinx.coroutines.launch
import kotlinx.coroutines.test.TestScope
import kotlinx.coroutines.test.runCurrent
@@ -58,7 +60,6 @@
import org.junit.Before
import org.junit.Test
import org.junit.runner.RunWith
-import org.junit.runners.JUnit4
/**
* Integration test cases for the Scene Framework.
@@ -80,7 +81,7 @@
*/
@OptIn(ExperimentalCoroutinesApi::class)
@SmallTest
-@RunWith(JUnit4::class)
+@RunWith(AndroidJUnit4::class)
class SceneFrameworkIntegrationTest : SysuiTestCase() {
private val utils = SceneTestUtils(this)
@@ -462,7 +463,8 @@
fromScene = getCurrentSceneInUi(),
toScene = to.key,
progress = progressFlow,
- isUserInputDriven = false,
+ isInitiatedByUserInput = false,
+ isUserInputOngoing = flowOf(false),
)
runCurrent()
diff --git a/packages/SystemUI/tests/src/com/android/systemui/scene/data/repository/SceneContainerRepositoryTest.kt b/packages/SystemUI/tests/src/com/android/systemui/scene/data/repository/SceneContainerRepositoryTest.kt
index ff28d2d..740c6d9 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/scene/data/repository/SceneContainerRepositoryTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/scene/data/repository/SceneContainerRepositoryTest.kt
@@ -18,6 +18,7 @@
package com.android.systemui.scene.data.repository
+import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.filters.SmallTest
import com.android.systemui.SysuiTestCase
import com.android.systemui.coroutines.collectLastValue
@@ -28,13 +29,13 @@
import com.google.common.truth.Truth.assertThat
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.flow.MutableStateFlow
+import kotlinx.coroutines.flow.flowOf
import kotlinx.coroutines.test.runTest
import org.junit.Test
import org.junit.runner.RunWith
-import org.junit.runners.JUnit4
@SmallTest
-@RunWith(JUnit4::class)
+@RunWith(AndroidJUnit4::class)
class SceneContainerRepositoryTest : SysuiTestCase() {
private val utils = SceneTestUtils(this)
@@ -119,7 +120,8 @@
fromScene = SceneKey.Lockscreen,
toScene = SceneKey.Shade,
progress = progress,
- isUserInputDriven = false,
+ isInitiatedByUserInput = false,
+ isUserInputOngoing = flowOf(false),
)
assertThat(reflectedTransitionState).isEqualTo(transitionState.value)
diff --git a/packages/SystemUI/tests/src/com/android/systemui/scene/data/repository/WindowRootViewVisibilityRepositoryTest.kt b/packages/SystemUI/tests/src/com/android/systemui/scene/data/repository/WindowRootViewVisibilityRepositoryTest.kt
index 2187f36..7ae501d 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/scene/data/repository/WindowRootViewVisibilityRepositoryTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/scene/data/repository/WindowRootViewVisibilityRepositoryTest.kt
@@ -16,6 +16,7 @@
package com.android.systemui.scene.data.repository
+import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.filters.SmallTest
import com.android.internal.statusbar.IStatusBarService
import com.android.systemui.SysuiTestCase
@@ -24,9 +25,11 @@
import com.android.systemui.util.time.FakeSystemClock
import com.google.common.truth.Truth.assertThat
import org.junit.Test
+import org.junit.runner.RunWith
import org.mockito.Mockito.verify
@SmallTest
+@RunWith(AndroidJUnit4::class)
class WindowRootViewVisibilityRepositoryTest : SysuiTestCase() {
private val iStatusBarService = mock<IStatusBarService>()
private val executor = FakeExecutor(FakeSystemClock())
diff --git a/packages/SystemUI/tests/src/com/android/systemui/scene/domain/interactor/SceneInteractorTest.kt b/packages/SystemUI/tests/src/com/android/systemui/scene/domain/interactor/SceneInteractorTest.kt
index afc0e69..31d26c0 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/scene/domain/interactor/SceneInteractorTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/scene/domain/interactor/SceneInteractorTest.kt
@@ -14,10 +14,9 @@
* limitations under the License.
*/
-@file:OptIn(ExperimentalCoroutinesApi::class, ExperimentalCoroutinesApi::class)
-
package com.android.systemui.scene.domain.interactor
+import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.filters.SmallTest
import com.android.systemui.SysuiTestCase
import com.android.systemui.coroutines.collectLastValue
@@ -26,16 +25,14 @@
import com.android.systemui.scene.shared.model.SceneKey
import com.android.systemui.scene.shared.model.SceneModel
import com.google.common.truth.Truth.assertThat
-import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.flowOf
import kotlinx.coroutines.test.runTest
import org.junit.Test
import org.junit.runner.RunWith
-import org.junit.runners.JUnit4
@SmallTest
-@RunWith(JUnit4::class)
+@RunWith(AndroidJUnit4::class)
class SceneInteractorTest : SysuiTestCase() {
private val utils = SceneTestUtils(this)
@@ -86,7 +83,8 @@
fromScene = SceneKey.Lockscreen,
toScene = SceneKey.Shade,
progress = progress,
- isUserInputDriven = false,
+ isInitiatedByUserInput = false,
+ isUserInputOngoing = flowOf(false),
)
assertThat(reflectedTransitionState).isEqualTo(transitionState.value)
@@ -124,7 +122,8 @@
fromScene = underTest.desiredScene.value.key,
toScene = SceneKey.Shade,
progress = progress,
- isUserInputDriven = false,
+ isInitiatedByUserInput = false,
+ isUserInputOngoing = flowOf(false),
)
assertThat(transitionTo).isEqualTo(SceneKey.Shade)
@@ -161,7 +160,8 @@
fromScene = SceneKey.Gone,
toScene = SceneKey.Lockscreen,
progress = flowOf(0.5f),
- isUserInputDriven = false,
+ isInitiatedByUserInput = false,
+ isUserInputOngoing = flowOf(false),
)
)
val transitioning by
@@ -180,7 +180,8 @@
fromScene = SceneKey.Shade,
toScene = SceneKey.QuickSettings,
progress = flowOf(0.5f),
- isUserInputDriven = false,
+ isInitiatedByUserInput = false,
+ isUserInputOngoing = flowOf(false),
)
)
underTest.setTransitionState(transitionState)
@@ -197,7 +198,8 @@
fromScene = SceneKey.Shade,
toScene = SceneKey.Lockscreen,
progress = flowOf(0.5f),
- isUserInputDriven = false,
+ isInitiatedByUserInput = false,
+ isUserInputOngoing = flowOf(false),
)
)
val transitioning by
@@ -225,7 +227,8 @@
fromScene = SceneKey.Shade,
toScene = SceneKey.Lockscreen,
progress = flowOf(0.5f),
- isUserInputDriven = false,
+ isInitiatedByUserInput = false,
+ isUserInputOngoing = flowOf(false),
)
assertThat(transitioning).isTrue()
diff --git a/packages/SystemUI/tests/src/com/android/systemui/scene/domain/interactor/WindowRootViewVisibilityInteractorTest.kt b/packages/SystemUI/tests/src/com/android/systemui/scene/domain/interactor/WindowRootViewVisibilityInteractorTest.kt
index 3785fd7..8be4eeb 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/scene/domain/interactor/WindowRootViewVisibilityInteractorTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/scene/domain/interactor/WindowRootViewVisibilityInteractorTest.kt
@@ -16,6 +16,7 @@
package com.android.systemui.scene.domain.interactor
+import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.filters.SmallTest
import com.android.internal.statusbar.IStatusBarService
import com.android.systemui.SysuiTestCase
@@ -36,16 +37,16 @@
import com.android.systemui.util.mockito.whenever
import com.android.systemui.util.time.FakeSystemClock
import com.google.common.truth.Truth.assertThat
-import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.test.TestScope
import kotlinx.coroutines.test.runCurrent
import kotlinx.coroutines.test.runTest
import org.junit.Test
+import org.junit.runner.RunWith
import org.mockito.Mockito.reset
import org.mockito.Mockito.verify
@SmallTest
-@OptIn(ExperimentalCoroutinesApi::class)
+@RunWith(AndroidJUnit4::class)
class WindowRootViewVisibilityInteractorTest : SysuiTestCase() {
private val testScope = TestScope()
diff --git a/packages/SystemUI/tests/src/com/android/systemui/scene/domain/startable/SceneContainerStartableTest.kt b/packages/SystemUI/tests/src/com/android/systemui/scene/domain/startable/SceneContainerStartableTest.kt
index 0216a0a..3b9621e 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/scene/domain/startable/SceneContainerStartableTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/scene/domain/startable/SceneContainerStartableTest.kt
@@ -20,6 +20,7 @@
import android.os.PowerManager
import android.view.Display
+import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.filters.SmallTest
import com.android.systemui.SysuiTestCase
import com.android.systemui.authentication.domain.model.AuthenticationMethodModel
@@ -46,14 +47,13 @@
import org.junit.Assume.assumeTrue
import org.junit.Test
import org.junit.runner.RunWith
-import org.junit.runners.JUnit4
import org.mockito.Mockito.clearInvocations
import org.mockito.Mockito.never
import org.mockito.Mockito.times
import org.mockito.Mockito.verify
@SmallTest
-@RunWith(JUnit4::class)
+@RunWith(AndroidJUnit4::class)
class SceneContainerStartableTest : SysuiTestCase() {
private val utils = SceneTestUtils(this)
@@ -109,7 +109,8 @@
fromScene = SceneKey.Gone,
toScene = SceneKey.Shade,
progress = flowOf(0.5f),
- isUserInputDriven = false,
+ isInitiatedByUserInput = false,
+ isUserInputOngoing = flowOf(false),
)
assertThat(isVisible).isTrue()
sceneInteractor.onSceneChanged(SceneModel(SceneKey.Shade), "reason")
@@ -122,7 +123,8 @@
fromScene = SceneKey.Shade,
toScene = SceneKey.Gone,
progress = flowOf(0.5f),
- isUserInputDriven = false,
+ isInitiatedByUserInput = false,
+ isUserInputOngoing = flowOf(false),
)
assertThat(isVisible).isTrue()
sceneInteractor.onSceneChanged(SceneModel(SceneKey.Gone), "reason")
diff --git a/packages/SystemUI/tests/src/com/android/systemui/scene/ui/viewmodel/SceneContainerViewModelTest.kt b/packages/SystemUI/tests/src/com/android/systemui/scene/ui/viewmodel/SceneContainerViewModelTest.kt
index 0b56a59..c89cd9e 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/scene/ui/viewmodel/SceneContainerViewModelTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/scene/ui/viewmodel/SceneContainerViewModelTest.kt
@@ -18,6 +18,7 @@
package com.android.systemui.scene.ui.viewmodel
+import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.filters.SmallTest
import com.android.systemui.SysuiTestCase
import com.android.systemui.coroutines.collectLastValue
@@ -29,10 +30,9 @@
import kotlinx.coroutines.test.runTest
import org.junit.Test
import org.junit.runner.RunWith
-import org.junit.runners.JUnit4
@SmallTest
-@RunWith(JUnit4::class)
+@RunWith(AndroidJUnit4::class)
class SceneContainerViewModelTest : SysuiTestCase() {
private val utils = SceneTestUtils(this)
diff --git a/packages/SystemUI/tests/src/com/android/systemui/settings/UserTrackerImplReceiveTest.kt b/packages/SystemUI/tests/src/com/android/systemui/settings/UserTrackerImplReceiveTest.kt
index 1bb2ff8..263b001 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/settings/UserTrackerImplReceiveTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/settings/UserTrackerImplReceiveTest.kt
@@ -42,6 +42,7 @@
@Parameterized.Parameters
fun data(): Iterable<String> =
listOf(
+ Intent.ACTION_LOCALE_CHANGED,
Intent.ACTION_USER_INFO_CHANGED,
Intent.ACTION_MANAGED_PROFILE_AVAILABLE,
Intent.ACTION_MANAGED_PROFILE_UNAVAILABLE,
diff --git a/packages/SystemUI/tests/src/com/android/systemui/settings/UserTrackerImplTest.kt b/packages/SystemUI/tests/src/com/android/systemui/settings/UserTrackerImplTest.kt
index 52b25f8..c32d259 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/settings/UserTrackerImplTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/settings/UserTrackerImplTest.kt
@@ -177,7 +177,8 @@
verify(context)
.registerReceiverForAllUsers(eq(tracker), capture(captor), isNull(), eq(handler))
with(captor.value) {
- assertThat(countActions()).isEqualTo(6)
+ assertThat(countActions()).isEqualTo(7)
+ assertThat(hasAction(Intent.ACTION_LOCALE_CHANGED)).isTrue()
assertThat(hasAction(Intent.ACTION_USER_INFO_CHANGED)).isTrue()
assertThat(hasAction(Intent.ACTION_MANAGED_PROFILE_AVAILABLE)).isTrue()
assertThat(hasAction(Intent.ACTION_MANAGED_PROFILE_UNAVAILABLE)).isTrue()
diff --git a/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationPanelViewControllerBaseTest.java b/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationPanelViewControllerBaseTest.java
index 7b12931..8d8c70e 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationPanelViewControllerBaseTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationPanelViewControllerBaseTest.java
@@ -79,7 +79,6 @@
import com.android.keyguard.dagger.KeyguardStatusViewComponent;
import com.android.keyguard.dagger.KeyguardUserSwitcherComponent;
import com.android.keyguard.logging.KeyguardLogger;
-import com.android.systemui.res.R;
import com.android.systemui.SysuiTestCase;
import com.android.systemui.biometrics.AuthController;
import com.android.systemui.bouncer.domain.interactor.AlternateBouncerInteractor;
@@ -120,6 +119,7 @@
import com.android.systemui.plugins.qs.QS;
import com.android.systemui.power.domain.interactor.PowerInteractor;
import com.android.systemui.qs.QSFragmentLegacy;
+import com.android.systemui.res.R;
import com.android.systemui.screenrecord.RecordingController;
import com.android.systemui.shade.data.repository.FakeShadeRepository;
import com.android.systemui.shade.data.repository.ShadeRepository;
@@ -153,7 +153,6 @@
import com.android.systemui.statusbar.phone.ConfigurationControllerImpl;
import com.android.systemui.statusbar.phone.DozeParameters;
import com.android.systemui.statusbar.phone.HeadsUpAppearanceController;
-import com.android.systemui.statusbar.phone.HeadsUpManagerPhone;
import com.android.systemui.statusbar.phone.HeadsUpTouchHelper;
import com.android.systemui.statusbar.phone.KeyguardBottomAreaView;
import com.android.systemui.statusbar.phone.KeyguardBottomAreaViewController;
@@ -170,6 +169,7 @@
import com.android.systemui.statusbar.phone.UnlockedScreenOffAnimationController;
import com.android.systemui.statusbar.policy.CastController;
import com.android.systemui.statusbar.policy.ConfigurationController;
+import com.android.systemui.statusbar.policy.HeadsUpManager;
import com.android.systemui.statusbar.policy.KeyguardQsUserSwitchController;
import com.android.systemui.statusbar.policy.KeyguardStateController;
import com.android.systemui.statusbar.policy.KeyguardUserSwitcherController;
@@ -182,6 +182,8 @@
import com.android.systemui.util.time.SystemClock;
import com.android.wm.shell.animation.FlingAnimationUtils;
+import dagger.Lazy;
+
import org.junit.After;
import org.junit.Before;
import org.mockito.ArgumentCaptor;
@@ -193,7 +195,6 @@
import java.util.List;
import java.util.Optional;
-import dagger.Lazy;
import kotlinx.coroutines.CoroutineDispatcher;
public class NotificationPanelViewControllerBaseTest extends SysuiTestCase {
@@ -208,7 +209,7 @@
@Mock protected KeyguardBottomAreaViewController mKeyguardBottomAreaViewController;
@Mock protected ViewPropertyAnimator mViewPropertyAnimator;
@Mock protected KeyguardBottomAreaView mQsFrame;
- @Mock protected HeadsUpManagerPhone mHeadsUpManager;
+ @Mock protected HeadsUpManager mHeadsUpManager;
@Mock protected NotificationShelfController mNotificationShelfController;
@Mock protected NotificationGutsManager mGutsManager;
@Mock protected KeyguardStatusBarView mKeyguardStatusBar;
@@ -527,7 +528,7 @@
NotificationWakeUpCoordinator coordinator =
new NotificationWakeUpCoordinator(
mDumpManager,
- mock(HeadsUpManagerPhone.class),
+ mock(HeadsUpManager.class),
new StatusBarStateControllerImpl(new UiEventLoggerFake(), mDumpManager,
mInteractionJankMonitor, mShadeExpansionStateManager),
mKeyguardBypassController,
@@ -547,7 +548,7 @@
mLockscreenShadeTransitionController,
new FalsingCollectorFake(),
mDumpManager);
- when(mKeyguardStatusViewComponentFactory.build(any()))
+ when(mKeyguardStatusViewComponentFactory.build(any(), any()))
.thenReturn(mKeyguardStatusViewComponent);
when(mKeyguardStatusViewComponent.getKeyguardClockSwitchController())
.thenReturn(mKeyguardClockSwitchController);
diff --git a/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationShadeWindowControllerImplTest.java b/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationShadeWindowControllerImplTest.java
index 2ed2090..eb00610 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationShadeWindowControllerImplTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationShadeWindowControllerImplTest.java
@@ -47,18 +47,34 @@
import androidx.test.filters.SmallTest;
import com.android.internal.colorextraction.ColorExtractor;
+import com.android.keyguard.KeyguardSecurityModel;
import com.android.systemui.SysuiTestCase;
import com.android.systemui.biometrics.AuthController;
+import com.android.systemui.bouncer.data.repository.FakeKeyguardBouncerRepository;
+import com.android.systemui.classifier.FalsingCollectorFake;
import com.android.systemui.colorextraction.SysuiColorExtractor;
import com.android.systemui.common.ui.data.repository.FakeConfigurationRepository;
+import com.android.systemui.deviceentry.data.repository.FakeDeviceEntryRepository;
import com.android.systemui.dump.DumpManager;
+import com.android.systemui.flags.FakeFeatureFlagsClassic;
import com.android.systemui.keyguard.KeyguardViewMediator;
+import com.android.systemui.keyguard.data.repository.FakeCommandQueue;
import com.android.systemui.keyguard.data.repository.FakeKeyguardRepository;
+import com.android.systemui.keyguard.data.repository.FakeKeyguardTransitionRepository;
+import com.android.systemui.keyguard.domain.interactor.FromLockscreenTransitionInteractor;
+import com.android.systemui.keyguard.domain.interactor.FromPrimaryBouncerTransitionInteractor;
+import com.android.systemui.keyguard.domain.interactor.KeyguardInteractor;
+import com.android.systemui.keyguard.domain.interactor.KeyguardTransitionInteractor;
import com.android.systemui.plugins.statusbar.StatusBarStateController;
+import com.android.systemui.power.data.repository.FakePowerRepository;
+import com.android.systemui.power.domain.interactor.PowerInteractor;
import com.android.systemui.res.R;
import com.android.systemui.scene.FakeWindowRootViewComponent;
import com.android.systemui.scene.SceneTestUtils;
+import com.android.systemui.scene.data.repository.SceneContainerRepository;
+import com.android.systemui.scene.domain.interactor.SceneInteractor;
import com.android.systemui.scene.shared.flag.FakeSceneContainerFlags;
+import com.android.systemui.scene.shared.logger.SceneLogger;
import com.android.systemui.shade.data.repository.FakeShadeRepository;
import com.android.systemui.shade.domain.interactor.ShadeInteractor;
import com.android.systemui.statusbar.StatusBarState;
@@ -71,9 +87,9 @@
import com.android.systemui.statusbar.phone.ScrimController;
import com.android.systemui.statusbar.pipeline.mobile.data.repository.FakeUserSetupRepository;
import com.android.systemui.statusbar.policy.ConfigurationController;
-import com.android.systemui.statusbar.policy.DeviceProvisionedController;
import com.android.systemui.statusbar.policy.KeyguardStateController;
import com.android.systemui.statusbar.policy.ResourcesSplitShadeStateController;
+import com.android.systemui.statusbar.policy.data.repository.FakeDeviceProvisioningRepository;
import com.android.systemui.user.domain.interactor.UserInteractor;
import com.google.common.util.concurrent.MoreExecutors;
@@ -109,6 +125,7 @@
@Mock private SysuiColorExtractor mColorExtractor;
@Mock ColorExtractor.GradientColors mGradientColors;
@Mock private DumpManager mDumpManager;
+ @Mock private KeyguardSecurityModel mKeyguardSecurityModel;
@Mock private KeyguardStateController mKeyguardStateController;
@Mock private ScreenOffAnimationController mScreenOffAnimationController;
@Mock private AuthController mAuthController;
@@ -123,6 +140,8 @@
private NotificationShadeWindowControllerImpl mNotificationShadeWindowController;
private float mPreferredRefreshRate = -1;
+ private FromLockscreenTransitionInteractor mFromLockscreenTransitionInteractor;
+ private FromPrimaryBouncerTransitionInteractor mFromPrimaryBouncerTransitionInteractor;
@Before
public void setUp() {
@@ -137,22 +156,86 @@
when(mDozeParameters.getAlwaysOn()).thenReturn(true);
when(mColorExtractor.getNeutralColors()).thenReturn(mGradientColors);
+ FakeKeyguardRepository keyguardRepository = new FakeKeyguardRepository();
+ FakeFeatureFlagsClassic featureFlags = new FakeFeatureFlagsClassic();
+ FakeShadeRepository shadeRepository = new FakeShadeRepository();
+ FakePowerRepository powerRepository = new FakePowerRepository();
+
+ PowerInteractor powerInteractor = new PowerInteractor(
+ powerRepository,
+ new FalsingCollectorFake(),
+ mScreenOffAnimationController,
+ mStatusBarStateController);
+
+ SceneInteractor sceneInteractor = new SceneInteractor(
+ mTestScope.getBackgroundScope(),
+ new SceneContainerRepository(
+ mTestScope.getBackgroundScope(),
+ mUtils.fakeSceneContainerConfig(mUtils.fakeSceneKeys())),
+ powerRepository,
+ mock(SceneLogger.class));
+
+ FakeConfigurationRepository configurationRepository = new FakeConfigurationRepository();
+ FakeSceneContainerFlags sceneContainerFlags = new FakeSceneContainerFlags();
+ KeyguardInteractor keyguardInteractor = new KeyguardInteractor(
+ keyguardRepository,
+ new FakeCommandQueue(),
+ powerInteractor,
+ featureFlags,
+ sceneContainerFlags,
+ new FakeDeviceEntryRepository(),
+ new FakeKeyguardBouncerRepository(),
+ configurationRepository,
+ shadeRepository,
+ () -> sceneInteractor);
+
+ FakeKeyguardTransitionRepository keyguardTransitionRepository =
+ new FakeKeyguardTransitionRepository();
+
+ KeyguardTransitionInteractor keyguardTransitionInteractor =
+ new KeyguardTransitionInteractor(
+ mTestScope.getBackgroundScope(),
+ keyguardTransitionRepository,
+ () -> keyguardInteractor,
+ () -> mFromLockscreenTransitionInteractor,
+ () -> mFromPrimaryBouncerTransitionInteractor);
+
+ mFromLockscreenTransitionInteractor = new FromLockscreenTransitionInteractor(
+ keyguardTransitionRepository,
+ keyguardTransitionInteractor,
+ mTestScope.getBackgroundScope(),
+ keyguardInteractor,
+ featureFlags,
+ shadeRepository,
+ powerInteractor);
+
+ mFromPrimaryBouncerTransitionInteractor = new FromPrimaryBouncerTransitionInteractor(
+ keyguardTransitionRepository,
+ keyguardTransitionInteractor,
+ mTestScope.getBackgroundScope(),
+ keyguardInteractor,
+ featureFlags,
+ mKeyguardSecurityModel,
+ powerInteractor);
+
mShadeInteractor =
new ShadeInteractor(
mTestScope.getBackgroundScope(),
+ new FakeDeviceProvisioningRepository(),
new FakeDisableFlagsRepository(),
- new FakeSceneContainerFlags(),
- mUtils::sceneInteractor,
- new FakeKeyguardRepository(),
+ mock(DozeParameters.class),
+ sceneContainerFlags,
+ () -> sceneInteractor,
+ keyguardRepository,
+ keyguardTransitionInteractor,
+ powerInteractor,
new FakeUserSetupRepository(),
- mock(DeviceProvisionedController.class),
mock(UserInteractor.class),
new SharedNotificationContainerInteractor(
- new FakeConfigurationRepository(),
+ configurationRepository,
mContext,
new ResourcesSplitShadeStateController()),
- new FakeShadeRepository()
- );
+ shadeRepository);
mNotificationShadeWindowController = new NotificationShadeWindowControllerImpl(
mContext,
diff --git a/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationShadeWindowViewControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationShadeWindowViewControllerTest.kt
index 9651072..b4f9e8d 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationShadeWindowViewControllerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationShadeWindowViewControllerTest.kt
@@ -34,6 +34,7 @@
import com.android.systemui.biometrics.data.repository.FakeFacePropertyRepository
import com.android.systemui.bouncer.data.repository.BouncerMessageRepositoryImpl
import com.android.systemui.bouncer.data.repository.FakeKeyguardBouncerRepository
+import com.android.systemui.bouncer.domain.interactor.AlternateBouncerInteractor
import com.android.systemui.bouncer.domain.interactor.BouncerMessageInteractor
import com.android.systemui.bouncer.domain.interactor.CountDownTimerUtil
import com.android.systemui.bouncer.domain.interactor.PrimaryBouncerCallbackInteractor
@@ -83,7 +84,6 @@
import com.android.systemui.util.mockito.any
import com.android.systemui.util.time.FakeSystemClock
import com.google.common.truth.Truth.assertThat
-import java.util.Optional
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.flow.emptyFlow
import kotlinx.coroutines.test.TestScope
@@ -97,8 +97,9 @@
import org.mockito.Mockito.mock
import org.mockito.Mockito.never
import org.mockito.Mockito.verify
-import org.mockito.Mockito.`when` as whenever
import org.mockito.MockitoAnnotations
+import java.util.Optional
+import org.mockito.Mockito.`when` as whenever
@OptIn(ExperimentalCoroutinesApi::class)
@SmallTest
@@ -144,6 +145,8 @@
@Mock
lateinit var primaryBouncerToGoneTransitionViewModel: PrimaryBouncerToGoneTransitionViewModel
@Mock lateinit var keyEventInteractor: KeyEventInteractor
+ @Mock lateinit var primaryBouncerInteractor: PrimaryBouncerInteractor
+ @Mock lateinit var alternateBouncerInteractor: AlternateBouncerInteractor
private val notificationExpansionRepository = NotificationExpansionRepository()
private lateinit var fakeClock: FakeSystemClock
@@ -176,6 +179,7 @@
featureFlags.set(Flags.REVAMPED_BOUNCER_MESSAGES, true)
featureFlags.set(Flags.LOCKSCREEN_WALLPAPER_DREAM_ENABLED, false)
featureFlags.set(Flags.MIGRATE_NSSL, false)
+ featureFlags.set(Flags.ALTERNATE_BOUNCER_VIEW, false)
testScope = TestScope()
fakeClock = FakeSystemClock()
@@ -248,6 +252,8 @@
),
BouncerLogger(logcatLogBuffer("BouncerLog")),
keyEventInteractor,
+ primaryBouncerInteractor,
+ alternateBouncerInteractor,
)
underTest.setupExpandedStatusBar()
underTest.setDragDownHelper(dragDownHelper)
@@ -425,29 +431,37 @@
}
@Test
- fun shouldInterceptTouchEvent_notificationPanelViewControllerShouldIntercept() {
- // GIVEN not dozing
- whenever(sysuiStatusBarStateController.isDozing()).thenReturn(false)
+ fun shouldInterceptTouchEvent_dozing_touchInLockIconArea_touchNotIntercepted() {
+ // GIVEN dozing
+ whenever(sysuiStatusBarStateController.isDozing).thenReturn(true)
// AND alternate bouncer doesn't want the touch
whenever(statusBarKeyguardViewManager.shouldInterceptTouchEvent(DOWN_EVENT))
.thenReturn(false)
- // AND the lock icon doesn't want the touch
- whenever(lockIconViewController.onInterceptTouchEvent(DOWN_EVENT)).thenReturn(false)
- // AND the notification panel can accept touches
- whenever(notificationPanelViewController.isFullyExpanded()).thenReturn(true)
- whenever(dragDownHelper.isDragDownEnabled).thenReturn(true)
- whenever(centralSurfaces.isBouncerShowing()).thenReturn(false)
-
- // AND the drag down helper doesn't want the touch (to pull the shade down)
- whenever(dragDownHelper.onInterceptTouchEvent(DOWN_EVENT)).thenReturn(false)
+ // AND the lock icon wants the touch
+ whenever(lockIconViewController.willHandleTouchWhileDozing(DOWN_EVENT))
+ .thenReturn(true)
featureFlags.set(Flags.MIGRATE_NSSL, true)
- // WHEN asked if should intercept touch
- interactionEventHandler.shouldInterceptTouchEvent(DOWN_EVENT)
+ // THEN touch should NOT be intercepted by NotificationShade
+ assertThat(interactionEventHandler.shouldInterceptTouchEvent(DOWN_EVENT)).isFalse()
+ }
- // Verify that NPVC gets a chance to use the touch
- verify(notificationPanelViewController).handleExternalInterceptTouch(DOWN_EVENT)
+ @Test
+ fun shouldInterceptTouchEvent_dozing_touchNotInLockIconArea_touchIntercepted() {
+ // GIVEN dozing
+ whenever(sysuiStatusBarStateController.isDozing).thenReturn(true)
+ // AND alternate bouncer doesn't want the touch
+ whenever(statusBarKeyguardViewManager.shouldInterceptTouchEvent(DOWN_EVENT))
+ .thenReturn(false)
+ // AND the lock icon does NOT want the touch
+ whenever(lockIconViewController.willHandleTouchWhileDozing(DOWN_EVENT))
+ .thenReturn(false)
+
+ featureFlags.set(Flags.MIGRATE_NSSL, true)
+
+ // THEN touch should NOT be intercepted by NotificationShade
+ assertThat(interactionEventHandler.shouldInterceptTouchEvent(DOWN_EVENT)).isTrue()
}
@Test
diff --git a/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationShadeWindowViewTest.kt b/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationShadeWindowViewTest.kt
index 0023020..189c9e2 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationShadeWindowViewTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationShadeWindowViewTest.kt
@@ -33,6 +33,7 @@
import com.android.systemui.biometrics.data.repository.FakeFacePropertyRepository
import com.android.systemui.bouncer.data.repository.BouncerMessageRepositoryImpl
import com.android.systemui.bouncer.data.repository.FakeKeyguardBouncerRepository
+import com.android.systemui.bouncer.domain.interactor.AlternateBouncerInteractor
import com.android.systemui.bouncer.domain.interactor.BouncerMessageInteractor
import com.android.systemui.bouncer.domain.interactor.CountDownTimerUtil
import com.android.systemui.bouncer.domain.interactor.PrimaryBouncerCallbackInteractor
@@ -141,6 +142,8 @@
Optional<UnfoldTransitionProgressProvider>
@Mock private lateinit var notificationInsetsController: NotificationInsetsController
@Mock private lateinit var keyguardTransitionInteractor: KeyguardTransitionInteractor
+ @Mock lateinit var primaryBouncerInteractor: PrimaryBouncerInteractor
+ @Mock lateinit var alternateBouncerInteractor: AlternateBouncerInteractor
@Mock
private lateinit var primaryBouncerToGoneTransitionViewModel:
PrimaryBouncerToGoneTransitionViewModel
@@ -180,6 +183,7 @@
featureFlags.set(Flags.REVAMPED_BOUNCER_MESSAGES, true)
featureFlags.set(Flags.LOCKSCREEN_WALLPAPER_DREAM_ENABLED, false)
featureFlags.set(Flags.MIGRATE_NSSL, false)
+ featureFlags.set(Flags.ALTERNATE_BOUNCER_VIEW, false)
testScope = TestScope()
controller =
NotificationShadeWindowViewController(
@@ -250,6 +254,8 @@
),
BouncerLogger(logcatLogBuffer("BouncerLog")),
Mockito.mock(KeyEventInteractor::class.java),
+ primaryBouncerInteractor,
+ alternateBouncerInteractor,
)
controller.setupExpandedStatusBar()
diff --git a/packages/SystemUI/tests/src/com/android/systemui/shade/QuickSettingsControllerBaseTest.java b/packages/SystemUI/tests/src/com/android/systemui/shade/QuickSettingsControllerBaseTest.java
index 8138b32..65174ba 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/shade/QuickSettingsControllerBaseTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/shade/QuickSettingsControllerBaseTest.java
@@ -32,23 +32,39 @@
import com.android.internal.jank.InteractionJankMonitor;
import com.android.internal.logging.MetricsLogger;
import com.android.internal.logging.UiEventLogger;
+import com.android.keyguard.KeyguardSecurityModel;
import com.android.keyguard.KeyguardStatusView;
import com.android.keyguard.KeyguardUpdateMonitor;
import com.android.systemui.SysuiTestCase;
+import com.android.systemui.bouncer.data.repository.FakeKeyguardBouncerRepository;
+import com.android.systemui.classifier.FalsingCollectorFake;
import com.android.systemui.common.ui.data.repository.FakeConfigurationRepository;
+import com.android.systemui.deviceentry.data.repository.FakeDeviceEntryRepository;
import com.android.systemui.dump.DumpManager;
+import com.android.systemui.flags.FakeFeatureFlagsClassic;
import com.android.systemui.flags.FeatureFlags;
import com.android.systemui.fragments.FragmentHostManager;
+import com.android.systemui.keyguard.data.repository.FakeCommandQueue;
import com.android.systemui.keyguard.data.repository.FakeKeyguardRepository;
+import com.android.systemui.keyguard.data.repository.FakeKeyguardTransitionRepository;
+import com.android.systemui.keyguard.domain.interactor.FromLockscreenTransitionInteractor;
+import com.android.systemui.keyguard.domain.interactor.FromPrimaryBouncerTransitionInteractor;
import com.android.systemui.keyguard.domain.interactor.KeyguardFaceAuthInteractor;
+import com.android.systemui.keyguard.domain.interactor.KeyguardInteractor;
+import com.android.systemui.keyguard.domain.interactor.KeyguardTransitionInteractor;
import com.android.systemui.media.controls.pipeline.MediaDataManager;
import com.android.systemui.media.controls.ui.MediaHierarchyManager;
import com.android.systemui.plugins.FalsingManager;
import com.android.systemui.plugins.qs.QS;
+import com.android.systemui.power.data.repository.FakePowerRepository;
+import com.android.systemui.power.domain.interactor.PowerInteractor;
import com.android.systemui.qs.QSFragmentLegacy;
import com.android.systemui.res.R;
import com.android.systemui.scene.SceneTestUtils;
+import com.android.systemui.scene.data.repository.SceneContainerRepository;
+import com.android.systemui.scene.domain.interactor.SceneInteractor;
import com.android.systemui.scene.shared.flag.FakeSceneContainerFlags;
+import com.android.systemui.scene.shared.logger.SceneLogger;
import com.android.systemui.screenrecord.RecordingController;
import com.android.systemui.shade.data.repository.FakeShadeRepository;
import com.android.systemui.shade.domain.interactor.ShadeInteractor;
@@ -64,19 +80,21 @@
import com.android.systemui.statusbar.notification.stack.AmbientState;
import com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayoutController;
import com.android.systemui.statusbar.notification.stack.domain.interactor.SharedNotificationContainerInteractor;
+import com.android.systemui.statusbar.phone.DozeParameters;
import com.android.systemui.statusbar.phone.KeyguardBottomAreaView;
import com.android.systemui.statusbar.phone.KeyguardBypassController;
import com.android.systemui.statusbar.phone.KeyguardStatusBarView;
import com.android.systemui.statusbar.phone.LightBarController;
import com.android.systemui.statusbar.phone.LockscreenGestureLogger;
+import com.android.systemui.statusbar.phone.ScreenOffAnimationController;
import com.android.systemui.statusbar.phone.ScrimController;
import com.android.systemui.statusbar.phone.StatusBarKeyguardViewManager;
import com.android.systemui.statusbar.phone.StatusBarTouchableRegionManager;
import com.android.systemui.statusbar.pipeline.mobile.data.repository.FakeUserSetupRepository;
import com.android.systemui.statusbar.policy.CastController;
-import com.android.systemui.statusbar.policy.DeviceProvisionedController;
import com.android.systemui.statusbar.policy.KeyguardStateController;
import com.android.systemui.statusbar.policy.ResourcesSplitShadeStateController;
+import com.android.systemui.statusbar.policy.data.repository.FakeDeviceProvisioningRepository;
import com.android.systemui.user.domain.interactor.UserInteractor;
import com.android.systemui.util.kotlin.JavaAdapter;
@@ -103,8 +121,7 @@
protected SceneTestUtils mUtils = new SceneTestUtils(this);
protected TestScope mTestScope = mUtils.getTestScope();
- @Mock
- protected Resources mResources;
+ @Mock protected Resources mResources;
@Mock protected KeyguardBottomAreaView mQsFrame;
@Mock protected KeyguardStatusBarView mKeyguardStatusBar;
@Mock protected QS mQs;
@@ -126,6 +143,7 @@
@Mock protected NotificationShadeDepthController mNotificationShadeDepthController;
@Mock protected ShadeHeaderController mShadeHeaderController;
@Mock protected StatusBarTouchableRegionManager mStatusBarTouchableRegionManager;
+ @Mock protected DozeParameters mDozeParameters;
@Mock protected KeyguardStateController mKeyguardStateController;
@Mock protected KeyguardBypassController mKeyguardBypassController;
@Mock protected KeyguardUpdateMonitor mKeyguardUpdateMonitor;
@@ -144,7 +162,6 @@
@Mock protected DumpManager mDumpManager;
@Mock protected UiEventLogger mUiEventLogger;
@Mock protected CastController mCastController;
- @Mock protected DeviceProvisionedController mDeviceProvisionedController;
@Mock protected UserInteractor mUserInteractor;
protected FakeDisableFlagsRepository mDisableFlagsRepository =
new FakeDisableFlagsRepository();
@@ -161,6 +178,8 @@
new ShadeExpansionStateManager();
protected FragmentHostManager.FragmentListener mFragmentListener;
+ private FromLockscreenTransitionInteractor mFromLockscreenTransitionInteractor;
+ private FromPrimaryBouncerTransitionInteractor mFromPrimaryBouncerTransitionInteractor;
@Before
public void setup() {
@@ -169,21 +188,89 @@
mStatusBarStateController = new StatusBarStateControllerImpl(mUiEventLogger, mDumpManager,
mInteractionJankMonitor, mShadeExpansionStateManager);
- when(mDeviceProvisionedController.isDeviceProvisioned()).thenReturn(true);
+ FakeDeviceProvisioningRepository deviceProvisioningRepository =
+ new FakeDeviceProvisioningRepository();
+ deviceProvisioningRepository.setDeviceProvisioned(true);
+ FakeFeatureFlagsClassic featureFlags = new FakeFeatureFlagsClassic();
+ FakePowerRepository powerRepository = new FakePowerRepository();
+ FakeConfigurationRepository configurationRepository = new FakeConfigurationRepository();
+
+ PowerInteractor powerInteractor = new PowerInteractor(
+ powerRepository,
+ new FalsingCollectorFake(),
+ mock(ScreenOffAnimationController.class),
+ mStatusBarStateController);
+
+ SceneInteractor sceneInteractor = new SceneInteractor(
+ mTestScope.getBackgroundScope(),
+ new SceneContainerRepository(
+ mTestScope.getBackgroundScope(),
+ mUtils.fakeSceneContainerConfig(mUtils.fakeSceneKeys())),
+ powerRepository,
+ mock(SceneLogger.class));
+
+ FakeSceneContainerFlags sceneContainerFlags = new FakeSceneContainerFlags();
+ KeyguardInteractor keyguardInteractor = new KeyguardInteractor(
+ mKeyguardRepository,
+ new FakeCommandQueue(),
+ powerInteractor,
+ featureFlags,
+ sceneContainerFlags,
+ new FakeDeviceEntryRepository(),
+ new FakeKeyguardBouncerRepository(),
+ configurationRepository,
+ mShadeRepository,
+ () -> sceneInteractor);
+
+ FakeKeyguardTransitionRepository keyguardTransitionRepository =
+ new FakeKeyguardTransitionRepository();
+
+ KeyguardTransitionInteractor keyguardTransitionInteractor =
+ new KeyguardTransitionInteractor(
+ mTestScope.getBackgroundScope(),
+ keyguardTransitionRepository,
+ () -> keyguardInteractor,
+ () -> mFromLockscreenTransitionInteractor,
+ () -> mFromPrimaryBouncerTransitionInteractor);
+
+ mFromLockscreenTransitionInteractor = new FromLockscreenTransitionInteractor(
+ keyguardTransitionRepository,
+ keyguardTransitionInteractor,
+ mTestScope.getBackgroundScope(),
+ keyguardInteractor,
+ featureFlags,
+ mShadeRepository,
+ powerInteractor);
+
+ mFromPrimaryBouncerTransitionInteractor = new FromPrimaryBouncerTransitionInteractor(
+ keyguardTransitionRepository,
+ keyguardTransitionInteractor,
+ mTestScope.getBackgroundScope(),
+ keyguardInteractor,
+ featureFlags,
+ mock(KeyguardSecurityModel.class),
+ powerInteractor);
+
+ ResourcesSplitShadeStateController splitShadeStateController =
+ new ResourcesSplitShadeStateController();
+
mShadeInteractor =
new ShadeInteractor(
mTestScope.getBackgroundScope(),
+ deviceProvisioningRepository,
mDisableFlagsRepository,
- new FakeSceneContainerFlags(),
- () -> mUtils.sceneInteractor(),
+ mDozeParameters,
+ sceneContainerFlags,
+ () -> sceneInteractor,
mKeyguardRepository,
+ keyguardTransitionInteractor,
+ powerInteractor,
new FakeUserSetupRepository(),
- mDeviceProvisionedController,
mUserInteractor,
new SharedNotificationContainerInteractor(
- new FakeConfigurationRepository(),
+ configurationRepository,
mContext,
- new ResourcesSplitShadeStateController()),
+ splitShadeStateController),
mShadeRepository
);
@@ -262,7 +349,7 @@
mShadeInteractor,
new JavaAdapter(mTestScope.getBackgroundScope()),
mCastController,
- new ResourcesSplitShadeStateController()
+ splitShadeStateController
);
mQsController.init();
diff --git a/packages/SystemUI/tests/src/com/android/systemui/shade/ShadeControllerImplTest.kt b/packages/SystemUI/tests/src/com/android/systemui/shade/ShadeControllerImplTest.kt
index b5841a9..215f8b1 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/shade/ShadeControllerImplTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/shade/ShadeControllerImplTest.kt
@@ -17,6 +17,7 @@
package com.android.systemui.shade
import android.testing.AndroidTestingRunner
+import android.testing.TestableLooper.RunWithLooper
import android.view.Display
import android.view.WindowManager
import androidx.test.filters.SmallTest
@@ -54,6 +55,7 @@
import org.mockito.MockitoAnnotations
@RunWith(AndroidTestingRunner::class)
+@RunWithLooper(setAsMainLooper = true)
@SmallTest
class ShadeControllerImplTest : SysuiTestCase() {
private val executor = FakeExecutor(FakeSystemClock())
diff --git a/packages/SystemUI/tests/src/com/android/systemui/shade/data/repository/ShadeInteractorTest.kt b/packages/SystemUI/tests/src/com/android/systemui/shade/data/repository/ShadeInteractorTest.kt
index 2be1c09..bcb060d 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/shade/data/repository/ShadeInteractorTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/shade/data/repository/ShadeInteractorTest.kt
@@ -16,50 +16,53 @@
package com.android.systemui.shade.data.repository
-import android.app.ActivityManager
import android.app.StatusBarManager.DISABLE2_NONE
import android.app.StatusBarManager.DISABLE2_NOTIFICATION_SHADE
import android.app.StatusBarManager.DISABLE2_QUICK_SETTINGS
import android.content.pm.UserInfo
import android.os.UserManager
import androidx.test.filters.SmallTest
-import com.android.internal.logging.UiEventLogger
-import com.android.keyguard.KeyguardUpdateMonitor
+import com.android.SysUITestModule
+import com.android.TestMocksModule
import com.android.systemui.SysuiTestCase
import com.android.systemui.common.ui.data.repository.FakeConfigurationRepository
import com.android.systemui.coroutines.collectLastValue
-import com.android.systemui.flags.FakeFeatureFlags
+import com.android.systemui.dagger.SysUISingleton
+import com.android.systemui.flags.FakeFeatureFlagsClassicModule
import com.android.systemui.flags.Flags
import com.android.systemui.keyguard.data.repository.FakeKeyguardRepository
-import com.android.systemui.keyguard.domain.interactor.KeyguardInteractorFactory
+import com.android.systemui.keyguard.data.repository.FakeKeyguardTransitionRepository
+import com.android.systemui.keyguard.shared.model.DozeStateModel
+import com.android.systemui.keyguard.shared.model.DozeTransitionModel
+import com.android.systemui.keyguard.shared.model.KeyguardState
import com.android.systemui.keyguard.shared.model.StatusBarState
-import com.android.systemui.plugins.ActivityStarter
+import com.android.systemui.keyguard.shared.model.TransitionState
+import com.android.systemui.keyguard.shared.model.TransitionStep
+import com.android.systemui.power.data.repository.FakePowerRepository
+import com.android.systemui.power.shared.model.WakeSleepReason
+import com.android.systemui.power.shared.model.WakefulnessState
import com.android.systemui.res.R
-import com.android.systemui.scene.SceneTestUtils
-import com.android.systemui.scene.shared.flag.FakeSceneContainerFlags
+import com.android.systemui.scene.domain.interactor.SceneInteractor
import com.android.systemui.scene.shared.model.ObservableTransitionState
import com.android.systemui.scene.shared.model.SceneKey
import com.android.systemui.shade.domain.interactor.ShadeInteractor
import com.android.systemui.statusbar.disableflags.data.model.DisableFlagsModel
import com.android.systemui.statusbar.disableflags.data.repository.FakeDisableFlagsRepository
-import com.android.systemui.statusbar.notification.stack.domain.interactor.SharedNotificationContainerInteractor
+import com.android.systemui.statusbar.phone.DozeParameters
import com.android.systemui.statusbar.pipeline.mobile.data.repository.FakeUserSetupRepository
-import com.android.systemui.statusbar.policy.DeviceProvisionedController
-import com.android.systemui.statusbar.policy.ResourcesSplitShadeStateController
-import com.android.systemui.telephony.data.repository.FakeTelephonyRepository
-import com.android.systemui.telephony.domain.interactor.TelephonyInteractor
+import com.android.systemui.statusbar.policy.data.repository.FakeDeviceProvisioningRepository
import com.android.systemui.user.data.model.UserSwitcherSettingsModel
import com.android.systemui.user.data.repository.FakeUserRepository
-import com.android.systemui.user.domain.interactor.GuestUserInteractor
-import com.android.systemui.user.domain.interactor.HeadlessSystemUserMode
-import com.android.systemui.user.domain.interactor.RefreshUsersScheduler
-import com.android.systemui.user.domain.interactor.UserInteractor
-import com.android.systemui.util.mockito.mock
+import com.android.systemui.user.domain.UserDomainLayerModule
import com.android.systemui.util.mockito.whenever
import com.google.common.truth.Truth.assertThat
+import dagger.BindsInstance
+import dagger.Component
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.flow.MutableStateFlow
+import kotlinx.coroutines.flow.flowOf
import kotlinx.coroutines.runBlocking
+import kotlinx.coroutines.test.TestScope
import kotlinx.coroutines.test.runCurrent
import kotlinx.coroutines.test.runTest
import org.junit.Before
@@ -70,50 +73,55 @@
@SmallTest
@OptIn(ExperimentalCoroutinesApi::class)
class ShadeInteractorTest : SysuiTestCase() {
+
+ @Mock private lateinit var dozeParameters: DozeParameters
+
+ private lateinit var testComponent: TestComponent
+
+ private val configurationRepository
+ get() = testComponent.configurationRepository
+ private val deviceProvisioningRepository
+ get() = testComponent.deviceProvisioningRepository
+ private val disableFlagsRepository
+ get() = testComponent.disableFlagsRepository
+ private val keyguardRepository
+ get() = testComponent.keyguardRepository
+ private val keyguardTransitionRepository
+ get() = testComponent.keygaurdTransitionRepository
+ private val powerRepository
+ get() = testComponent.powerRepository
+ private val sceneInteractor
+ get() = testComponent.sceneInteractor
+ private val shadeRepository
+ get() = testComponent.shadeRepository
+ private val testScope
+ get() = testComponent.testScope
+ private val userRepository
+ get() = testComponent.userRepository
+ private val userSetupRepository
+ get() = testComponent.userSetupRepository
+
private lateinit var underTest: ShadeInteractor
- private val utils = SceneTestUtils(this)
- private val testScope = utils.testScope
- private val featureFlags = FakeFeatureFlags()
- private val sceneContainerFlags = FakeSceneContainerFlags()
- private val sceneInteractor = utils.sceneInteractor()
- private val userSetupRepository = FakeUserSetupRepository()
- private val userRepository = FakeUserRepository()
- private val disableFlagsRepository = FakeDisableFlagsRepository()
- private val keyguardRepository = FakeKeyguardRepository()
- private val shadeRepository = FakeShadeRepository()
- private val configurationRepository = FakeConfigurationRepository()
- private val sharedNotificationContainerInteractor =
- SharedNotificationContainerInteractor(
- configurationRepository,
- mContext,
- ResourcesSplitShadeStateController()
- )
-
- @Mock private lateinit var manager: UserManager
- @Mock private lateinit var headlessSystemUserMode: HeadlessSystemUserMode
- @Mock private lateinit var deviceProvisionedController: DeviceProvisionedController
- @Mock private lateinit var activityStarter: ActivityStarter
- @Mock private lateinit var keyguardUpdateMonitor: KeyguardUpdateMonitor
- @Mock private lateinit var activityManager: ActivityManager
- @Mock private lateinit var uiEventLogger: UiEventLogger
- @Mock private lateinit var guestInteractor: GuestUserInteractor
-
- private lateinit var userInteractor: UserInteractor
-
@Before
fun setUp() {
MockitoAnnotations.initMocks(this)
- featureFlags.set(Flags.FACE_AUTH_REFACTOR, false)
- featureFlags.set(Flags.FULL_SCREEN_USER_SWITCHER, true)
-
- val refreshUsersScheduler =
- RefreshUsersScheduler(
- applicationScope = testScope.backgroundScope,
- mainDispatcher = utils.testDispatcher,
- repository = userRepository,
- )
+ testComponent =
+ DaggerShadeInteractorTest_TestComponent.factory()
+ .create(
+ test = this,
+ featureFlags =
+ FakeFeatureFlagsClassicModule {
+ set(Flags.FACE_AUTH_REFACTOR, false)
+ set(Flags.FULL_SCREEN_USER_SWITCHER, true)
+ },
+ mocks =
+ TestMocksModule(
+ dozeParameters = dozeParameters,
+ ),
+ )
+ underTest = testComponent.underTest
runBlocking {
val userInfos =
@@ -131,44 +139,6 @@
userRepository.setUserInfos(userInfos)
userRepository.setSelectedUserInfo(userInfos[0])
}
- userInteractor =
- UserInteractor(
- applicationContext = context,
- repository = userRepository,
- activityStarter = activityStarter,
- keyguardInteractor =
- KeyguardInteractorFactory.create(featureFlags = featureFlags)
- .keyguardInteractor,
- featureFlags = featureFlags,
- manager = manager,
- headlessSystemUserMode = headlessSystemUserMode,
- applicationScope = testScope.backgroundScope,
- telephonyInteractor =
- TelephonyInteractor(
- repository = FakeTelephonyRepository(),
- ),
- broadcastDispatcher = fakeBroadcastDispatcher,
- keyguardUpdateMonitor = keyguardUpdateMonitor,
- backgroundDispatcher = utils.testDispatcher,
- activityManager = activityManager,
- refreshUsersScheduler = refreshUsersScheduler,
- guestUserInteractor = guestInteractor,
- uiEventLogger = uiEventLogger,
- userRestrictionChecker = mock(),
- )
- underTest =
- ShadeInteractor(
- testScope.backgroundScope,
- disableFlagsRepository,
- sceneContainerFlags,
- { sceneInteractor },
- keyguardRepository,
- userSetupRepository,
- deviceProvisionedController,
- userInteractor,
- sharedNotificationContainerInteractor,
- shadeRepository,
- )
}
@Test
@@ -188,7 +158,7 @@
@Test
fun isExpandToQsEnabled_deviceNotProvisioned_false() =
testScope.runTest {
- whenever(deviceProvisionedController.isDeviceProvisioned).thenReturn(false)
+ deviceProvisioningRepository.setDeviceProvisioned(false)
val actual by collectLastValue(underTest.isExpandToQsEnabled)
@@ -198,7 +168,7 @@
@Test
fun isExpandToQsEnabled_userNotSetupAndSimpleUserSwitcher_false() =
testScope.runTest {
- whenever(deviceProvisionedController.isDeviceProvisioned).thenReturn(true)
+ deviceProvisioningRepository.setDeviceProvisioned(true)
userSetupRepository.setUserSetup(false)
userRepository.setSettings(UserSwitcherSettingsModel(isSimpleUserSwitcher = true))
@@ -211,7 +181,7 @@
@Test
fun isExpandToQsEnabled_shadeNotEnabled_false() =
testScope.runTest {
- whenever(deviceProvisionedController.isDeviceProvisioned).thenReturn(true)
+ deviceProvisioningRepository.setDeviceProvisioned(true)
userSetupRepository.setUserSetup(true)
disableFlagsRepository.disableFlags.value =
@@ -227,7 +197,7 @@
@Test
fun isExpandToQsEnabled_quickSettingsNotEnabled_false() =
testScope.runTest {
- whenever(deviceProvisionedController.isDeviceProvisioned).thenReturn(true)
+ deviceProvisioningRepository.setDeviceProvisioned(true)
userSetupRepository.setUserSetup(true)
disableFlagsRepository.disableFlags.value =
@@ -242,7 +212,7 @@
@Test
fun isExpandToQsEnabled_dozing_false() =
testScope.runTest {
- whenever(deviceProvisionedController.isDeviceProvisioned).thenReturn(true)
+ deviceProvisioningRepository.setDeviceProvisioned(true)
userSetupRepository.setUserSetup(true)
disableFlagsRepository.disableFlags.value =
DisableFlagsModel(
@@ -259,7 +229,7 @@
@Test
fun isExpandToQsEnabled_userSetup_true() =
testScope.runTest {
- whenever(deviceProvisionedController.isDeviceProvisioned).thenReturn(true)
+ deviceProvisioningRepository.setDeviceProvisioned(true)
keyguardRepository.setIsDozing(false)
disableFlagsRepository.disableFlags.value =
DisableFlagsModel(
@@ -276,7 +246,7 @@
@Test
fun isExpandToQsEnabled_notSimpleUserSwitcher_true() =
testScope.runTest {
- whenever(deviceProvisionedController.isDeviceProvisioned).thenReturn(true)
+ deviceProvisioningRepository.setDeviceProvisioned(true)
keyguardRepository.setIsDozing(false)
disableFlagsRepository.disableFlags.value =
DisableFlagsModel(
@@ -293,7 +263,7 @@
@Test
fun isExpandToQsEnabled_respondsToDozingUpdates() =
testScope.runTest {
- whenever(deviceProvisionedController.isDeviceProvisioned).thenReturn(true)
+ deviceProvisioningRepository.setDeviceProvisioned(true)
keyguardRepository.setIsDozing(false)
disableFlagsRepository.disableFlags.value =
DisableFlagsModel(
@@ -321,7 +291,7 @@
@Test
fun isExpandToQsEnabled_respondsToDisableUpdates() =
testScope.runTest {
- whenever(deviceProvisionedController.isDeviceProvisioned).thenReturn(true)
+ deviceProvisioningRepository.setDeviceProvisioned(true)
keyguardRepository.setIsDozing(false)
disableFlagsRepository.disableFlags.value =
DisableFlagsModel(
@@ -353,7 +323,7 @@
@Test
fun isExpandToQsEnabled_respondsToUserUpdates() =
testScope.runTest {
- whenever(deviceProvisionedController.isDeviceProvisioned).thenReturn(true)
+ deviceProvisioningRepository.setDeviceProvisioned(true)
keyguardRepository.setIsDozing(false)
disableFlagsRepository.disableFlags.value =
DisableFlagsModel(
@@ -625,7 +595,8 @@
fromScene = SceneKey.Lockscreen,
toScene = key,
progress = progress,
- isUserInputDriven = false,
+ isInitiatedByUserInput = false,
+ isUserInputOngoing = flowOf(false),
)
)
sceneInteractor.setTransitionState(transitionState)
@@ -662,7 +633,8 @@
fromScene = key,
toScene = SceneKey.Lockscreen,
progress = progress,
- isUserInputDriven = false,
+ isInitiatedByUserInput = false,
+ isUserInputOngoing = flowOf(false),
)
)
sceneInteractor.setTransitionState(transitionState)
@@ -698,7 +670,8 @@
fromScene = SceneKey.Lockscreen,
toScene = SceneKey.Shade,
progress = progress,
- isUserInputDriven = false,
+ isInitiatedByUserInput = false,
+ isUserInputOngoing = flowOf(false),
)
)
sceneInteractor.setTransitionState(transitionState)
@@ -974,7 +947,8 @@
fromScene = SceneKey.Lockscreen,
toScene = key,
progress = progress,
- isUserInputDriven = false,
+ isInitiatedByUserInput = false,
+ isUserInputOngoing = flowOf(false),
)
)
sceneInteractor.setTransitionState(transitionState)
@@ -1011,7 +985,8 @@
fromScene = SceneKey.Lockscreen,
toScene = key,
progress = progress,
- isUserInputDriven = true,
+ isInitiatedByUserInput = true,
+ isUserInputOngoing = flowOf(false),
)
)
sceneInteractor.setTransitionState(transitionState)
@@ -1048,7 +1023,8 @@
fromScene = key,
toScene = SceneKey.Lockscreen,
progress = progress,
- isUserInputDriven = false,
+ isInitiatedByUserInput = false,
+ isUserInputOngoing = flowOf(false),
)
)
sceneInteractor.setTransitionState(transitionState)
@@ -1085,7 +1061,8 @@
fromScene = key,
toScene = SceneKey.Lockscreen,
progress = progress,
- isUserInputDriven = true,
+ isInitiatedByUserInput = true,
+ isUserInputOngoing = flowOf(false),
)
)
sceneInteractor.setTransitionState(transitionState)
@@ -1120,8 +1097,9 @@
ObservableTransitionState.Transition(
fromScene = SceneKey.Lockscreen,
toScene = SceneKey.QuickSettings,
- progress = progress,
- isUserInputDriven = true,
+ progress = MutableStateFlow(0f),
+ isInitiatedByUserInput = true,
+ isUserInputOngoing = flowOf(false),
)
)
sceneInteractor.setTransitionState(transitionState)
@@ -1129,4 +1107,168 @@
// THEN interacting is false
assertThat(interacting).isFalse()
}
+
+ @Test
+ fun isShadeTouchable_isFalse_whenFrpIsActive() =
+ testScope.runTest {
+ deviceProvisioningRepository.setFactoryResetProtectionActive(true)
+ keyguardTransitionRepository.sendTransitionStep(
+ TransitionStep(
+ transitionState = TransitionState.STARTED,
+ )
+ )
+ val isShadeTouchable by collectLastValue(underTest.isShadeTouchable)
+ runCurrent()
+ assertThat(isShadeTouchable).isFalse()
+ }
+
+ @Test
+ fun isShadeTouchable_isFalse_whenDeviceAsleepAndNotPulsing() =
+ testScope.runTest {
+ powerRepository.updateWakefulness(
+ rawState = WakefulnessState.ASLEEP,
+ lastWakeReason = WakeSleepReason.POWER_BUTTON,
+ lastSleepReason = WakeSleepReason.OTHER,
+ )
+ // goingToSleep == false
+ // TODO: remove?
+ keyguardTransitionRepository.sendTransitionStep(
+ TransitionStep(
+ from = KeyguardState.GONE,
+ to = KeyguardState.LOCKSCREEN,
+ transitionState = TransitionState.STARTED,
+ )
+ )
+ keyguardRepository.setDozeTransitionModel(
+ DozeTransitionModel(
+ to = DozeStateModel.DOZE_AOD,
+ )
+ )
+ val isShadeTouchable by collectLastValue(underTest.isShadeTouchable)
+ runCurrent()
+ assertThat(isShadeTouchable).isFalse()
+ }
+
+ @Test
+ fun isShadeTouchable_isTrue_whenDeviceAsleepAndPulsing() =
+ testScope.runTest {
+ powerRepository.updateWakefulness(
+ rawState = WakefulnessState.ASLEEP,
+ lastWakeReason = WakeSleepReason.POWER_BUTTON,
+ lastSleepReason = WakeSleepReason.OTHER,
+ )
+ // goingToSleep == false
+ // TODO: remove?
+ keyguardTransitionRepository.sendTransitionStep(
+ TransitionStep(
+ from = KeyguardState.GONE,
+ to = KeyguardState.LOCKSCREEN,
+ transitionState = TransitionState.STARTED,
+ )
+ )
+ keyguardRepository.setDozeTransitionModel(
+ DozeTransitionModel(
+ to = DozeStateModel.DOZE_PULSING,
+ )
+ )
+ val isShadeTouchable by collectLastValue(underTest.isShadeTouchable)
+ runCurrent()
+ assertThat(isShadeTouchable).isTrue()
+ }
+
+ @Test
+ fun isShadeTouchable_isFalse_whenStartingToSleepAndNotControlScreenOff() =
+ testScope.runTest {
+ powerRepository.updateWakefulness(
+ rawState = WakefulnessState.STARTING_TO_SLEEP,
+ lastWakeReason = WakeSleepReason.POWER_BUTTON,
+ lastSleepReason = WakeSleepReason.OTHER,
+ )
+ // goingToSleep == true
+ keyguardTransitionRepository.sendTransitionStep(
+ TransitionStep(
+ from = KeyguardState.GONE,
+ to = KeyguardState.AOD,
+ transitionState = TransitionState.STARTED,
+ )
+ )
+ whenever(dozeParameters.shouldControlScreenOff()).thenReturn(false)
+ val isShadeTouchable by collectLastValue(underTest.isShadeTouchable)
+ runCurrent()
+ assertThat(isShadeTouchable).isFalse()
+ }
+
+ @Test
+ fun isShadeTouchable_isTrue_whenStartingToSleepAndControlScreenOff() =
+ testScope.runTest {
+ powerRepository.updateWakefulness(
+ rawState = WakefulnessState.STARTING_TO_SLEEP,
+ lastWakeReason = WakeSleepReason.POWER_BUTTON,
+ lastSleepReason = WakeSleepReason.OTHER,
+ )
+ // goingToSleep == true
+ keyguardTransitionRepository.sendTransitionStep(
+ TransitionStep(
+ from = KeyguardState.GONE,
+ to = KeyguardState.AOD,
+ transitionState = TransitionState.STARTED,
+ )
+ )
+ whenever(dozeParameters.shouldControlScreenOff()).thenReturn(true)
+ val isShadeTouchable by collectLastValue(underTest.isShadeTouchable)
+ runCurrent()
+ assertThat(isShadeTouchable).isTrue()
+ }
+
+ @Test
+ fun isShadeTouchable_isTrue_whenNotAsleep() =
+ testScope.runTest {
+ powerRepository.updateWakefulness(
+ rawState = WakefulnessState.AWAKE,
+ lastWakeReason = WakeSleepReason.POWER_BUTTON,
+ lastSleepReason = WakeSleepReason.OTHER,
+ )
+ keyguardTransitionRepository.sendTransitionStep(
+ TransitionStep(
+ transitionState = TransitionState.STARTED,
+ )
+ )
+ val isShadeTouchable by collectLastValue(underTest.isShadeTouchable)
+ runCurrent()
+ assertThat(isShadeTouchable).isTrue()
+ }
+
+ @SysUISingleton
+ @Component(
+ modules =
+ [
+ SysUITestModule::class,
+ UserDomainLayerModule::class,
+ ]
+ )
+ interface TestComponent {
+
+ val underTest: ShadeInteractor
+
+ val configurationRepository: FakeConfigurationRepository
+ val deviceProvisioningRepository: FakeDeviceProvisioningRepository
+ val disableFlagsRepository: FakeDisableFlagsRepository
+ val keyguardRepository: FakeKeyguardRepository
+ val keygaurdTransitionRepository: FakeKeyguardTransitionRepository
+ val powerRepository: FakePowerRepository
+ val sceneInteractor: SceneInteractor
+ val shadeRepository: FakeShadeRepository
+ val testScope: TestScope
+ val userRepository: FakeUserRepository
+ val userSetupRepository: FakeUserSetupRepository
+
+ @Component.Factory
+ interface Factory {
+ fun create(
+ @BindsInstance test: SysuiTestCase,
+ featureFlags: FakeFeatureFlagsClassicModule,
+ mocks: TestMocksModule,
+ ): TestComponent
+ }
+ }
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/shade/data/repository/ShadeRepositoryImplTest.kt b/packages/SystemUI/tests/src/com/android/systemui/shade/data/repository/ShadeRepositoryImplTest.kt
index 7463e65..6eeafefd 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/shade/data/repository/ShadeRepositoryImplTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/shade/data/repository/ShadeRepositoryImplTest.kt
@@ -18,7 +18,6 @@
import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.filters.SmallTest
-import com.android.systemui.RoboPilotTest
import com.android.systemui.SysuiTestCase
import com.android.systemui.shade.ShadeExpansionChangeEvent
import com.android.systemui.shade.ShadeExpansionStateManager
@@ -43,7 +42,6 @@
@OptIn(ExperimentalCoroutinesApi::class)
@SmallTest
-@RoboPilotTest
@RunWith(AndroidJUnit4::class)
class ShadeRepositoryImplTest : SysuiTestCase() {
diff --git a/packages/SystemUI/tests/src/com/android/systemui/shade/ui/viewmodel/ShadeHeaderViewModelTest.kt b/packages/SystemUI/tests/src/com/android/systemui/shade/ui/viewmodel/ShadeHeaderViewModelTest.kt
index 0925858..bb20d94 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/shade/ui/viewmodel/ShadeHeaderViewModelTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/shade/ui/viewmodel/ShadeHeaderViewModelTest.kt
@@ -1,5 +1,6 @@
package com.android.systemui.shade.ui.viewmodel
+import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.filters.SmallTest
import com.android.systemui.SysuiTestCase
import com.android.systemui.coroutines.collectLastValue
@@ -16,15 +17,15 @@
import com.android.systemui.util.mockito.mock
import com.google.common.truth.Truth.assertThat
import kotlinx.coroutines.flow.MutableStateFlow
+import kotlinx.coroutines.flow.flowOf
import kotlinx.coroutines.test.runTest
import org.junit.Before
import org.junit.Test
import org.junit.runner.RunWith
-import org.junit.runners.JUnit4
import org.mockito.MockitoAnnotations
@SmallTest
-@RunWith(JUnit4::class)
+@RunWith(AndroidJUnit4::class)
class ShadeHeaderViewModelTest : SysuiTestCase() {
private val utils = SceneTestUtils(this)
private val testScope = utils.testScope
@@ -84,7 +85,8 @@
fromScene = SceneKey.Shade,
toScene = SceneKey.QuickSettings,
progress = MutableStateFlow(0.5f),
- isUserInputDriven = false,
+ isInitiatedByUserInput = false,
+ isUserInputOngoing = flowOf(false),
)
)
)
@@ -102,7 +104,8 @@
fromScene = SceneKey.QuickSettings,
toScene = SceneKey.Shade,
progress = MutableStateFlow(0.5f),
- isUserInputDriven = false,
+ isInitiatedByUserInput = false,
+ isUserInputOngoing = flowOf(false),
)
)
)
@@ -120,7 +123,8 @@
fromScene = SceneKey.Gone,
toScene = SceneKey.Shade,
progress = MutableStateFlow(0.5f),
- isUserInputDriven = false,
+ isInitiatedByUserInput = false,
+ isUserInputOngoing = flowOf(false),
)
)
)
diff --git a/packages/SystemUI/tests/src/com/android/systemui/shade/ui/viewmodel/ShadeSceneViewModelTest.kt b/packages/SystemUI/tests/src/com/android/systemui/shade/ui/viewmodel/ShadeSceneViewModelTest.kt
index 602bd5f..c423782 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/shade/ui/viewmodel/ShadeSceneViewModelTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/shade/ui/viewmodel/ShadeSceneViewModelTest.kt
@@ -16,6 +16,7 @@
package com.android.systemui.shade.ui.viewmodel
+import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.filters.SmallTest
import com.android.systemui.SysuiTestCase
import com.android.systemui.authentication.data.model.AuthenticationMethodModel
@@ -37,11 +38,10 @@
import org.junit.Before
import org.junit.Test
import org.junit.runner.RunWith
-import org.junit.runners.JUnit4
@OptIn(ExperimentalCoroutinesApi::class)
@SmallTest
-@RunWith(JUnit4::class)
+@RunWith(AndroidJUnit4::class)
class ShadeSceneViewModelTest : SysuiTestCase() {
private val utils = SceneTestUtils(this)
diff --git a/packages/SystemUI/tests/src/com/android/systemui/shared/clocks/ClockRegistryTest.kt b/packages/SystemUI/tests/src/com/android/systemui/shared/clocks/ClockRegistryTest.kt
index e714736..ae659f4 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/shared/clocks/ClockRegistryTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/shared/clocks/ClockRegistryTest.kt
@@ -131,11 +131,10 @@
fun addClock(
id: ClockId,
- name: String,
create: (ClockId) -> ClockController = ::failFactory,
getThumbnail: (ClockId) -> Drawable? = ::failThumbnail
): FakeClockPlugin {
- metadata.add(ClockMetadata(id, name))
+ metadata.add(ClockMetadata(id))
createCallbacks[id] = create
thumbnailCallbacks[id] = getThumbnail
return this
@@ -149,7 +148,7 @@
scope = TestScope(dispatcher)
fakeDefaultProvider = FakeClockPlugin()
- .addClock(DEFAULT_CLOCK_ID, DEFAULT_CLOCK_NAME, { mockDefaultClock }, { mockThumbnail })
+ .addClock(DEFAULT_CLOCK_ID, { mockDefaultClock }, { mockThumbnail })
whenever(mockContext.contentResolver).thenReturn(mockContentResolver)
val captor = argumentCaptor<PluginListener<ClockProviderPlugin>>()
@@ -183,13 +182,13 @@
@Test
fun pluginRegistration_CorrectState() {
val plugin1 = FakeClockPlugin()
- .addClock("clock_1", "clock 1")
- .addClock("clock_2", "clock 2")
+ .addClock("clock_1")
+ .addClock("clock_2")
val lifecycle1 = FakeLifecycle("1", plugin1)
val plugin2 = FakeClockPlugin()
- .addClock("clock_3", "clock 3")
- .addClock("clock_4", "clock 4")
+ .addClock("clock_3")
+ .addClock("clock_4")
val lifecycle2 = FakeLifecycle("2", plugin2)
pluginListener.onPluginLoaded(plugin1, mockContext, lifecycle1)
@@ -198,11 +197,11 @@
assertEquals(
list.toSet(),
setOf(
- ClockMetadata(DEFAULT_CLOCK_ID, DEFAULT_CLOCK_NAME),
- ClockMetadata("clock_1", "clock 1"),
- ClockMetadata("clock_2", "clock 2"),
- ClockMetadata("clock_3", "clock 3"),
- ClockMetadata("clock_4", "clock 4")
+ ClockMetadata(DEFAULT_CLOCK_ID),
+ ClockMetadata("clock_1"),
+ ClockMetadata("clock_2"),
+ ClockMetadata("clock_3"),
+ ClockMetadata("clock_4")
)
)
}
@@ -216,13 +215,13 @@
@Test
fun clockIdConflict_ErrorWithoutCrash_unloadDuplicate() {
val plugin1 = FakeClockPlugin()
- .addClock("clock_1", "clock 1", { mockClock }, { mockThumbnail })
- .addClock("clock_2", "clock 2", { mockClock }, { mockThumbnail })
+ .addClock("clock_1", { mockClock }, { mockThumbnail })
+ .addClock("clock_2", { mockClock }, { mockThumbnail })
val lifecycle1 = spy(FakeLifecycle("1", plugin1))
val plugin2 = FakeClockPlugin()
- .addClock("clock_1", "clock 1")
- .addClock("clock_2", "clock 2")
+ .addClock("clock_1")
+ .addClock("clock_2")
val lifecycle2 = spy(FakeLifecycle("2", plugin2))
pluginListener.onPluginLoaded(plugin1, mockContext, lifecycle1)
@@ -231,9 +230,9 @@
assertEquals(
list.toSet(),
setOf(
- ClockMetadata(DEFAULT_CLOCK_ID, DEFAULT_CLOCK_NAME),
- ClockMetadata("clock_1", "clock 1"),
- ClockMetadata("clock_2", "clock 2")
+ ClockMetadata(DEFAULT_CLOCK_ID),
+ ClockMetadata("clock_1"),
+ ClockMetadata("clock_2")
)
)
@@ -248,13 +247,13 @@
@Test
fun createCurrentClock_pluginConnected() {
val plugin1 = FakeClockPlugin()
- .addClock("clock_1", "clock 1")
- .addClock("clock_2", "clock 2")
+ .addClock("clock_1")
+ .addClock("clock_2")
val lifecycle1 = spy(FakeLifecycle("1", plugin1))
val plugin2 = FakeClockPlugin()
- .addClock("clock_3", "clock 3", { mockClock })
- .addClock("clock_4", "clock 4")
+ .addClock("clock_3", { mockClock })
+ .addClock("clock_4")
val lifecycle2 = spy(FakeLifecycle("2", plugin2))
registry.applySettings(ClockSettings("clock_3", null))
@@ -268,13 +267,13 @@
@Test
fun activeClockId_changeAfterPluginConnected() {
val plugin1 = FakeClockPlugin()
- .addClock("clock_1", "clock 1")
- .addClock("clock_2", "clock 2")
+ .addClock("clock_1")
+ .addClock("clock_2")
val lifecycle1 = spy(FakeLifecycle("1", plugin1))
val plugin2 = FakeClockPlugin()
- .addClock("clock_3", "clock 3", { mockClock })
- .addClock("clock_4", "clock 4")
+ .addClock("clock_3", { mockClock })
+ .addClock("clock_4")
val lifecycle2 = spy(FakeLifecycle("2", plugin2))
registry.applySettings(ClockSettings("clock_3", null))
@@ -289,13 +288,13 @@
@Test
fun createDefaultClock_pluginDisconnected() {
val plugin1 = FakeClockPlugin()
- .addClock("clock_1", "clock 1")
- .addClock("clock_2", "clock 2")
+ .addClock("clock_1")
+ .addClock("clock_2")
val lifecycle1 = spy(FakeLifecycle("1", plugin1))
val plugin2 = FakeClockPlugin()
- .addClock("clock_3", "clock 3")
- .addClock("clock_4", "clock 4")
+ .addClock("clock_3")
+ .addClock("clock_4")
val lifecycle2 = spy(FakeLifecycle("2", plugin2))
registry.applySettings(ClockSettings("clock_3", null))
@@ -310,13 +309,13 @@
@Test
fun pluginRemoved_clockAndListChanged() {
val plugin1 = FakeClockPlugin()
- .addClock("clock_1", "clock 1")
- .addClock("clock_2", "clock 2")
+ .addClock("clock_1")
+ .addClock("clock_2")
val lifecycle1 = spy(FakeLifecycle("1", plugin1))
val plugin2 = FakeClockPlugin()
- .addClock("clock_3", "clock 3", { mockClock })
- .addClock("clock_4", "clock 4")
+ .addClock("clock_3", { mockClock })
+ .addClock("clock_4")
val lifecycle2 = spy(FakeLifecycle("2", plugin2))
var changeCallCount = 0
@@ -415,13 +414,13 @@
@Test
fun pluginAddRemove_concurrentModification() {
- val plugin1 = FakeClockPlugin().addClock("clock_1", "clock 1")
+ val plugin1 = FakeClockPlugin().addClock("clock_1")
val lifecycle1 = FakeLifecycle("1", plugin1)
- val plugin2 = FakeClockPlugin().addClock("clock_2", "clock 2")
+ val plugin2 = FakeClockPlugin().addClock("clock_2")
val lifecycle2 = FakeLifecycle("2", plugin2)
- val plugin3 = FakeClockPlugin().addClock("clock_3", "clock 3")
+ val plugin3 = FakeClockPlugin().addClock("clock_3")
val lifecycle3 = FakeLifecycle("3", plugin3)
- val plugin4 = FakeClockPlugin().addClock("clock_4", "clock 4")
+ val plugin4 = FakeClockPlugin().addClock("clock_4")
val lifecycle4 = FakeLifecycle("4", plugin4)
// Set the current clock to the final clock to load
@@ -450,10 +449,10 @@
// Verify all plugins were correctly loaded into the registry
assertEquals(registry.getClocks().toSet(), setOf(
- ClockMetadata("DEFAULT", "Default Clock"),
- ClockMetadata("clock_2", "clock 2"),
- ClockMetadata("clock_3", "clock 3"),
- ClockMetadata("clock_4", "clock 4")
+ ClockMetadata("DEFAULT"),
+ ClockMetadata("clock_2"),
+ ClockMetadata("clock_3"),
+ ClockMetadata("clock_4")
))
}
@@ -527,8 +526,8 @@
featureFlags.set(TRANSIT_CLOCK, flag)
registry.isTransitClockEnabled = featureFlags.isEnabled(TRANSIT_CLOCK)
val plugin = FakeClockPlugin()
- .addClock("clock_1", "clock 1")
- .addClock("DIGITAL_CLOCK_METRO", "metro clock")
+ .addClock("clock_1")
+ .addClock("DIGITAL_CLOCK_METRO")
val lifecycle = FakeLifecycle("metro", plugin)
pluginListener.onPluginLoaded(plugin, mockContext, lifecycle)
@@ -536,17 +535,17 @@
if (flag) {
assertEquals(
setOf(
- ClockMetadata(DEFAULT_CLOCK_ID, DEFAULT_CLOCK_NAME),
- ClockMetadata("clock_1", "clock 1"),
- ClockMetadata("DIGITAL_CLOCK_METRO", "metro clock")
+ ClockMetadata(DEFAULT_CLOCK_ID),
+ ClockMetadata("clock_1"),
+ ClockMetadata("DIGITAL_CLOCK_METRO")
),
list.toSet()
)
} else {
assertEquals(
setOf(
- ClockMetadata(DEFAULT_CLOCK_ID, DEFAULT_CLOCK_NAME),
- ClockMetadata("clock_1", "clock 1")
+ ClockMetadata(DEFAULT_CLOCK_ID),
+ ClockMetadata("clock_1")
),
list.toSet()
)
diff --git a/packages/SystemUI/tests/src/com/android/systemui/smartspace/BcSmartspaceConfigProviderTest.kt b/packages/SystemUI/tests/src/com/android/systemui/smartspace/BcSmartspaceConfigProviderTest.kt
index 7a2d122..b8fe2f9 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/smartspace/BcSmartspaceConfigProviderTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/smartspace/BcSmartspaceConfigProviderTest.kt
@@ -18,7 +18,6 @@
import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.filters.SmallTest
-import com.android.systemui.RoboPilotTest
import com.android.systemui.SysuiTestCase
import com.android.systemui.flags.FeatureFlags
import com.android.systemui.flags.Flags
@@ -33,7 +32,6 @@
import org.mockito.MockitoAnnotations
@SmallTest
-@RoboPilotTest
@RunWith(AndroidJUnit4::class)
class BcSmartspaceConfigProviderTest : SysuiTestCase() {
@Mock private lateinit var featureFlags: FeatureFlags
diff --git a/packages/SystemUI/tests/src/com/android/systemui/smartspace/DreamSmartspaceControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/smartspace/DreamSmartspaceControllerTest.kt
index f1c181f..e093859 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/smartspace/DreamSmartspaceControllerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/smartspace/DreamSmartspaceControllerTest.kt
@@ -26,7 +26,6 @@
import android.widget.FrameLayout
import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.filters.SmallTest
-import com.android.systemui.RoboPilotTest
import com.android.systemui.SysuiTestCase
import com.android.systemui.dreams.smartspace.DreamSmartspaceController
import com.android.systemui.plugins.BcSmartspaceConfigPlugin
@@ -53,7 +52,6 @@
import org.mockito.Spy
@SmallTest
-@RoboPilotTest
@RunWith(AndroidJUnit4::class)
@TestableLooper.RunWithLooper
class DreamSmartspaceControllerTest : SysuiTestCase() {
diff --git a/packages/SystemUI/tests/src/com/android/systemui/smartspace/LockscreenAndDreamTargetFilterTest.kt b/packages/SystemUI/tests/src/com/android/systemui/smartspace/LockscreenAndDreamTargetFilterTest.kt
index 7af29ba..886c61a 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/smartspace/LockscreenAndDreamTargetFilterTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/smartspace/LockscreenAndDreamTargetFilterTest.kt
@@ -25,7 +25,6 @@
import android.testing.TestableLooper
import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.filters.SmallTest
-import com.android.systemui.RoboPilotTest
import com.android.systemui.SysuiTestCase
import com.android.systemui.settings.UserTracker
import com.android.systemui.smartspace.filters.LockscreenAndDreamTargetFilter
@@ -52,7 +51,6 @@
@SmallTest
@TestableLooper.RunWithLooper
-@RoboPilotTest
@RunWith(AndroidJUnit4::class)
class LockscreenAndDreamTargetFilterTest : SysuiTestCase() {
@Mock
diff --git a/packages/SystemUI/tests/src/com/android/systemui/smartspace/LockscreenPreconditionTest.kt b/packages/SystemUI/tests/src/com/android/systemui/smartspace/LockscreenPreconditionTest.kt
index a7c223d..0b5aea7 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/smartspace/LockscreenPreconditionTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/smartspace/LockscreenPreconditionTest.kt
@@ -19,7 +19,6 @@
import android.testing.TestableLooper
import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.filters.SmallTest
-import com.android.systemui.RoboPilotTest
import com.android.systemui.SysuiTestCase
import com.android.systemui.smartspace.preconditions.LockscreenPrecondition
import com.android.systemui.statusbar.policy.DeviceProvisionedController
@@ -36,7 +35,6 @@
import org.mockito.MockitoAnnotations
@SmallTest
-@RoboPilotTest
@RunWith(AndroidJUnit4::class)
@TestableLooper.RunWithLooper
class LockscreenPreconditionTest : SysuiTestCase() {
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/LockscreenShadeTransitionControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/LockscreenShadeTransitionControllerTest.kt
index 14e58e5..e8923a5 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/LockscreenShadeTransitionControllerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/LockscreenShadeTransitionControllerTest.kt
@@ -5,41 +5,32 @@
import android.testing.TestableLooper
import android.testing.TestableLooper.RunWithLooper
import androidx.test.filters.SmallTest
+import com.android.SysUITestModule
+import com.android.TestMocksModule
import com.android.systemui.ExpandHelper
-import com.android.systemui.res.R
import com.android.systemui.SysuiTestCase
-import com.android.systemui.classifier.FalsingCollector
-import com.android.systemui.common.ui.data.repository.FakeConfigurationRepository
-import com.android.systemui.dump.DumpManager
-import com.android.systemui.keyguard.WakefulnessLifecycle
-import com.android.systemui.keyguard.data.repository.FakeKeyguardRepository
+import com.android.systemui.dagger.SysUISingleton
+import com.android.systemui.flags.FakeFeatureFlagsClassicModule
+import com.android.systemui.flags.Flags
import com.android.systemui.media.controls.ui.MediaHierarchyManager
-import com.android.systemui.plugins.ActivityStarter
-import com.android.systemui.plugins.FalsingManager
import com.android.systemui.plugins.qs.QS
-import com.android.systemui.power.domain.interactor.PowerInteractorFactory
-import com.android.systemui.scene.SceneTestUtils
-import com.android.systemui.scene.shared.flag.FakeSceneContainerFlags
+import com.android.systemui.res.R
import com.android.systemui.shade.ShadeViewController
-import com.android.systemui.shade.data.repository.FakeShadeRepository
-import com.android.systemui.shade.domain.interactor.ShadeInteractor
import com.android.systemui.statusbar.disableflags.data.model.DisableFlagsModel
import com.android.systemui.statusbar.disableflags.data.repository.FakeDisableFlagsRepository
import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow
import com.android.systemui.statusbar.notification.row.NotificationTestHelper
-import com.android.systemui.statusbar.notification.stack.AmbientState
import com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayout
import com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayoutController
-import com.android.systemui.statusbar.notification.stack.domain.interactor.SharedNotificationContainerInteractor
import com.android.systemui.statusbar.phone.CentralSurfaces
import com.android.systemui.statusbar.phone.KeyguardBypassController
-import com.android.systemui.statusbar.phone.LSShadeTransitionLogger
import com.android.systemui.statusbar.phone.ScrimController
-import com.android.systemui.statusbar.pipeline.mobile.data.repository.FakeUserSetupRepository
import com.android.systemui.statusbar.policy.FakeConfigurationController
-import com.android.systemui.statusbar.policy.ResourcesSplitShadeStateController
-import com.android.systemui.util.mockito.mock
+import com.android.systemui.user.domain.UserDomainLayerModule
+import dagger.BindsInstance
+import dagger.Component
import kotlinx.coroutines.ExperimentalCoroutinesApi
+import kotlinx.coroutines.test.TestScope
import kotlinx.coroutines.test.runCurrent
import org.junit.After
import org.junit.Assert.assertFalse
@@ -60,9 +51,8 @@
import org.mockito.Mockito.clearInvocations
import org.mockito.Mockito.never
import org.mockito.Mockito.verify
-import org.mockito.Mockito.verifyZeroInteractions
-import org.mockito.junit.MockitoJUnit
import org.mockito.Mockito.`when` as whenever
+import org.mockito.junit.MockitoJUnit
private fun <T> anyObject(): T {
return Mockito.anyObject<T>()
@@ -73,68 +63,38 @@
@RunWith(AndroidTestingRunner::class)
@OptIn(ExperimentalCoroutinesApi::class)
class LockscreenShadeTransitionControllerTest : SysuiTestCase() {
- private val utils = SceneTestUtils(this)
- private val testScope = utils.testScope
- lateinit var transitionController: LockscreenShadeTransitionController
+ private lateinit var testComponent: TestComponent
+
+ private val transitionController
+ get() = testComponent.transitionController
+ private val configurationController
+ get() = testComponent.configurationController
+ private val disableFlagsRepository
+ get() = testComponent.disableFlagsRepository
+ private val testScope
+ get() = testComponent.testScope
+
lateinit var row: ExpandableNotificationRow
- @Mock lateinit var statusbarStateController: SysuiStatusBarStateController
- @Mock lateinit var logger: LSShadeTransitionLogger
- @Mock lateinit var dumpManager: DumpManager
+
+ @Mock lateinit var centralSurfaces: CentralSurfaces
+ @Mock lateinit var depthController: NotificationShadeDepthController
+ @Mock lateinit var expandHelperCallback: ExpandHelper.Callback
@Mock lateinit var keyguardBypassController: KeyguardBypassController
@Mock lateinit var lockScreenUserManager: NotificationLockscreenUserManager
- @Mock lateinit var falsingCollector: FalsingCollector
- @Mock lateinit var ambientState: AmbientState
- @Mock lateinit var wakefulnessLifecycle: WakefulnessLifecycle
@Mock lateinit var mediaHierarchyManager: MediaHierarchyManager
- @Mock lateinit var scrimController: ScrimController
- @Mock lateinit var falsingManager: FalsingManager
- @Mock lateinit var shadeViewController: ShadeViewController
@Mock lateinit var nsslController: NotificationStackScrollLayoutController
- @Mock lateinit var depthController: NotificationShadeDepthController
- @Mock lateinit var stackscroller: NotificationStackScrollLayout
- @Mock lateinit var expandHelperCallback: ExpandHelper.Callback
- @Mock lateinit var mCentralSurfaces: CentralSurfaces
@Mock lateinit var qS: QS
- @Mock lateinit var singleShadeOverScroller: SingleShadeLockScreenOverScroller
- @Mock lateinit var splitShadeOverScroller: SplitShadeLockScreenOverScroller
- @Mock lateinit var qsTransitionController: LockscreenShadeQsTransitionController
- @Mock lateinit var activityStarter: ActivityStarter
+ @Mock lateinit var scrimController: ScrimController
+ @Mock lateinit var shadeViewController: ShadeViewController
+ @Mock lateinit var stackscroller: NotificationStackScrollLayout
+ @Mock lateinit var statusbarStateController: SysuiStatusBarStateController
@Mock lateinit var transitionControllerCallback: LockscreenShadeTransitionController.Callback
- private val sceneContainerFlags = FakeSceneContainerFlags()
- private val sceneInteractor = utils.sceneInteractor()
- private val disableFlagsRepository = FakeDisableFlagsRepository()
- private val keyguardRepository = FakeKeyguardRepository()
- private val configurationRepository = FakeConfigurationRepository()
- private val sharedNotificationContainerInteractor = SharedNotificationContainerInteractor(
- configurationRepository,
- mContext,
- ResourcesSplitShadeStateController()
- )
- private val shadeInteractor =
- ShadeInteractor(
- testScope.backgroundScope,
- disableFlagsRepository,
- sceneContainerFlags,
- { sceneInteractor },
- keyguardRepository,
- userSetupRepository = FakeUserSetupRepository(),
- deviceProvisionedController = mock(),
- userInteractor = mock(),
- sharedNotificationContainerInteractor,
- repository = FakeShadeRepository(),
- )
- private val powerInteractor = PowerInteractorFactory.create().powerInteractor
- @JvmField @Rule val mockito = MockitoJUnit.rule()
- private val configurationController = FakeConfigurationController()
+ @JvmField @Rule val mockito = MockitoJUnit.rule()
@Before
fun setup() {
- // By default, have the shade enabled
- disableFlagsRepository.disableFlags.value = DisableFlagsModel()
- testScope.runCurrent()
-
val helper = NotificationTestHelper(mContext, mDependency, TestableLooper.get(this))
row = helper.createRow()
context
@@ -143,55 +103,9 @@
context
.getOrCreateTestableResources()
.addOverride(R.dimen.lockscreen_shade_depth_controller_transition_distance, 100)
- transitionController =
- LockscreenShadeTransitionController(
- statusBarStateController = statusbarStateController,
- logger = logger,
- keyguardBypassController = keyguardBypassController,
- lockScreenUserManager = lockScreenUserManager,
- falsingCollector = falsingCollector,
- ambientState = ambientState,
- mediaHierarchyManager = mediaHierarchyManager,
- depthController = depthController,
- wakefulnessLifecycle = wakefulnessLifecycle,
- context = context,
- configurationController = configurationController,
- falsingManager = falsingManager,
- dumpManager = dumpManager,
- splitShadeOverScrollerFactory = { _, _ -> splitShadeOverScroller },
- singleShadeOverScrollerFactory = { singleShadeOverScroller },
- scrimTransitionController =
- LockscreenShadeScrimTransitionController(
- scrimController,
- context,
- configurationController,
- dumpManager,
- ResourcesSplitShadeStateController()
- ),
- keyguardTransitionControllerFactory = { notificationPanelController ->
- LockscreenShadeKeyguardTransitionController(
- mediaHierarchyManager,
- notificationPanelController,
- context,
- configurationController,
- dumpManager,
- ResourcesSplitShadeStateController()
- )
- },
- qsTransitionControllerFactory = { qsTransitionController },
- activityStarter = activityStarter,
- shadeRepository = FakeShadeRepository(),
- shadeInteractor = shadeInteractor,
- powerInteractor = powerInteractor,
- splitShadeStateController = ResourcesSplitShadeStateController()
- )
- transitionController.addCallback(transitionControllerCallback)
+
whenever(nsslController.view).thenReturn(stackscroller)
whenever(nsslController.expandHelperCallback).thenReturn(expandHelperCallback)
- transitionController.shadeViewController = shadeViewController
- transitionController.centralSurfaces = mCentralSurfaces
- transitionController.qS = qS
- transitionController.setStackScroller(nsslController)
whenever(statusbarStateController.state).thenReturn(StatusBarState.KEYGUARD)
whenever(nsslController.isInLockedDownShade).thenReturn(false)
whenever(qS.isFullyCollapsed).thenReturn(true)
@@ -199,9 +113,36 @@
.thenReturn(true)
whenever(lockScreenUserManager.shouldShowLockscreenNotifications()).thenReturn(true)
whenever(lockScreenUserManager.isLockscreenPublicMode(anyInt())).thenReturn(true)
- whenever(falsingCollector.shouldEnforceBouncer()).thenReturn(false)
whenever(keyguardBypassController.bypassEnabled).thenReturn(false)
- clearInvocations(mCentralSurfaces)
+
+ testComponent =
+ DaggerLockscreenShadeTransitionControllerTest_TestComponent.factory()
+ .create(
+ test = this,
+ featureFlags =
+ FakeFeatureFlagsClassicModule {
+ set(Flags.FULL_SCREEN_USER_SWITCHER, false)
+ },
+ mocks =
+ TestMocksModule(
+ notificationShadeDepthController = depthController,
+ keyguardBypassController = keyguardBypassController,
+ mediaHierarchyManager = mediaHierarchyManager,
+ notificationLockscreenUserManager = lockScreenUserManager,
+ notificationStackScrollLayoutController = nsslController,
+ scrimController = scrimController,
+ statusBarStateController = statusbarStateController,
+ )
+ )
+
+ transitionController.addCallback(transitionControllerCallback)
+ transitionController.shadeViewController = shadeViewController
+ transitionController.centralSurfaces = centralSurfaces
+ transitionController.qS = qS
+ transitionController.setStackScroller(nsslController)
+ clearInvocations(centralSurfaces)
+
+ testScope.runCurrent()
}
@After
@@ -282,7 +223,7 @@
transitionController.goToLockedShade(null)
verify(statusbarStateController, never()).setState(anyInt())
verify(statusbarStateController).setLeaveOpenOnKeyguardHide(true)
- verify(mCentralSurfaces).showBouncerWithDimissAndCancelIfKeyguard(anyObject(), anyObject())
+ verify(centralSurfaces).showBouncerWithDimissAndCancelIfKeyguard(anyObject(), anyObject())
}
@Test
@@ -318,7 +259,7 @@
verify(scrimController, never()).setTransitionToFullShadeProgress(anyFloat(), anyFloat())
verify(transitionControllerCallback, never())
.setTransitionToFullShadeAmount(anyFloat(), anyBoolean(), anyLong())
- verify(qsTransitionController, never()).dragDownAmount = anyFloat()
+ verify(qS, never()).setTransitionToFullShadeProgress(anyBoolean(), anyFloat(), anyFloat())
}
@Test
@@ -329,7 +270,7 @@
verify(scrimController).setTransitionToFullShadeProgress(anyFloat(), anyFloat())
verify(transitionControllerCallback)
.setTransitionToFullShadeAmount(anyFloat(), anyBoolean(), anyLong())
- verify(qsTransitionController).dragDownAmount = 10f
+ verify(qS).setTransitionToFullShadeProgress(eq(true), anyFloat(), anyFloat())
verify(depthController).transitionToFullShadeProgress = anyFloat()
}
@@ -532,8 +473,8 @@
transitionController.dragDownAmount = 10f
- verify(singleShadeOverScroller).expansionDragDownAmount = 10f
- verifyZeroInteractions(splitShadeOverScroller)
+ verify(nsslController).setOverScrollAmount(0)
+ verify(scrimController, never()).setNotificationsOverScrollAmount(anyInt())
}
@Test
@@ -542,8 +483,8 @@
transitionController.dragDownAmount = 10f
- verify(splitShadeOverScroller).expansionDragDownAmount = 10f
- verifyZeroInteractions(singleShadeOverScroller)
+ verify(nsslController).setOverScrollAmount(0)
+ verify(scrimController).setNotificationsOverScrollAmount(0)
}
@Test
@@ -591,6 +532,32 @@
progress: Float,
lockScreenNotificationsProgress: Float
) {
- scrimController.setTransitionToFullShadeProgress(progress, lockScreenNotificationsProgress)
+ setTransitionToFullShadeProgress(progress, lockScreenNotificationsProgress)
+ }
+
+ @SysUISingleton
+ @Component(
+ modules =
+ [
+ SysUITestModule::class,
+ UserDomainLayerModule::class,
+ ]
+ )
+ interface TestComponent {
+
+ val transitionController: LockscreenShadeTransitionController
+
+ val configurationController: FakeConfigurationController
+ val disableFlagsRepository: FakeDisableFlagsRepository
+ val testScope: TestScope
+
+ @Component.Factory
+ interface Factory {
+ fun create(
+ @BindsInstance test: SysuiTestCase,
+ featureFlags: FakeFeatureFlagsClassicModule,
+ mocks: TestMocksModule,
+ ): TestComponent
+ }
}
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/PulseExpansionHandlerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/PulseExpansionHandlerTest.kt
index fbb8ebf..20e5c43 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/PulseExpansionHandlerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/PulseExpansionHandlerTest.kt
@@ -29,9 +29,9 @@
import com.android.systemui.statusbar.notification.NotificationWakeUpCoordinator
import com.android.systemui.statusbar.notification.row.ExpandableView
import com.android.systemui.statusbar.notification.stack.NotificationRoundnessManager
-import com.android.systemui.statusbar.phone.HeadsUpManagerPhone
import com.android.systemui.statusbar.phone.KeyguardBypassController
import com.android.systemui.statusbar.policy.ConfigurationController
+import com.android.systemui.statusbar.policy.HeadsUpManager
import com.android.systemui.util.mockito.mock
import org.junit.Before
import org.junit.Test
@@ -52,7 +52,7 @@
private val collapsedHeight = 300
private val wakeUpCoordinator: NotificationWakeUpCoordinator = mock()
private val bypassController: KeyguardBypassController = mock()
- private val headsUpManager: HeadsUpManagerPhone = mock()
+ private val headsUpManager: HeadsUpManager = mock()
private val roundnessManager: NotificationRoundnessManager = mock()
private val configurationController: ConfigurationController = mock()
private val statusBarStateController: StatusBarStateController = mock()
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/NotificationLaunchAnimatorControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/NotificationLaunchAnimatorControllerTest.kt
index d86f8bb..235ac5c 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/NotificationLaunchAnimatorControllerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/NotificationLaunchAnimatorControllerTest.kt
@@ -8,15 +8,15 @@
import com.android.internal.jank.InteractionJankMonitor
import com.android.systemui.SysuiTestCase
import com.android.systemui.coroutines.collectLastValue
+import com.android.systemui.res.R
import com.android.systemui.statusbar.notification.collection.GroupEntryBuilder
import com.android.systemui.statusbar.notification.collection.NotificationEntryBuilder
import com.android.systemui.statusbar.notification.data.repository.NotificationExpansionRepository
import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow
import com.android.systemui.statusbar.notification.row.NotificationTestHelper
import com.android.systemui.statusbar.notification.stack.NotificationListContainer
-import com.android.systemui.statusbar.phone.HeadsUpManagerPhone
+import com.android.systemui.statusbar.policy.HeadsUpManager
import com.android.systemui.statusbar.policy.HeadsUpUtil
-import com.android.systemui.res.R
import junit.framework.Assert.assertFalse
import junit.framework.Assert.assertTrue
import kotlinx.coroutines.test.TestScope
@@ -37,7 +37,7 @@
@RunWithLooper
class NotificationLaunchAnimatorControllerTest : SysuiTestCase() {
@Mock lateinit var notificationListContainer: NotificationListContainer
- @Mock lateinit var headsUpManager: HeadsUpManagerPhone
+ @Mock lateinit var headsUpManager: HeadsUpManager
@Mock lateinit var jankMonitor: InteractionJankMonitor
@Mock lateinit var onFinishAnimationCallback: Runnable
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/HeadsUpCoordinatorTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/HeadsUpCoordinatorTest.kt
index 257cc5b..4f1581c 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/HeadsUpCoordinatorTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/HeadsUpCoordinatorTest.kt
@@ -43,8 +43,8 @@
import com.android.systemui.statusbar.notification.interruption.NotificationInterruptStateProviderWrapper.FullScreenIntentDecisionImpl
import com.android.systemui.statusbar.notification.interruption.VisualInterruptionDecisionProvider
import com.android.systemui.statusbar.notification.row.NotifBindPipeline.BindCallback
+import com.android.systemui.statusbar.phone.HeadsUpManagerPhone
import com.android.systemui.statusbar.phone.NotificationGroupTestHelper
-import com.android.systemui.statusbar.policy.HeadsUpManager
import com.android.systemui.statusbar.policy.OnHeadsUpChangedListener
import com.android.systemui.util.concurrency.FakeExecutor
import com.android.systemui.util.mockito.any
@@ -87,7 +87,7 @@
private val notifPipeline: NotifPipeline = mock()
private val logger = HeadsUpCoordinatorLogger(logcatLogBuffer(), verbose = true)
- private val headsUpManager: HeadsUpManager = mock()
+ private val headsUpManager: HeadsUpManagerPhone = mock()
private val headsUpViewBinder: HeadsUpViewBinder = mock()
private val visualInterruptionDecisionProvider: VisualInterruptionDecisionProvider = mock()
private val remoteInputManager: NotificationRemoteInputManager = mock()
@@ -435,7 +435,7 @@
private fun addHUN(entry: NotificationEntry) {
huns.add(entry)
- whenever(headsUpManager.topEntry).thenReturn(entry)
+ whenever(headsUpManager.getTopEntry()).thenReturn(entry)
onHeadsUpChangedListener.onHeadsUpStateChanged(entry, true)
notifLifetimeExtender.cancelLifetimeExtension(entry)
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/KeyguardCoordinatorTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/KeyguardCoordinatorTest.kt
index fbd61f4..546abd4 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/KeyguardCoordinatorTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/KeyguardCoordinatorTest.kt
@@ -23,7 +23,6 @@
import android.testing.AndroidTestingRunner
import androidx.test.filters.SmallTest
import com.android.systemui.SysuiTestCase
-import com.android.systemui.coroutines.advanceTimeBy
import com.android.systemui.dump.DumpManager
import com.android.systemui.dump.logcatLogBuffer
import com.android.systemui.keyguard.data.repository.FakeKeyguardRepository
@@ -40,10 +39,10 @@
import com.android.systemui.statusbar.notification.collection.listbuilder.pluggable.Pluggable
import com.android.systemui.statusbar.notification.collection.notifcollection.NotifCollectionListener
import com.android.systemui.statusbar.notification.collection.provider.SectionHeaderVisibilityProvider
-import com.android.systemui.statusbar.notification.collection.provider.SeenNotificationsProvider
-import com.android.systemui.statusbar.notification.collection.provider.SeenNotificationsProviderImpl
import com.android.systemui.statusbar.notification.interruption.KeyguardNotificationVisibilityProvider
import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow
+import com.android.systemui.statusbar.notification.stack.data.repository.NotificationListRepository
+import com.android.systemui.statusbar.notification.stack.domain.interactor.NotificationListInteractor
import com.android.systemui.statusbar.policy.HeadsUpManager
import com.android.systemui.statusbar.policy.OnHeadsUpChangedListener
import com.android.systemui.util.mockito.any
@@ -247,7 +246,7 @@
unseenFilter.onCleanup()
// THEN: The SeenNotificationProvider has been updated to reflect the suppression
- assertThat(seenNotificationsProvider.hasFilteredOutSeenNotifications).isTrue()
+ assertThat(notificationListInteractor.hasFilteredOutSeenNotifications.value).isTrue()
}
}
@@ -598,7 +597,7 @@
FakeSettings().apply {
putInt(Settings.Secure.LOCK_SCREEN_SHOW_ONLY_UNSEEN_NOTIFICATIONS, 1)
}
- val seenNotificationsProvider = SeenNotificationsProviderImpl()
+ val notificationListInteractor = NotificationListInteractor(NotificationListRepository())
val keyguardCoordinator =
KeyguardCoordinator(
testDispatcher,
@@ -611,7 +610,7 @@
testScope.backgroundScope,
sectionHeaderVisibilityProvider,
fakeSettings,
- seenNotificationsProvider,
+ notificationListInteractor,
statusBarStateController,
)
keyguardCoordinator.attach(notifPipeline)
@@ -619,7 +618,7 @@
KeyguardCoordinatorTestScope(
keyguardCoordinator,
testScope,
- seenNotificationsProvider,
+ notificationListInteractor,
fakeSettings,
)
.testBlock()
@@ -629,7 +628,7 @@
private inner class KeyguardCoordinatorTestScope(
private val keyguardCoordinator: KeyguardCoordinator,
private val scope: TestScope,
- val seenNotificationsProvider: SeenNotificationsProvider,
+ val notificationListInteractor: NotificationListInteractor,
private val fakeSettings: FakeSettings,
) : CoroutineScope by scope {
val testScheduler: TestCoroutineScheduler
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/icon/ui/viewmodel/NotificationIconContainerAlwaysOnDisplayViewModelTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/icon/ui/viewmodel/NotificationIconContainerAlwaysOnDisplayViewModelTest.kt
new file mode 100644
index 0000000..99c3b19
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/icon/ui/viewmodel/NotificationIconContainerAlwaysOnDisplayViewModelTest.kt
@@ -0,0 +1,282 @@
+/*
+ * Copyright (C) 2023 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.
+ */
+@file:OptIn(ExperimentalCoroutinesApi::class)
+
+package com.android.systemui.statusbar.notification.icon.ui.viewmodel
+
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import androidx.test.filters.SmallTest
+import com.android.SysUITestModule
+import com.android.TestMocksModule
+import com.android.systemui.SysuiTestCase
+import com.android.systemui.biometrics.domain.BiometricsDomainLayerModule
+import com.android.systemui.coroutines.collectLastValue
+import com.android.systemui.dagger.SysUISingleton
+import com.android.systemui.flags.FakeFeatureFlagsClassicModule
+import com.android.systemui.flags.Flags
+import com.android.systemui.keyguard.data.repository.FakeKeyguardRepository
+import com.android.systemui.keyguard.data.repository.FakeKeyguardTransitionRepository
+import com.android.systemui.keyguard.shared.model.DozeStateModel
+import com.android.systemui.keyguard.shared.model.DozeTransitionModel
+import com.android.systemui.keyguard.shared.model.KeyguardState
+import com.android.systemui.keyguard.shared.model.TransitionState
+import com.android.systemui.keyguard.shared.model.TransitionStep
+import com.android.systemui.power.data.repository.FakePowerRepository
+import com.android.systemui.power.shared.model.WakeSleepReason
+import com.android.systemui.power.shared.model.WakefulnessState
+import com.android.systemui.statusbar.phone.DozeParameters
+import com.android.systemui.statusbar.policy.data.repository.FakeDeviceProvisioningRepository
+import com.android.systemui.user.domain.UserDomainLayerModule
+import com.android.systemui.util.mockito.whenever
+import com.google.common.truth.Truth.assertThat
+import dagger.BindsInstance
+import dagger.Component
+import kotlinx.coroutines.ExperimentalCoroutinesApi
+import kotlinx.coroutines.test.TestScope
+import kotlinx.coroutines.test.runCurrent
+import kotlinx.coroutines.test.runTest
+import org.junit.Before
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.mockito.Mock
+import org.mockito.MockitoAnnotations
+
+@SmallTest
+@RunWith(AndroidJUnit4::class)
+class NotificationIconContainerAlwaysOnDisplayViewModelTest : SysuiTestCase() {
+
+ @Mock private lateinit var dozeParams: DozeParameters
+
+ private lateinit var testComponent: TestComponent
+ private val underTest
+ get() = testComponent.underTest
+ private val deviceProvisioningRepository
+ get() = testComponent.deviceProvisioningRepository
+ private val keyguardRepository
+ get() = testComponent.keyguardRepository
+ private val keyguardTransitionRepository
+ get() = testComponent.keyguardTransitionRepository
+ private val powerRepository
+ get() = testComponent.powerRepository
+ private val scope
+ get() = testComponent.scope
+
+ @Before
+ fun setup() {
+ MockitoAnnotations.initMocks(this)
+
+ testComponent =
+ DaggerNotificationIconContainerAlwaysOnDisplayViewModelTest_TestComponent.factory()
+ .create(
+ test = this,
+ featureFlags =
+ FakeFeatureFlagsClassicModule {
+ set(Flags.FACE_AUTH_REFACTOR, value = false)
+ set(Flags.FULL_SCREEN_USER_SWITCHER, value = false)
+ },
+ mocks =
+ TestMocksModule(
+ dozeParameters = dozeParams,
+ ),
+ )
+
+ keyguardRepository.setKeyguardShowing(true)
+ keyguardRepository.setKeyguardOccluded(false)
+ deviceProvisioningRepository.setFactoryResetProtectionActive(false)
+ powerRepository.updateWakefulness(
+ rawState = WakefulnessState.AWAKE,
+ lastWakeReason = WakeSleepReason.OTHER,
+ lastSleepReason = WakeSleepReason.OTHER,
+ )
+ }
+
+ @Test
+ fun animationsEnabled_isFalse_whenFrpIsActive() =
+ scope.runTest {
+ deviceProvisioningRepository.setFactoryResetProtectionActive(true)
+ keyguardTransitionRepository.sendTransitionStep(
+ TransitionStep(
+ transitionState = TransitionState.STARTED,
+ )
+ )
+ val animationsEnabled by collectLastValue(underTest.animationsEnabled)
+ runCurrent()
+ assertThat(animationsEnabled).isFalse()
+ }
+
+ @Test
+ fun animationsEnabled_isFalse_whenDeviceAsleepAndNotPulsing() =
+ scope.runTest {
+ powerRepository.updateWakefulness(
+ rawState = WakefulnessState.ASLEEP,
+ lastWakeReason = WakeSleepReason.POWER_BUTTON,
+ lastSleepReason = WakeSleepReason.OTHER,
+ )
+ keyguardTransitionRepository.sendTransitionStep(
+ TransitionStep(
+ transitionState = TransitionState.STARTED,
+ )
+ )
+ keyguardRepository.setDozeTransitionModel(
+ DozeTransitionModel(
+ to = DozeStateModel.DOZE_AOD,
+ )
+ )
+ val animationsEnabled by collectLastValue(underTest.animationsEnabled)
+ runCurrent()
+ assertThat(animationsEnabled).isFalse()
+ }
+
+ @Test
+ fun animationsEnabled_isTrue_whenDeviceAsleepAndPulsing() =
+ scope.runTest {
+ powerRepository.updateWakefulness(
+ rawState = WakefulnessState.ASLEEP,
+ lastWakeReason = WakeSleepReason.POWER_BUTTON,
+ lastSleepReason = WakeSleepReason.OTHER,
+ )
+ keyguardTransitionRepository.sendTransitionStep(
+ TransitionStep(
+ transitionState = TransitionState.STARTED,
+ )
+ )
+ keyguardRepository.setDozeTransitionModel(
+ DozeTransitionModel(
+ to = DozeStateModel.DOZE_PULSING,
+ )
+ )
+ val animationsEnabled by collectLastValue(underTest.animationsEnabled)
+ runCurrent()
+ assertThat(animationsEnabled).isTrue()
+ }
+
+ @Test
+ fun animationsEnabled_isFalse_whenStartingToSleepAndNotControlScreenOff() =
+ scope.runTest {
+ powerRepository.updateWakefulness(
+ rawState = WakefulnessState.STARTING_TO_SLEEP,
+ lastWakeReason = WakeSleepReason.POWER_BUTTON,
+ lastSleepReason = WakeSleepReason.OTHER,
+ )
+ keyguardTransitionRepository.sendTransitionStep(
+ TransitionStep(
+ from = KeyguardState.GONE,
+ to = KeyguardState.AOD,
+ transitionState = TransitionState.STARTED,
+ )
+ )
+ whenever(dozeParams.shouldControlScreenOff()).thenReturn(false)
+ val animationsEnabled by collectLastValue(underTest.animationsEnabled)
+ runCurrent()
+ assertThat(animationsEnabled).isFalse()
+ }
+
+ @Test
+ fun animationsEnabled_isTrue_whenStartingToSleepAndControlScreenOff() =
+ scope.runTest {
+ powerRepository.updateWakefulness(
+ rawState = WakefulnessState.STARTING_TO_SLEEP,
+ lastWakeReason = WakeSleepReason.POWER_BUTTON,
+ lastSleepReason = WakeSleepReason.OTHER,
+ )
+ keyguardTransitionRepository.sendTransitionStep(
+ TransitionStep(
+ from = KeyguardState.GONE,
+ to = KeyguardState.AOD,
+ transitionState = TransitionState.STARTED,
+ )
+ )
+ whenever(dozeParams.shouldControlScreenOff()).thenReturn(true)
+ val animationsEnabled by collectLastValue(underTest.animationsEnabled)
+ runCurrent()
+ assertThat(animationsEnabled).isTrue()
+ }
+
+ @Test
+ fun animationsEnabled_isTrue_whenNotAsleep() =
+ scope.runTest {
+ powerRepository.updateWakefulness(
+ rawState = WakefulnessState.AWAKE,
+ lastWakeReason = WakeSleepReason.POWER_BUTTON,
+ lastSleepReason = WakeSleepReason.OTHER,
+ )
+ keyguardTransitionRepository.sendTransitionStep(
+ TransitionStep(
+ transitionState = TransitionState.STARTED,
+ )
+ )
+ val animationsEnabled by collectLastValue(underTest.animationsEnabled)
+ runCurrent()
+ assertThat(animationsEnabled).isTrue()
+ }
+
+ @Test
+ fun animationsEnabled_isTrue_whenKeyguardIsShowing() =
+ scope.runTest {
+ keyguardTransitionRepository.sendTransitionStep(
+ TransitionStep(
+ transitionState = TransitionState.STARTED,
+ )
+ )
+ val animationsEnabled by collectLastValue(underTest.animationsEnabled)
+
+ keyguardRepository.setKeyguardShowing(true)
+ keyguardRepository.setKeyguardOccluded(false)
+ runCurrent()
+
+ assertThat(animationsEnabled).isTrue()
+
+ keyguardRepository.setKeyguardOccluded(true)
+ runCurrent()
+
+ assertThat(animationsEnabled).isFalse()
+
+ keyguardRepository.setKeyguardShowing(false)
+ keyguardRepository.setKeyguardOccluded(true)
+ runCurrent()
+
+ assertThat(animationsEnabled).isFalse()
+ }
+
+ @SysUISingleton
+ @Component(
+ modules =
+ [
+ SysUITestModule::class,
+ BiometricsDomainLayerModule::class,
+ UserDomainLayerModule::class,
+ ]
+ )
+ interface TestComponent {
+
+ val underTest: NotificationIconContainerAlwaysOnDisplayViewModel
+
+ val deviceProvisioningRepository: FakeDeviceProvisioningRepository
+ val keyguardRepository: FakeKeyguardRepository
+ val keyguardTransitionRepository: FakeKeyguardTransitionRepository
+ val powerRepository: FakePowerRepository
+ val scope: TestScope
+
+ @Component.Factory
+ interface Factory {
+ fun create(
+ @BindsInstance test: SysuiTestCase,
+ mocks: TestMocksModule,
+ featureFlags: FakeFeatureFlagsClassicModule,
+ ): TestComponent
+ }
+ }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/icon/ui/viewmodel/NotificationIconContainerStatusBarViewModelTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/icon/ui/viewmodel/NotificationIconContainerStatusBarViewModelTest.kt
new file mode 100644
index 0000000..d1518f7
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/icon/ui/viewmodel/NotificationIconContainerStatusBarViewModelTest.kt
@@ -0,0 +1,274 @@
+/*
+ * Copyright (C) 2023 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.
+ */
+@file:OptIn(ExperimentalCoroutinesApi::class)
+
+package com.android.systemui.statusbar.notification.icon.ui.viewmodel
+
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import androidx.test.filters.SmallTest
+import com.android.SysUITestModule
+import com.android.TestMocksModule
+import com.android.systemui.SysuiTestCase
+import com.android.systemui.biometrics.domain.BiometricsDomainLayerModule
+import com.android.systemui.coroutines.collectLastValue
+import com.android.systemui.dagger.SysUISingleton
+import com.android.systemui.flags.FakeFeatureFlagsClassicModule
+import com.android.systemui.flags.Flags
+import com.android.systemui.keyguard.data.repository.FakeKeyguardRepository
+import com.android.systemui.keyguard.data.repository.FakeKeyguardTransitionRepository
+import com.android.systemui.keyguard.shared.model.DozeStateModel
+import com.android.systemui.keyguard.shared.model.DozeTransitionModel
+import com.android.systemui.keyguard.shared.model.KeyguardState
+import com.android.systemui.keyguard.shared.model.TransitionState
+import com.android.systemui.keyguard.shared.model.TransitionStep
+import com.android.systemui.power.data.repository.FakePowerRepository
+import com.android.systemui.power.shared.model.WakeSleepReason
+import com.android.systemui.power.shared.model.WakefulnessState
+import com.android.systemui.statusbar.phone.DozeParameters
+import com.android.systemui.statusbar.policy.data.repository.FakeDeviceProvisioningRepository
+import com.android.systemui.user.domain.UserDomainLayerModule
+import com.android.systemui.util.mockito.whenever
+import com.google.common.truth.Truth.assertThat
+import dagger.BindsInstance
+import dagger.Component
+import kotlinx.coroutines.ExperimentalCoroutinesApi
+import kotlinx.coroutines.test.TestScope
+import kotlinx.coroutines.test.runCurrent
+import kotlinx.coroutines.test.runTest
+import org.junit.Before
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.mockito.Mock
+import org.mockito.MockitoAnnotations
+
+@SmallTest
+@RunWith(AndroidJUnit4::class)
+class NotificationIconContainerStatusBarViewModelTest : SysuiTestCase() {
+
+ @Mock lateinit var dozeParams: DozeParameters
+
+ private lateinit var testComponent: TestComponent
+ private val underTest: NotificationIconContainerStatusBarViewModel
+ get() = testComponent.underTest
+ private val deviceProvisioningRepository
+ get() = testComponent.deviceProvisioningRepository
+ private val keyguardTransitionRepository
+ get() = testComponent.keyguardTransitionRepository
+ private val keyguardRepository
+ get() = testComponent.keyguardRepository
+ private val powerRepository
+ get() = testComponent.powerRepository
+ private val scope
+ get() = testComponent.scope
+
+ @Before
+ fun setup() {
+ MockitoAnnotations.initMocks(this)
+
+ testComponent =
+ DaggerNotificationIconContainerStatusBarViewModelTest_TestComponent.factory()
+ .create(
+ test = this,
+ featureFlags =
+ FakeFeatureFlagsClassicModule {
+ set(Flags.FACE_AUTH_REFACTOR, value = false)
+ set(Flags.FULL_SCREEN_USER_SWITCHER, value = false)
+ },
+ mocks =
+ TestMocksModule(
+ dozeParameters = dozeParams,
+ ),
+ )
+
+ keyguardRepository.setKeyguardShowing(false)
+ deviceProvisioningRepository.setFactoryResetProtectionActive(false)
+ powerRepository.updateWakefulness(
+ rawState = WakefulnessState.AWAKE,
+ lastWakeReason = WakeSleepReason.OTHER,
+ lastSleepReason = WakeSleepReason.OTHER,
+ )
+ }
+
+ @Test
+ fun animationsEnabled_isFalse_whenFrpIsActive() =
+ scope.runTest {
+ deviceProvisioningRepository.setFactoryResetProtectionActive(true)
+ keyguardTransitionRepository.sendTransitionStep(
+ TransitionStep(
+ transitionState = TransitionState.STARTED,
+ )
+ )
+ val animationsEnabled by collectLastValue(underTest.animationsEnabled)
+ runCurrent()
+ assertThat(animationsEnabled).isFalse()
+ }
+
+ @Test
+ fun animationsEnabled_isFalse_whenDeviceAsleepAndNotPulsing() =
+ scope.runTest {
+ powerRepository.updateWakefulness(
+ rawState = WakefulnessState.ASLEEP,
+ lastWakeReason = WakeSleepReason.POWER_BUTTON,
+ lastSleepReason = WakeSleepReason.OTHER,
+ )
+ keyguardTransitionRepository.sendTransitionStep(
+ TransitionStep(
+ transitionState = TransitionState.STARTED,
+ )
+ )
+ keyguardRepository.setDozeTransitionModel(
+ DozeTransitionModel(
+ to = DozeStateModel.DOZE_AOD,
+ )
+ )
+ val animationsEnabled by collectLastValue(underTest.animationsEnabled)
+ runCurrent()
+ assertThat(animationsEnabled).isFalse()
+ }
+
+ @Test
+ fun animationsEnabled_isTrue_whenDeviceAsleepAndPulsing() =
+ scope.runTest {
+ powerRepository.updateWakefulness(
+ rawState = WakefulnessState.ASLEEP,
+ lastWakeReason = WakeSleepReason.POWER_BUTTON,
+ lastSleepReason = WakeSleepReason.OTHER,
+ )
+ keyguardTransitionRepository.sendTransitionStep(
+ TransitionStep(
+ transitionState = TransitionState.STARTED,
+ )
+ )
+ keyguardRepository.setDozeTransitionModel(
+ DozeTransitionModel(
+ to = DozeStateModel.DOZE_PULSING,
+ )
+ )
+ val animationsEnabled by collectLastValue(underTest.animationsEnabled)
+ runCurrent()
+ assertThat(animationsEnabled).isTrue()
+ }
+
+ @Test
+ fun animationsEnabled_isFalse_whenStartingToSleepAndNotControlScreenOff() =
+ scope.runTest {
+ powerRepository.updateWakefulness(
+ rawState = WakefulnessState.STARTING_TO_SLEEP,
+ lastWakeReason = WakeSleepReason.POWER_BUTTON,
+ lastSleepReason = WakeSleepReason.OTHER,
+ )
+ keyguardTransitionRepository.sendTransitionStep(
+ TransitionStep(
+ from = KeyguardState.GONE,
+ to = KeyguardState.AOD,
+ transitionState = TransitionState.STARTED,
+ )
+ )
+ whenever(dozeParams.shouldControlScreenOff()).thenReturn(false)
+ val animationsEnabled by collectLastValue(underTest.animationsEnabled)
+ runCurrent()
+ assertThat(animationsEnabled).isFalse()
+ }
+
+ @Test
+ fun animationsEnabled_isTrue_whenStartingToSleepAndControlScreenOff() =
+ scope.runTest {
+ powerRepository.updateWakefulness(
+ rawState = WakefulnessState.STARTING_TO_SLEEP,
+ lastWakeReason = WakeSleepReason.POWER_BUTTON,
+ lastSleepReason = WakeSleepReason.OTHER,
+ )
+ keyguardTransitionRepository.sendTransitionStep(
+ TransitionStep(
+ from = KeyguardState.GONE,
+ to = KeyguardState.AOD,
+ transitionState = TransitionState.STARTED,
+ )
+ )
+ whenever(dozeParams.shouldControlScreenOff()).thenReturn(true)
+ val animationsEnabled by collectLastValue(underTest.animationsEnabled)
+ runCurrent()
+ assertThat(animationsEnabled).isTrue()
+ }
+
+ @Test
+ fun animationsEnabled_isTrue_whenNotAsleep() =
+ scope.runTest {
+ powerRepository.updateWakefulness(
+ rawState = WakefulnessState.AWAKE,
+ lastWakeReason = WakeSleepReason.POWER_BUTTON,
+ lastSleepReason = WakeSleepReason.OTHER,
+ )
+ keyguardTransitionRepository.sendTransitionStep(
+ TransitionStep(
+ transitionState = TransitionState.STARTED,
+ )
+ )
+ val animationsEnabled by collectLastValue(underTest.animationsEnabled)
+ runCurrent()
+ assertThat(animationsEnabled).isTrue()
+ }
+
+ @Test
+ fun animationsEnabled_isTrue_whenKeyguardIsNotShowing() =
+ scope.runTest {
+ val animationsEnabled by collectLastValue(underTest.animationsEnabled)
+
+ keyguardTransitionRepository.sendTransitionStep(
+ TransitionStep(
+ transitionState = TransitionState.STARTED,
+ )
+ )
+ keyguardRepository.setKeyguardShowing(true)
+ runCurrent()
+
+ assertThat(animationsEnabled).isFalse()
+
+ keyguardRepository.setKeyguardShowing(false)
+ runCurrent()
+
+ assertThat(animationsEnabled).isTrue()
+ }
+
+ @SysUISingleton
+ @Component(
+ modules =
+ [
+ SysUITestModule::class,
+ BiometricsDomainLayerModule::class,
+ UserDomainLayerModule::class,
+ ]
+ )
+ interface TestComponent {
+
+ val underTest: NotificationIconContainerStatusBarViewModel
+
+ val deviceProvisioningRepository: FakeDeviceProvisioningRepository
+ val keyguardTransitionRepository: FakeKeyguardTransitionRepository
+ val keyguardRepository: FakeKeyguardRepository
+ val powerRepository: FakePowerRepository
+ val scope: TestScope
+
+ @Component.Factory
+ interface Factory {
+ fun create(
+ @BindsInstance test: SysuiTestCase,
+ mocks: TestMocksModule,
+ featureFlags: FakeFeatureFlagsClassicModule,
+ ): TestComponent
+ }
+ }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/FeedbackInfoTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/FeedbackInfoTest.java
index c9b77c5..9c20e54 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/FeedbackInfoTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/FeedbackInfoTest.java
@@ -54,9 +54,9 @@
import android.widget.TextView;
import com.android.internal.statusbar.IStatusBarService;
-import com.android.systemui.res.R;
import com.android.systemui.SysuiTestCase;
import com.android.systemui.plugins.statusbar.NotificationMenuRowPlugin;
+import com.android.systemui.res.R;
import com.android.systemui.statusbar.notification.AssistantFeedbackController;
import com.android.systemui.statusbar.notification.collection.NotificationEntry;
import com.android.systemui.statusbar.notification.collection.NotificationEntryBuilder;
@@ -132,7 +132,8 @@
public void testBindNotification_SetsTextApplicationName() {
when(mMockPackageManager.getApplicationLabel(any())).thenReturn("App Name");
mFeedbackInfo.bindGuts(mMockPackageManager, mSbn, getEntry(),
- mMockNotificationRow, mAssistantFeedbackController);
+ mMockNotificationRow, mAssistantFeedbackController, mStatusBarService,
+ mNotificationGutsManager);
final TextView textView = mFeedbackInfo.findViewById(R.id.pkg_name);
assertTrue(textView.getText().toString().contains("App Name"));
}
@@ -143,7 +144,8 @@
when(mMockPackageManager.getApplicationIcon(any(ApplicationInfo.class)))
.thenReturn(iconDrawable);
mFeedbackInfo.bindGuts(mMockPackageManager, mSbn, getEntry(),
- mMockNotificationRow, mAssistantFeedbackController);
+ mMockNotificationRow, mAssistantFeedbackController, mStatusBarService,
+ mNotificationGutsManager);
final ImageView iconView = mFeedbackInfo.findViewById(R.id.pkg_icon);
assertEquals(iconDrawable, iconView.getDrawable());
}
@@ -153,7 +155,7 @@
when(mAssistantFeedbackController.getFeedbackStatus(any(NotificationEntry.class)))
.thenReturn(STATUS_SILENCED);
mFeedbackInfo.bindGuts(mMockPackageManager, mSbn, getEntry(), mMockNotificationRow,
- mAssistantFeedbackController);
+ mAssistantFeedbackController, mStatusBarService, mNotificationGutsManager);
TextView prompt = mFeedbackInfo.findViewById(R.id.prompt);
assertEquals("This notification was automatically demoted to Silent by the system. "
+ "Let the developer know your feedback. Was this correct?",
@@ -165,7 +167,7 @@
when(mAssistantFeedbackController.getFeedbackStatus(any(NotificationEntry.class)))
.thenReturn(STATUS_PROMOTED);
mFeedbackInfo.bindGuts(mMockPackageManager, mSbn, getEntry(), mMockNotificationRow,
- mAssistantFeedbackController);
+ mAssistantFeedbackController, mStatusBarService, mNotificationGutsManager);
TextView prompt = mFeedbackInfo.findViewById(R.id.prompt);
assertEquals("This notification was automatically ranked higher in your shade. "
+ "Let the developer know your feedback. Was this correct?",
@@ -177,7 +179,7 @@
when(mAssistantFeedbackController.getFeedbackStatus(any(NotificationEntry.class)))
.thenReturn(STATUS_ALERTED);
mFeedbackInfo.bindGuts(mMockPackageManager, mSbn, getEntry(), mMockNotificationRow,
- mAssistantFeedbackController);
+ mAssistantFeedbackController, mStatusBarService, mNotificationGutsManager);
TextView prompt = mFeedbackInfo.findViewById(R.id.prompt);
assertEquals("This notification was automatically promoted to Default by the system. "
+ "Let the developer know your feedback. Was this correct?",
@@ -189,7 +191,7 @@
when(mAssistantFeedbackController.getFeedbackStatus(any(NotificationEntry.class)))
.thenReturn(STATUS_DEMOTED);
mFeedbackInfo.bindGuts(mMockPackageManager, mSbn, getEntry(), mMockNotificationRow,
- mAssistantFeedbackController);
+ mAssistantFeedbackController, mStatusBarService, mNotificationGutsManager);
TextView prompt = mFeedbackInfo.findViewById(R.id.prompt);
assertEquals("This notification was automatically ranked lower in your shade. "
+ "Let the developer know your feedback. Was this correct?",
@@ -199,7 +201,7 @@
@Test
public void testPositiveFeedback() {
mFeedbackInfo.bindGuts(mMockPackageManager, mSbn, getEntry(), mMockNotificationRow,
- mAssistantFeedbackController);
+ mAssistantFeedbackController, mStatusBarService, mNotificationGutsManager);
final View yes = mFeedbackInfo.findViewById(R.id.yes);
yes.performClick();
@@ -216,7 +218,7 @@
.thenReturn(true);
mFeedbackInfo.bindGuts(mMockPackageManager, mSbn, getEntry(), mMockNotificationRow,
- mAssistantFeedbackController);
+ mAssistantFeedbackController, mStatusBarService, mNotificationGutsManager);
final View no = mFeedbackInfo.findViewById(R.id.no);
no.performClick();
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationGutsManagerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationGutsManagerTest.java
index 9f2afdf..8a730cf 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationGutsManagerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationGutsManagerTest.java
@@ -33,7 +33,6 @@
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyBoolean;
import static org.mockito.ArgumentMatchers.anyInt;
-import static org.mockito.ArgumentMatchers.anySet;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.doNothing;
import static org.mockito.Mockito.mock;
@@ -89,8 +88,8 @@
import com.android.systemui.statusbar.notification.people.PeopleNotificationIdentifier;
import com.android.systemui.statusbar.notification.row.NotificationGutsManager.OnSettingsClickListener;
import com.android.systemui.statusbar.notification.stack.NotificationListContainer;
-import com.android.systemui.statusbar.phone.HeadsUpManagerPhone;
import com.android.systemui.statusbar.policy.DeviceProvisionedController;
+import com.android.systemui.statusbar.policy.HeadsUpManager;
import com.android.systemui.util.concurrency.FakeExecutor;
import com.android.systemui.util.kotlin.JavaAdapter;
import com.android.systemui.util.time.FakeSystemClock;
@@ -152,7 +151,7 @@
@Mock private AssistantFeedbackController mAssistantFeedbackController;
@Mock private NotificationLockscreenUserManager mNotificationLockscreenUserManager;
@Mock private StatusBarStateController mStatusBarStateController;
- @Mock private HeadsUpManagerPhone mHeadsUpManagerPhone;
+ @Mock private HeadsUpManager mHeadsUpManager;
@Mock private ActivityStarter mActivityStarter;
@Mock private UserManager mUserManager;
@@ -171,7 +170,7 @@
mTestScope.getBackgroundScope(),
new WindowRootViewVisibilityRepository(mBarService, mExecutor),
new FakeKeyguardRepository(),
- mHeadsUpManagerPhone,
+ mHeadsUpManager,
PowerInteractorFactory.create().getPowerInteractor());
mGutsManager = new NotificationGutsManager(
@@ -196,9 +195,10 @@
mWindowRootViewVisibilityInteractor,
mNotificationLockscreenUserManager,
mStatusBarStateController,
+ mBarService,
mDeviceProvisionedController,
mMetricsLogger,
- mHeadsUpManagerPhone,
+ mHeadsUpManager,
mActivityStarter);
mGutsManager.setUpWithPresenter(mPresenter, mNotificationListContainer,
mOnSettingsClickListener);
@@ -239,7 +239,7 @@
anyInt(),
anyBoolean(),
any(Runnable.class));
- verify(mHeadsUpManagerPhone).setGutsShown(realRow.getEntry(), true);
+ verify(mHeadsUpManager).setGutsShown(realRow.getEntry(), true);
assertEquals(View.VISIBLE, guts.getVisibility());
mGutsManager.closeAndSaveGuts(false, false, true, 0, 0, false);
@@ -247,7 +247,7 @@
verify(guts).closeControls(anyBoolean(), anyBoolean(), anyInt(), anyInt(), anyBoolean());
verify(row, times(1)).setGutsView(any());
mTestableLooper.processAllMessages();
- verify(mHeadsUpManagerPhone).setGutsShown(realRow.getEntry(), false);
+ verify(mHeadsUpManager).setGutsShown(realRow.getEntry(), false);
}
@Test
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationTestHelper.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationTestHelper.java
index ac680e6..cb73108 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationTestHelper.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationTestHelper.java
@@ -61,6 +61,7 @@
import com.android.systemui.media.controls.util.MediaFeatureFlag;
import com.android.systemui.media.dialog.MediaOutputDialogFactory;
import com.android.systemui.plugins.statusbar.StatusBarStateController;
+import com.android.systemui.res.R;
import com.android.systemui.statusbar.NotificationMediaManager;
import com.android.systemui.statusbar.NotificationRemoteInputManager;
import com.android.systemui.statusbar.NotificationShadeWindowController;
@@ -81,14 +82,13 @@
import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow.OnExpandClickListener;
import com.android.systemui.statusbar.notification.row.NotificationRowContentBinder.InflationFlag;
import com.android.systemui.statusbar.notification.stack.NotificationChildrenContainerLogger;
-import com.android.systemui.statusbar.phone.HeadsUpManagerPhone;
import com.android.systemui.statusbar.phone.KeyguardBypassController;
+import com.android.systemui.statusbar.policy.HeadsUpManager;
import com.android.systemui.statusbar.policy.InflatedSmartReplyState;
import com.android.systemui.statusbar.policy.InflatedSmartReplyViewHolder;
import com.android.systemui.statusbar.policy.SmartReplyConstants;
import com.android.systemui.statusbar.policy.SmartReplyStateInflater;
import com.android.systemui.statusbar.policy.dagger.RemoteInputViewSubcomponent;
-import com.android.systemui.res.R;
import com.android.systemui.wmshell.BubblesManager;
import com.android.systemui.wmshell.BubblesTestActivity;
@@ -123,7 +123,7 @@
private final GroupMembershipManager mGroupMembershipManager;
private final GroupExpansionManager mGroupExpansionManager;
private ExpandableNotificationRow mRow;
- private final HeadsUpManagerPhone mHeadsUpManager;
+ private final HeadsUpManager mHeadsUpManager;
private final NotifBindPipeline mBindPipeline;
private final NotifCollectionListener mBindPipelineEntryListener;
private final RowContentBindStage mBindStage;
@@ -161,7 +161,7 @@
mKeyguardBypassController = mock(KeyguardBypassController.class);
mGroupMembershipManager = mock(GroupMembershipManager.class);
mGroupExpansionManager = mock(GroupExpansionManager.class);
- mHeadsUpManager = mock(HeadsUpManagerPhone.class);
+ mHeadsUpManager = mock(HeadsUpManager.class);
mIconManager = new IconManager(
mock(CommonNotifCollection.class),
mock(LauncherApps.class),
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutControllerTest.java
index ffe312b..20197e3 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutControllerTest.java
@@ -77,7 +77,6 @@
import com.android.systemui.statusbar.notification.collection.NotifCollection;
import com.android.systemui.statusbar.notification.collection.NotifPipeline;
import com.android.systemui.statusbar.notification.collection.provider.NotificationDismissibilityProvider;
-import com.android.systemui.statusbar.notification.collection.provider.SeenNotificationsProviderImpl;
import com.android.systemui.statusbar.notification.collection.provider.VisibilityLocationProviderDelegator;
import com.android.systemui.statusbar.notification.collection.render.GroupExpansionManager;
import com.android.systemui.statusbar.notification.collection.render.NotifStats;
@@ -88,13 +87,15 @@
import com.android.systemui.statusbar.notification.row.NotificationGutsManager;
import com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayoutController.NotificationPanelEvent;
import com.android.systemui.statusbar.notification.stack.NotificationSwipeHelper.NotificationCallback;
+import com.android.systemui.statusbar.notification.stack.data.repository.NotificationListRepository;
+import com.android.systemui.statusbar.notification.stack.domain.interactor.NotificationListInteractor;
import com.android.systemui.statusbar.notification.stack.ui.viewmodel.NotificationListViewModel;
-import com.android.systemui.statusbar.phone.HeadsUpManagerPhone;
import com.android.systemui.statusbar.phone.KeyguardBypassController;
import com.android.systemui.statusbar.phone.NotificationIconAreaController;
import com.android.systemui.statusbar.phone.ScrimController;
import com.android.systemui.statusbar.policy.ConfigurationController;
import com.android.systemui.statusbar.policy.DeviceProvisionedController;
+import com.android.systemui.statusbar.policy.HeadsUpManager;
import com.android.systemui.statusbar.policy.ResourcesSplitShadeStateController;
import com.android.systemui.statusbar.policy.ZenModeController;
import com.android.systemui.tuner.TunerService;
@@ -124,7 +125,7 @@
@Mock private NotificationGutsManager mNotificationGutsManager;
@Mock private NotificationsController mNotificationsController;
@Mock private NotificationVisibilityProvider mVisibilityProvider;
- @Mock private HeadsUpManagerPhone mHeadsUpManager;
+ @Mock private HeadsUpManager mHeadsUpManager;
@Mock private NotificationRoundnessManager mNotificationRoundnessManager;
@Mock private TunerService mTunerService;
@Mock private DeviceProvisionedController mDeviceProvisionedController;
@@ -170,8 +171,8 @@
@Captor
private ArgumentCaptor<StatusBarStateController.StateListener> mStateListenerArgumentCaptor;
- private final SeenNotificationsProviderImpl mSeenNotificationsProvider =
- new SeenNotificationsProviderImpl();
+ private final NotificationListInteractor mNotificationListInteractor =
+ new NotificationListInteractor(new NotificationListRepository());
private NotificationStackScrollLayoutController mController;
@@ -503,7 +504,7 @@
@Test
public void testSetNotifStats_updatesHasFilteredOutSeenNotifications() {
initController(/* viewIsAttached= */ true);
- mSeenNotificationsProvider.setHasFilteredOutSeenNotifications(true);
+ mNotificationListInteractor.setHasFilteredOutSeenNotifications(true);
mController.getNotifStackController().setNotifStats(NotifStats.getEmpty());
verify(mNotificationStackScrollLayout).setHasFilteredOutSeenNotifications(true);
verify(mNotificationStackScrollLayout).updateFooter();
@@ -703,7 +704,7 @@
mUiEventLogger,
mRemoteInputManager,
mVisibilityLocationProviderDelegator,
- mSeenNotificationsProvider,
+ mNotificationListInteractor,
mShadeController,
mJankMonitor,
mStackLogger,
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/ui/viewmodel/SharedNotificationContainerViewModelTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/ui/viewmodel/SharedNotificationContainerViewModelTest.kt
index e254dd0..ac11ff2 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/ui/viewmodel/SharedNotificationContainerViewModelTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/ui/viewmodel/SharedNotificationContainerViewModelTest.kt
@@ -19,36 +19,35 @@
import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.filters.SmallTest
-import com.android.systemui.res.R
+import com.android.SysUITestModule
+import com.android.TestMocksModule
import com.android.systemui.SysuiTestCase
import com.android.systemui.common.shared.model.SharedNotificationContainerPosition
import com.android.systemui.common.ui.data.repository.FakeConfigurationRepository
import com.android.systemui.coroutines.collectLastValue
+import com.android.systemui.dagger.SysUISingleton
+import com.android.systemui.flags.FakeFeatureFlagsClassicModule
+import com.android.systemui.flags.Flags
import com.android.systemui.keyguard.data.repository.FakeKeyguardRepository
import com.android.systemui.keyguard.data.repository.FakeKeyguardTransitionRepository
import com.android.systemui.keyguard.domain.interactor.KeyguardInteractor
-import com.android.systemui.keyguard.domain.interactor.KeyguardTransitionInteractor
-import com.android.systemui.keyguard.domain.interactor.KeyguardTransitionInteractorFactory
import com.android.systemui.keyguard.shared.model.KeyguardState
import com.android.systemui.keyguard.shared.model.StatusBarState
import com.android.systemui.keyguard.shared.model.TransitionState
import com.android.systemui.keyguard.shared.model.TransitionStep
-import com.android.systemui.scene.SceneTestUtils
-import com.android.systemui.scene.shared.flag.FakeSceneContainerFlags
+import com.android.systemui.res.R
import com.android.systemui.shade.data.repository.FakeShadeRepository
-import com.android.systemui.shade.domain.interactor.ShadeInteractor
-import com.android.systemui.statusbar.disableflags.data.repository.FakeDisableFlagsRepository
import com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayoutController
import com.android.systemui.statusbar.notification.stack.NotificationStackSizeCalculator
import com.android.systemui.statusbar.notification.stack.domain.interactor.SharedNotificationContainerInteractor
-import com.android.systemui.statusbar.pipeline.mobile.data.repository.FakeUserSetupRepository
-import com.android.systemui.statusbar.policy.DeviceProvisionedController
-import com.android.systemui.statusbar.policy.ResourcesSplitShadeStateController
-import com.android.systemui.user.domain.interactor.UserInteractor
+import com.android.systemui.user.domain.UserDomainLayerModule
import com.android.systemui.util.mockito.any
import com.android.systemui.util.mockito.mock
import com.android.systemui.util.mockito.whenever
import com.google.common.truth.Truth.assertThat
+import dagger.BindsInstance
+import dagger.Component
+import kotlinx.coroutines.test.TestScope
import kotlinx.coroutines.test.runCurrent
import kotlinx.coroutines.test.runTest
import org.junit.Before
@@ -60,29 +59,27 @@
@SmallTest
@RunWith(AndroidJUnit4::class)
class SharedNotificationContainerViewModelTest : SysuiTestCase() {
- private val utils = SceneTestUtils(this)
- private val testScope = utils.testScope
+ private lateinit var testComponent: TestComponent
- private val disableFlagsRepository = FakeDisableFlagsRepository()
- private val userSetupRepository = FakeUserSetupRepository()
- private val shadeRepository = FakeShadeRepository()
- private val keyguardRepository = FakeKeyguardRepository()
- private val sceneContainerFlags = FakeSceneContainerFlags()
- private val sceneInteractor = utils.sceneInteractor()
-
- private lateinit var configurationRepository: FakeConfigurationRepository
- private lateinit var sharedNotificationContainerInteractor:
- SharedNotificationContainerInteractor
- private lateinit var underTest: SharedNotificationContainerViewModel
- private lateinit var keyguardInteractor: KeyguardInteractor
- private lateinit var keyguardTransitionInteractor: KeyguardTransitionInteractor
- private lateinit var keyguardTransitionRepository: FakeKeyguardTransitionRepository
- private lateinit var shadeInteractor: ShadeInteractor
+ private val shadeRepository
+ get() = testComponent.shadeRepository
+ private val keyguardRepository
+ get() = testComponent.keyguardRepository
+ private val configurationRepository
+ get() = testComponent.configurationRepository
+ private val sharedNotificationContainerInteractor: SharedNotificationContainerInteractor
+ get() = testComponent.sharedNotificationContainerInteractor
+ private val underTest: SharedNotificationContainerViewModel
+ get() = testComponent.underTest
+ private val keyguardInteractor: KeyguardInteractor
+ get() = testComponent.keyguardInteractor
+ private val keyguardTransitionRepository
+ get() = testComponent.keyguardTransitionRepository
+ private val testScope
+ get() = testComponent.testScope
@Mock private lateinit var notificationStackSizeCalculator: NotificationStackSizeCalculator
- @Mock private lateinit var deviceProvisionedController: DeviceProvisionedController
- @Mock private lateinit var userInteractor: UserInteractor
@Mock
private lateinit var notificationStackScrollLayoutController:
NotificationStackScrollLayoutController
@@ -94,43 +91,21 @@
whenever(notificationStackScrollLayoutController.getView()).thenReturn(mock())
whenever(notificationStackScrollLayoutController.getShelfHeight()).thenReturn(0)
- configurationRepository = FakeConfigurationRepository()
- KeyguardTransitionInteractorFactory.create(
- scope = testScope.backgroundScope,
- )
- .also {
- keyguardInteractor = it.keyguardInteractor
- keyguardTransitionInteractor = it.keyguardTransitionInteractor
- keyguardTransitionRepository = it.repository
- }
- sharedNotificationContainerInteractor =
- SharedNotificationContainerInteractor(
- configurationRepository,
- mContext,
- ResourcesSplitShadeStateController()
- )
- shadeInteractor =
- ShadeInteractor(
- testScope.backgroundScope,
- disableFlagsRepository,
- sceneContainerFlags,
- { sceneInteractor },
- keyguardRepository,
- userSetupRepository,
- deviceProvisionedController,
- userInteractor,
- sharedNotificationContainerInteractor,
- shadeRepository,
- )
- underTest =
- SharedNotificationContainerViewModel(
- sharedNotificationContainerInteractor,
- keyguardInteractor,
- keyguardTransitionInteractor,
- notificationStackSizeCalculator,
- notificationStackScrollLayoutController,
- shadeInteractor
- )
+ testComponent =
+ DaggerSharedNotificationContainerViewModelTest_TestComponent.factory()
+ .create(
+ test = this,
+ featureFlags =
+ FakeFeatureFlagsClassicModule {
+ set(Flags.FULL_SCREEN_USER_SWITCHER, true)
+ },
+ mocks =
+ TestMocksModule(
+ notificationStackSizeCalculator = notificationStackSizeCalculator,
+ notificationStackScrollLayoutController =
+ notificationStackScrollLayoutController,
+ )
+ )
}
@Test
@@ -404,4 +379,34 @@
)
)
}
+
+ @SysUISingleton
+ @Component(
+ modules =
+ [
+ SysUITestModule::class,
+ UserDomainLayerModule::class,
+ ]
+ )
+ interface TestComponent {
+
+ val underTest: SharedNotificationContainerViewModel
+
+ val configurationRepository: FakeConfigurationRepository
+ val keyguardRepository: FakeKeyguardRepository
+ val keyguardInteractor: KeyguardInteractor
+ val keyguardTransitionRepository: FakeKeyguardTransitionRepository
+ val shadeRepository: FakeShadeRepository
+ val sharedNotificationContainerInteractor: SharedNotificationContainerInteractor
+ val testScope: TestScope
+
+ @Component.Factory
+ interface Factory {
+ fun create(
+ @BindsInstance test: SysuiTestCase,
+ featureFlags: FakeFeatureFlagsClassicModule,
+ mocks: TestMocksModule,
+ ): TestComponent
+ }
+ }
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/CentralSurfacesCommandQueueCallbacksTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/CentralSurfacesCommandQueueCallbacksTest.java
index a5d3484..e7dad6a 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/CentralSurfacesCommandQueueCallbacksTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/CentralSurfacesCommandQueueCallbacksTest.java
@@ -57,6 +57,7 @@
import com.android.systemui.statusbar.disableflags.DisableFlagsLogger;
import com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayoutController;
import com.android.systemui.statusbar.policy.DeviceProvisionedController;
+import com.android.systemui.statusbar.policy.HeadsUpManager;
import com.android.systemui.statusbar.policy.KeyguardStateController;
import com.android.systemui.statusbar.policy.RemoteInputQuickSettingsDisabler;
@@ -85,7 +86,7 @@
private final MetricsLogger mMetricsLogger = new FakeMetricsLogger();
@Mock private KeyguardUpdateMonitor mKeyguardUpdateMonitor;
@Mock private KeyguardStateController mKeyguardStateController;
- @Mock private HeadsUpManagerPhone mHeadsUpManager;
+ @Mock private HeadsUpManager mHeadsUpManager;
@Mock private WakefulnessLifecycle mWakefulnessLifecycle;
@Mock private DeviceProvisionedController mDeviceProvisionedController;
@Mock private StatusBarKeyguardViewManager mStatusBarKeyguardViewManager;
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/CentralSurfacesImplTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/CentralSurfacesImplTest.java
index e33fa22..f18af61 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/CentralSurfacesImplTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/CentralSurfacesImplTest.java
@@ -85,7 +85,6 @@
import com.android.keyguard.TestScopeProvider;
import com.android.keyguard.ViewMediatorCallback;
import com.android.systemui.InitController;
-import com.android.systemui.res.R;
import com.android.systemui.SysuiTestCase;
import com.android.systemui.accessibility.floatingmenu.AccessibilityFloatingMenuController;
import com.android.systemui.animation.ActivityLaunchAnimator;
@@ -117,6 +116,7 @@
import com.android.systemui.plugins.PluginManager;
import com.android.systemui.plugins.statusbar.StatusBarStateController;
import com.android.systemui.power.domain.interactor.PowerInteractor;
+import com.android.systemui.res.R;
import com.android.systemui.scene.domain.interactor.WindowRootViewVisibilityInteractor;
import com.android.systemui.settings.UserTracker;
import com.android.systemui.settings.brightness.BrightnessSliderController;
@@ -219,7 +219,7 @@
@Mock private KeyguardIndicationController mKeyguardIndicationController;
@Mock private NotificationStackScrollLayout mStackScroller;
@Mock private NotificationStackScrollLayoutController mStackScrollerController;
- @Mock private HeadsUpManagerPhone mHeadsUpManager;
+ @Mock private HeadsUpManager mHeadsUpManager;
@Mock private NotificationPanelViewController mNotificationPanelViewController;
@Mock private ShadeLogger mShadeLogger;
@Mock private NotificationPanelView mNotificationPanelView;
@@ -336,6 +336,7 @@
mFeatureFlags.set(Flags.WM_ENABLE_PREDICTIVE_BACK_SYSUI, false);
// Set default value to avoid IllegalStateException.
mFeatureFlags.set(Flags.SHORTCUT_LIST_SEARCH_LAYOUT, false);
+ mFeatureFlags.setDefault(Flags.NOTIFICATION_ICON_CONTAINER_REFACTOR);
// For the Shade to respond to Back gesture, we must enable the event routing
mFeatureFlags.set(Flags.WM_SHADE_ALLOW_BACK_GESTURE, true);
// For the Shade to animate during the Back gesture, we must enable the animation flag.
@@ -343,6 +344,7 @@
mFeatureFlags.set(Flags.LIGHT_REVEAL_MIGRATION, true);
// Turn AOD on and toggle feature flag for jank fixes
mFeatureFlags.set(Flags.ZJ_285570694_LOCKSCREEN_TRANSITION_FROM_AOD, true);
+ mFeatureFlags.set(Flags.ALTERNATE_BOUNCER_VIEW, false);
when(mDozeParameters.getAlwaysOn()).thenReturn(true);
IThermalService thermalService = mock(IThermalService.class);
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/DozeServiceHostTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/DozeServiceHostTest.java
index ff6f40d5..593c587 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/DozeServiceHostTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/DozeServiceHostTest.java
@@ -53,6 +53,7 @@
import com.android.systemui.statusbar.notification.NotificationWakeUpCoordinator;
import com.android.systemui.statusbar.policy.BatteryController;
import com.android.systemui.statusbar.policy.DeviceProvisionedController;
+import com.android.systemui.statusbar.policy.HeadsUpManager;
import org.junit.Before;
import org.junit.Test;
@@ -72,7 +73,7 @@
private DozeServiceHost mDozeServiceHost;
- @Mock private HeadsUpManagerPhone mHeadsUpManager;
+ @Mock private HeadsUpManager mHeadsUpManager;
@Mock private ScrimController mScrimController;
@Mock private DozeScrimController mDozeScrimController;
@Mock private StatusBarStateControllerImpl mStatusBarStateController;
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/HeadsUpAppearanceControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/HeadsUpAppearanceControllerTest.java
index ec6286b..d84bb72 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/HeadsUpAppearanceControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/HeadsUpAppearanceControllerTest.java
@@ -47,6 +47,7 @@
import com.android.systemui.statusbar.notification.stack.NotificationRoundnessManager;
import com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayoutController;
import com.android.systemui.statusbar.policy.Clock;
+import com.android.systemui.statusbar.policy.HeadsUpManager;
import com.android.systemui.statusbar.policy.KeyguardStateController;
import org.junit.Assert;
@@ -72,7 +73,7 @@
private ExpandableNotificationRow mRow;
private NotificationEntry mEntry;
private HeadsUpStatusBarView mHeadsUpStatusBarView;
- private HeadsUpManagerPhone mHeadsUpManager;
+ private HeadsUpManager mHeadsUpManager;
private View mOperatorNameView;
private StatusBarStateController mStatusbarStateController;
private PhoneStatusBarTransitions mPhoneStatusBarTransitions;
@@ -93,7 +94,7 @@
mEntry = mRow.getEntry();
mHeadsUpStatusBarView = new HeadsUpStatusBarView(mContext, mock(View.class),
mock(TextView.class));
- mHeadsUpManager = mock(HeadsUpManagerPhone.class);
+ mHeadsUpManager = mock(HeadsUpManager.class);
mOperatorNameView = new View(mContext);
mStatusbarStateController = mock(StatusBarStateController.class);
mPhoneStatusBarTransitions = mock(PhoneStatusBarTransitions.class);
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/HeadsUpManagerPhoneTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/HeadsUpManagerPhoneTest.java
index 1bc522d..cda2a74 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/HeadsUpManagerPhoneTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/HeadsUpManagerPhoneTest.java
@@ -32,8 +32,8 @@
import androidx.test.filters.SmallTest;
import com.android.internal.logging.UiEventLogger;
-import com.android.systemui.res.R;
import com.android.systemui.plugins.statusbar.StatusBarStateController;
+import com.android.systemui.res.R;
import com.android.systemui.shade.ShadeExpansionStateManager;
import com.android.systemui.statusbar.AlertingNotificationManager;
import com.android.systemui.statusbar.AlertingNotificationManagerTest;
@@ -43,6 +43,7 @@
import com.android.systemui.statusbar.notification.collection.render.GroupMembershipManager;
import com.android.systemui.statusbar.policy.AccessibilityManagerWrapper;
import com.android.systemui.statusbar.policy.ConfigurationController;
+import com.android.systemui.statusbar.policy.HeadsUpManager;
import com.android.systemui.statusbar.policy.HeadsUpManagerLogger;
import org.junit.After;
@@ -71,7 +72,6 @@
@Mock private AccessibilityManagerWrapper mAccessibilityManagerWrapper;
@Mock private ShadeExpansionStateManager mShadeExpansionStateManager;
@Mock private UiEventLogger mUiEventLogger;
- private boolean mLivesPastNormalTime;
private static final class TestableHeadsUpManagerPhone extends HeadsUpManagerPhone {
TestableHeadsUpManagerPhone(
@@ -149,7 +149,7 @@
@Test
public void testSnooze() {
- final HeadsUpManagerPhone hmp = createHeadsUpManagerPhone();
+ final HeadsUpManager hmp = createHeadsUpManagerPhone();
final NotificationEntry entry = createEntry(/* id = */ 0);
hmp.showNotification(entry);
@@ -160,7 +160,7 @@
@Test
public void testSwipedOutNotification() {
- final HeadsUpManagerPhone hmp = createHeadsUpManagerPhone();
+ final HeadsUpManager hmp = createHeadsUpManagerPhone();
final NotificationEntry entry = createEntry(/* id = */ 0);
hmp.showNotification(entry);
@@ -176,7 +176,7 @@
@Test
public void testCanRemoveImmediately_swipedOut() {
- final HeadsUpManagerPhone hmp = createHeadsUpManagerPhone();
+ final HeadsUpManager hmp = createHeadsUpManagerPhone();
final NotificationEntry entry = createEntry(/* id = */ 0);
hmp.showNotification(entry);
@@ -189,7 +189,7 @@
@Ignore("b/141538055")
@Test
public void testCanRemoveImmediately_notTopEntry() {
- final HeadsUpManagerPhone hmp = createHeadsUpManagerPhone();
+ final HeadsUpManager hmp = createHeadsUpManagerPhone();
final NotificationEntry earlierEntry = createEntry(/* id = */ 0);
final NotificationEntry laterEntry = createEntry(/* id = */ 1);
laterEntry.setRow(mRow);
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManagerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManagerTest.java
index bac8579..b36d09d 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManagerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManagerTest.java
@@ -18,6 +18,9 @@
import static com.android.systemui.bouncer.shared.constants.KeyguardBouncerConstants.EXPANSION_HIDDEN;
import static com.android.systemui.bouncer.shared.constants.KeyguardBouncerConstants.EXPANSION_VISIBLE;
+
+import static kotlinx.coroutines.test.TestCoroutineDispatchersKt.StandardTestDispatcher;
+
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import static org.mockito.ArgumentMatchers.any;
@@ -33,7 +36,6 @@
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
-import static kotlinx.coroutines.test.TestCoroutineDispatchersKt.StandardTestDispatcher;
import android.service.trust.TrustAgentService;
import android.testing.AndroidTestingRunner;
@@ -175,6 +177,7 @@
mFeatureFlags.set(Flags.REFACTOR_KEYGUARD_DISMISS_INTENT, false);
mFeatureFlags.set(Flags.UDFPS_NEW_TOUCH_DETECTION, true);
mFeatureFlags.set(Flags.KEYGUARD_WM_STATE_REFACTOR, false);
+ mFeatureFlags.set(Flags.ALTERNATE_BOUNCER_VIEW, false);
when(mNotificationShadeWindowController.getWindowRootView())
.thenReturn(mNotificationShadeWindowView);
@@ -761,6 +764,30 @@
}
@Test
+ public void handleDispatchTouchEvent_alternateBouncerViewFlagEnabled() {
+ mStatusBarKeyguardViewManager.addCallback(mCallback);
+
+ // GIVEN alternate bouncer view flag enabled & the alternate bouncer is visible
+ mFeatureFlags.set(Flags.ALTERNATE_BOUNCER_VIEW, true);
+ when(mAlternateBouncerInteractor.isVisibleState()).thenReturn(true);
+
+ // THEN the touch is not acted upon
+ verify(mCallback, never()).onTouch(any());
+ }
+
+ @Test
+ public void onInterceptTouch_alternateBouncerViewFlagEnabled() {
+ // GIVEN alternate bouncer view flag enabled & the alternate bouncer is visible
+ mFeatureFlags.set(Flags.ALTERNATE_BOUNCER_VIEW, true);
+ when(mAlternateBouncerInteractor.isVisibleState()).thenReturn(true);
+
+ // THEN the touch is not intercepted
+ assertFalse(mStatusBarKeyguardViewManager.shouldInterceptTouchEvent(
+ MotionEvent.obtain(0L, 0L, MotionEvent.ACTION_DOWN, 0f, 0f, 0)
+ ));
+ }
+
+ @Test
public void handleDispatchTouchEvent_alternateBouncerNotVisible() {
mStatusBarKeyguardViewManager.addCallback(mCallback);
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarNotificationActivityStarterTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarNotificationActivityStarterTest.java
index 8013e5e..beac995 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarNotificationActivityStarterTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarNotificationActivityStarterTest.java
@@ -92,6 +92,7 @@
import com.android.systemui.statusbar.notification.row.NotificationTestHelper;
import com.android.systemui.statusbar.notification.row.OnUserInteractionCallback;
import com.android.systemui.statusbar.notification.stack.NotificationListContainer;
+import com.android.systemui.statusbar.policy.HeadsUpManager;
import com.android.systemui.statusbar.policy.KeyguardStateController;
import com.android.systemui.util.concurrency.FakeExecutor;
import com.android.systemui.util.time.FakeSystemClock;
@@ -218,7 +219,7 @@
mScreenOffAnimationController,
mStatusBarStateController).getPowerInteractor();
- HeadsUpManagerPhone headsUpManager = mock(HeadsUpManagerPhone.class);
+ HeadsUpManager headsUpManager = mock(HeadsUpManager.class);
NotificationLaunchAnimatorControllerProvider notificationAnimationProvider =
new NotificationLaunchAnimatorControllerProvider(
new NotificationExpansionRepository(),
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarNotificationPresenterTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarNotificationPresenterTest.java
index 233f407..ee4f208 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarNotificationPresenterTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarNotificationPresenterTest.java
@@ -15,6 +15,7 @@
package com.android.systemui.statusbar.phone;
import static android.view.Display.DEFAULT_DISPLAY;
+
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import static org.mockito.Mockito.mock;
@@ -59,6 +60,7 @@
import com.android.systemui.statusbar.notification.stack.NotificationListContainer;
import com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayout;
import com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayoutController;
+import com.android.systemui.statusbar.policy.HeadsUpManager;
import com.android.systemui.statusbar.policy.KeyguardStateController;
import org.junit.Before;
@@ -106,7 +108,7 @@
mContext,
shadeViewController,
mock(QuickSettingsController.class),
- mock(HeadsUpManagerPhone.class),
+ mock(HeadsUpManager.class),
notificationShadeWindowView,
mock(ActivityStarter.class),
stackScrollLayoutController,
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/wifi/data/repository/WifiRepositorySwitcherTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/wifi/data/repository/WifiRepositorySwitcherTest.kt
index dbaa29b..d06a6e2 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/wifi/data/repository/WifiRepositorySwitcherTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/wifi/data/repository/WifiRepositorySwitcherTest.kt
@@ -20,7 +20,6 @@
import android.net.wifi.WifiManager
import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.filters.SmallTest
-import com.android.systemui.RoboPilotTest
import com.android.systemui.SysuiTestCase
import com.android.systemui.demomode.DemoMode
import com.android.systemui.demomode.DemoModeController
@@ -53,7 +52,6 @@
@OptIn(ExperimentalCoroutinesApi::class)
@Suppress("EXPERIMENTAL_IS_NOT_ENABLED")
@SmallTest
-@RoboPilotTest
@RunWith(AndroidJUnit4::class)
class WifiRepositorySwitcherTest : SysuiTestCase() {
private lateinit var underTest: WifiRepositorySwitcher
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/wifi/data/repository/prod/DisabledWifiRepositoryTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/wifi/data/repository/prod/DisabledWifiRepositoryTest.kt
index 206ac1d..ce00250 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/wifi/data/repository/prod/DisabledWifiRepositoryTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/wifi/data/repository/prod/DisabledWifiRepositoryTest.kt
@@ -18,7 +18,6 @@
import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.filters.SmallTest
-import com.android.systemui.RoboPilotTest
import com.android.systemui.SysuiTestCase
import com.android.systemui.statusbar.pipeline.shared.data.model.DataActivityModel
import com.android.systemui.statusbar.pipeline.wifi.shared.model.WifiNetworkModel
@@ -28,7 +27,6 @@
import org.junit.runner.RunWith
@SmallTest
-@RoboPilotTest
@RunWith(AndroidJUnit4::class)
class DisabledWifiRepositoryTest : SysuiTestCase() {
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/wifi/data/repository/prod/WifiRepositoryImplTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/wifi/data/repository/prod/WifiRepositoryImplTest.kt
index c2e75aa..cf20ba8 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/wifi/data/repository/prod/WifiRepositoryImplTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/wifi/data/repository/prod/WifiRepositoryImplTest.kt
@@ -35,7 +35,6 @@
import android.telephony.SubscriptionManager.INVALID_SUBSCRIPTION_ID
import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.filters.SmallTest
-import com.android.systemui.RoboPilotTest
import com.android.systemui.SysuiTestCase
import com.android.systemui.coroutines.collectLastValue
import com.android.systemui.log.table.TableLogBuffer
@@ -73,7 +72,6 @@
@Suppress("EXPERIMENTAL_IS_NOT_ENABLED")
@OptIn(ExperimentalCoroutinesApi::class)
@SmallTest
-@RoboPilotTest
@RunWith(AndroidJUnit4::class)
class WifiRepositoryImplTest : SysuiTestCase() {
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/wifi/domain/interactor/WifiInteractorImplTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/wifi/domain/interactor/WifiInteractorImplTest.kt
index 1db8065..7fbbfc7 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/wifi/domain/interactor/WifiInteractorImplTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/wifi/domain/interactor/WifiInteractorImplTest.kt
@@ -19,7 +19,6 @@
import android.net.wifi.WifiManager
import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.filters.SmallTest
-import com.android.systemui.RoboPilotTest
import com.android.systemui.SysuiTestCase
import com.android.systemui.coroutines.collectLastValue
import com.android.systemui.statusbar.pipeline.shared.data.model.ConnectivitySlot
@@ -43,7 +42,6 @@
@OptIn(ExperimentalCoroutinesApi::class)
@Suppress("EXPERIMENTAL_IS_NOT_ENABLED")
@SmallTest
-@RoboPilotTest
@RunWith(AndroidJUnit4::class)
class WifiInteractorImplTest : SysuiTestCase() {
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/wifi/ui/viewmodel/WifiViewModelTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/wifi/ui/viewmodel/WifiViewModelTest.kt
index 49a2648..2d1a27f 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/wifi/ui/viewmodel/WifiViewModelTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/wifi/ui/viewmodel/WifiViewModelTest.kt
@@ -19,7 +19,6 @@
import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.filters.SmallTest
import com.android.settingslib.AccessibilityContentDescriptions.WIFI_OTHER_DEVICE_CONNECTION
-import com.android.systemui.RoboPilotTest
import com.android.systemui.SysuiTestCase
import com.android.systemui.common.shared.model.ContentDescription.Companion.loadContentDescription
import com.android.systemui.coroutines.collectLastValue
@@ -53,7 +52,6 @@
import org.mockito.MockitoAnnotations
@SmallTest
-@RoboPilotTest
@RunWith(AndroidJUnit4::class)
class WifiViewModelTest : SysuiTestCase() {
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/HeadsUpManagerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/HeadsUpManagerTest.java
index 64ebcd9..4f3f564 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/HeadsUpManagerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/HeadsUpManagerTest.java
@@ -41,10 +41,13 @@
import android.app.Person;
import android.content.Context;
import android.content.Intent;
+import android.graphics.Region;
import android.os.Handler;
import android.testing.AndroidTestingRunner;
import android.testing.TestableLooper;
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
import androidx.test.filters.SmallTest;
import com.android.internal.logging.UiEventLogger;
@@ -73,7 +76,7 @@
private final HeadsUpManagerLogger mLogger = spy(new HeadsUpManagerLogger(logcatLogBuffer()));
@Mock private AccessibilityManagerWrapper mAccessibilityMgr;
- private final class TestableHeadsUpManager extends HeadsUpManager {
+ private final class TestableHeadsUpManager extends BaseHeadsUpManager {
TestableHeadsUpManager(Context context,
HeadsUpManagerLogger logger,
Handler handler,
@@ -85,9 +88,78 @@
mAutoDismissNotificationDecay = TEST_AUTO_DISMISS_TIME;
mStickyDisplayTime = TEST_STICKY_AUTO_DISMISS_TIME;
}
+
+ // The following are only implemented by HeadsUpManagerPhone. If you need them, use that.
+ @Override
+ public void addHeadsUpPhoneListener(@NonNull OnHeadsUpPhoneListenerChange listener) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public void addSwipedOutNotification(@NonNull String key) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public void extendHeadsUp() {
+ throw new UnsupportedOperationException();
+ }
+
+ @Nullable
+ @Override
+ public Region getTouchableRegion() {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public boolean isHeadsUpGoingAway() {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public void onExpandingFinished() {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public boolean removeNotification(@NonNull String key, boolean releaseImmediately,
+ boolean animate) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public void setAnimationStateHandler(@NonNull AnimationStateHandler handler) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public void setGutsShown(@NonNull NotificationEntry entry, boolean gutsShown) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public void setHeadsUpGoingAway(boolean headsUpGoingAway) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public void setRemoteInputActive(@NonNull NotificationEntry entry,
+ boolean remoteInputActive) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public void setTrackingHeadsUp(boolean tracking) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public boolean shouldSwallowClick(@NonNull String key) {
+ throw new UnsupportedOperationException();
+ }
}
- private HeadsUpManager createHeadsUpManager() {
+ private BaseHeadsUpManager createHeadsUpManager() {
return new TestableHeadsUpManager(mContext, mLogger, mTestHandler, mAccessibilityMgr,
mUiEventLoggerFake);
}
@@ -165,9 +237,10 @@
@Test
public void testHunRemovedLogging() {
- final HeadsUpManager hum = createHeadsUpManager();
+ final BaseHeadsUpManager hum = createHeadsUpManager();
final NotificationEntry notifEntry = createEntry(/* id = */ 0);
- final HeadsUpManager.HeadsUpEntry headsUpEntry = mock(HeadsUpManager.HeadsUpEntry.class);
+ final BaseHeadsUpManager.HeadsUpEntry headsUpEntry = mock(
+ BaseHeadsUpManager.HeadsUpEntry.class);
headsUpEntry.mEntry = notifEntry;
hum.onAlertEntryRemoved(headsUpEntry);
@@ -177,35 +250,37 @@
@Test
public void testShouldHeadsUpBecomePinned_hasFSI_notUnpinned_true() {
- final HeadsUpManager hum = createHeadsUpManager();
+ final BaseHeadsUpManager hum = createHeadsUpManager();
final NotificationEntry notifEntry = createFullScreenIntentEntry(/* id = */ 0);
// Add notifEntry to ANM mAlertEntries map and make it NOT unpinned
hum.showNotification(notifEntry);
- final HeadsUpManager.HeadsUpEntry headsUpEntry = hum.getHeadsUpEntry(notifEntry.getKey());
- headsUpEntry.wasUnpinned = false;
+ final BaseHeadsUpManager.HeadsUpEntry headsUpEntry = hum.getHeadsUpEntry(
+ notifEntry.getKey());
+ headsUpEntry.mWasUnpinned = false;
assertTrue(hum.shouldHeadsUpBecomePinned(notifEntry));
}
@Test
public void testShouldHeadsUpBecomePinned_wasUnpinned_false() {
- final HeadsUpManager hum = createHeadsUpManager();
+ final BaseHeadsUpManager hum = createHeadsUpManager();
final NotificationEntry notifEntry = createFullScreenIntentEntry(/* id = */ 0);
// Add notifEntry to ANM mAlertEntries map and make it unpinned
hum.showNotification(notifEntry);
- final HeadsUpManager.HeadsUpEntry headsUpEntry = hum.getHeadsUpEntry(notifEntry.getKey());
- headsUpEntry.wasUnpinned = true;
+ final BaseHeadsUpManager.HeadsUpEntry headsUpEntry = hum.getHeadsUpEntry(
+ notifEntry.getKey());
+ headsUpEntry.mWasUnpinned = true;
assertFalse(hum.shouldHeadsUpBecomePinned(notifEntry));
}
@Test
public void testShouldHeadsUpBecomePinned_noFSI_false() {
- final HeadsUpManager hum = createHeadsUpManager();
+ final BaseHeadsUpManager hum = createHeadsUpManager();
final NotificationEntry entry = createEntry(/* id = */ 0);
assertFalse(hum.shouldHeadsUpBecomePinned(entry));
@@ -214,7 +289,7 @@
@Test
public void testShowNotification_autoDismissesIncludingTouchAcceptanceDelay() {
- final HeadsUpManager hum = createHeadsUpManager();
+ final BaseHeadsUpManager hum = createHeadsUpManager();
final NotificationEntry entry = createEntry(/* id = */ 0);
useAccessibilityTimeout(false);
@@ -228,7 +303,7 @@
@Test
public void testShowNotification_autoDismissesWithDefaultTimeout() {
- final HeadsUpManager hum = createHeadsUpManager();
+ final BaseHeadsUpManager hum = createHeadsUpManager();
final NotificationEntry entry = createEntry(/* id = */ 0);
useAccessibilityTimeout(false);
@@ -242,7 +317,7 @@
@Test
public void testShowNotification_stickyForSomeTime_autoDismissesWithStickyTimeout() {
- final HeadsUpManager hum = createHeadsUpManager();
+ final BaseHeadsUpManager hum = createHeadsUpManager();
final NotificationEntry entry = createStickyForSomeTimeEntry(/* id = */ 0);
useAccessibilityTimeout(false);
@@ -256,7 +331,7 @@
@Test
public void testShowNotification_sticky_neverAutoDismisses() {
- final HeadsUpManager hum = createHeadsUpManager();
+ final BaseHeadsUpManager hum = createHeadsUpManager();
final NotificationEntry entry = createStickyEntry(/* id = */ 0);
useAccessibilityTimeout(false);
@@ -278,7 +353,7 @@
@Test
public void testShowNotification_autoDismissesWithAccessibilityTimeout() {
- final HeadsUpManager hum = createHeadsUpManager();
+ final BaseHeadsUpManager hum = createHeadsUpManager();
final NotificationEntry entry = createEntry(/* id = */ 0);
useAccessibilityTimeout(true);
@@ -292,7 +367,7 @@
@Test
public void testShowNotification_stickyForSomeTime_autoDismissesWithAccessibilityTimeout() {
- final HeadsUpManager hum = createHeadsUpManager();
+ final BaseHeadsUpManager hum = createHeadsUpManager();
final NotificationEntry entry = createStickyForSomeTimeEntry(/* id = */ 0);
useAccessibilityTimeout(true);
@@ -306,7 +381,7 @@
@Test
public void testRemoveNotification_beforeMinimumDisplayTime() {
- final HeadsUpManager hum = createHeadsUpManager();
+ final BaseHeadsUpManager hum = createHeadsUpManager();
final NotificationEntry entry = createEntry(/* id = */ 0);
useAccessibilityTimeout(false);
@@ -329,7 +404,7 @@
@Test
public void testRemoveNotification_afterMinimumDisplayTime() {
- final HeadsUpManager hum = createHeadsUpManager();
+ final BaseHeadsUpManager hum = createHeadsUpManager();
final NotificationEntry entry = createEntry(/* id = */ 0);
useAccessibilityTimeout(false);
@@ -366,7 +441,7 @@
@Test
public void testRemoveNotification_releaseImmediately() {
- final HeadsUpManager hum = createHeadsUpManager();
+ final BaseHeadsUpManager hum = createHeadsUpManager();
final NotificationEntry entry = createEntry(/* id = */ 0);
hum.showNotification(entry);
@@ -382,14 +457,15 @@
@Test
public void testIsSticky_rowPinnedAndExpanded_true() {
- final HeadsUpManager hum = createHeadsUpManager();
+ final BaseHeadsUpManager hum = createHeadsUpManager();
final NotificationEntry notifEntry = createEntry(/* id = */ 0);
when(mRow.isPinned()).thenReturn(true);
notifEntry.setRow(mRow);
hum.showNotification(notifEntry);
- final HeadsUpManager.HeadsUpEntry headsUpEntry = hum.getHeadsUpEntry(notifEntry.getKey());
+ final BaseHeadsUpManager.HeadsUpEntry headsUpEntry = hum.getHeadsUpEntry(
+ notifEntry.getKey());
headsUpEntry.setExpanded(true);
assertTrue(hum.isSticky(notifEntry.getKey()));
@@ -397,20 +473,21 @@
@Test
public void testIsSticky_remoteInputActive_true() {
- final HeadsUpManager hum = createHeadsUpManager();
+ final BaseHeadsUpManager hum = createHeadsUpManager();
final NotificationEntry notifEntry = createEntry(/* id = */ 0);
hum.showNotification(notifEntry);
- final HeadsUpManager.HeadsUpEntry headsUpEntry = hum.getHeadsUpEntry(notifEntry.getKey());
- headsUpEntry.remoteInputActive = true;
+ final BaseHeadsUpManager.HeadsUpEntry headsUpEntry = hum.getHeadsUpEntry(
+ notifEntry.getKey());
+ headsUpEntry.mRemoteInputActive = true;
assertTrue(hum.isSticky(notifEntry.getKey()));
}
@Test
public void testIsSticky_hasFullScreenIntent_true() {
- final HeadsUpManager hum = createHeadsUpManager();
+ final BaseHeadsUpManager hum = createHeadsUpManager();
final NotificationEntry notifEntry = createFullScreenIntentEntry(/* id = */ 0);
hum.showNotification(notifEntry);
@@ -421,7 +498,7 @@
@Test
public void testIsSticky_stickyForSomeTime_false() {
- final HeadsUpManager hum = createHeadsUpManager();
+ final BaseHeadsUpManager hum = createHeadsUpManager();
final NotificationEntry entry = createStickyForSomeTimeEntry(/* id = */ 0);
hum.showNotification(entry);
@@ -432,21 +509,22 @@
@Test
public void testIsSticky_false() {
- final HeadsUpManager hum = createHeadsUpManager();
+ final BaseHeadsUpManager hum = createHeadsUpManager();
final NotificationEntry notifEntry = createEntry(/* id = */ 0);
hum.showNotification(notifEntry);
- final HeadsUpManager.HeadsUpEntry headsUpEntry = hum.getHeadsUpEntry(notifEntry.getKey());
+ final BaseHeadsUpManager.HeadsUpEntry headsUpEntry = hum.getHeadsUpEntry(
+ notifEntry.getKey());
headsUpEntry.setExpanded(false);
- headsUpEntry.remoteInputActive = false;
+ headsUpEntry.mRemoteInputActive = false;
assertFalse(hum.isSticky(notifEntry.getKey()));
}
@Test
public void testCompareTo_withNullEntries() {
- final HeadsUpManager hum = createHeadsUpManager();
+ final BaseHeadsUpManager hum = createHeadsUpManager();
final NotificationEntry alertEntry = new NotificationEntryBuilder().setTag("alert").build();
hum.showNotification(alertEntry);
@@ -458,7 +536,7 @@
@Test
public void testCompareTo_withNonAlertEntries() {
- final HeadsUpManager hum = createHeadsUpManager();
+ final BaseHeadsUpManager hum = createHeadsUpManager();
final NotificationEntry nonAlertEntry1 = new NotificationEntryBuilder().setTag(
"nae1").build();
@@ -474,9 +552,9 @@
@Test
public void testAlertEntryCompareTo_ongoingCallLessThanActiveRemoteInput() {
- final HeadsUpManager hum = createHeadsUpManager();
+ final BaseHeadsUpManager hum = createHeadsUpManager();
- final HeadsUpManager.HeadsUpEntry ongoingCall = hum.new HeadsUpEntry();
+ final BaseHeadsUpManager.HeadsUpEntry ongoingCall = hum.new HeadsUpEntry();
ongoingCall.setEntry(new NotificationEntryBuilder()
.setSbn(createSbn(/* id = */ 0,
new Notification.Builder(mContext, "")
@@ -484,9 +562,9 @@
.setOngoing(true)))
.build());
- final HeadsUpManager.HeadsUpEntry activeRemoteInput = hum.new HeadsUpEntry();
+ final BaseHeadsUpManager.HeadsUpEntry activeRemoteInput = hum.new HeadsUpEntry();
activeRemoteInput.setEntry(createEntry(/* id = */ 1));
- activeRemoteInput.remoteInputActive = true;
+ activeRemoteInput.mRemoteInputActive = true;
assertThat(ongoingCall.compareTo(activeRemoteInput)).isLessThan(0);
assertThat(activeRemoteInput.compareTo(ongoingCall)).isGreaterThan(0);
@@ -494,9 +572,9 @@
@Test
public void testAlertEntryCompareTo_incomingCallLessThanActiveRemoteInput() {
- final HeadsUpManager hum = createHeadsUpManager();
+ final BaseHeadsUpManager hum = createHeadsUpManager();
- final HeadsUpManager.HeadsUpEntry incomingCall = hum.new HeadsUpEntry();
+ final BaseHeadsUpManager.HeadsUpEntry incomingCall = hum.new HeadsUpEntry();
final Person person = new Person.Builder().setName("person").build();
final PendingIntent intent = mock(PendingIntent.class);
incomingCall.setEntry(new NotificationEntryBuilder()
@@ -506,9 +584,9 @@
.forIncomingCall(person, intent, intent))))
.build());
- final HeadsUpManager.HeadsUpEntry activeRemoteInput = hum.new HeadsUpEntry();
+ final BaseHeadsUpManager.HeadsUpEntry activeRemoteInput = hum.new HeadsUpEntry();
activeRemoteInput.setEntry(createEntry(/* id = */ 1));
- activeRemoteInput.remoteInputActive = true;
+ activeRemoteInput.mRemoteInputActive = true;
assertThat(incomingCall.compareTo(activeRemoteInput)).isLessThan(0);
assertThat(activeRemoteInput.compareTo(incomingCall)).isGreaterThan(0);
@@ -516,10 +594,10 @@
@Test
public void testPinEntry_logsPeek() {
- final HeadsUpManager hum = createHeadsUpManager();
+ final BaseHeadsUpManager hum = createHeadsUpManager();
// Needs full screen intent in order to be pinned
- final HeadsUpManager.HeadsUpEntry entryToPin = hum.new HeadsUpEntry();
+ final BaseHeadsUpManager.HeadsUpEntry entryToPin = hum.new HeadsUpEntry();
entryToPin.setEntry(createFullScreenIntentEntry(/* id = */ 0));
// Note: the standard way to show a notification would be calling showNotification rather
@@ -530,13 +608,13 @@
hum.onAlertEntryAdded(entryToPin);
assertEquals(1, mUiEventLoggerFake.numLogs());
- assertEquals(HeadsUpManager.NotificationPeekEvent.NOTIFICATION_PEEK.getId(),
+ assertEquals(BaseHeadsUpManager.NotificationPeekEvent.NOTIFICATION_PEEK.getId(),
mUiEventLoggerFake.eventId(0));
}
@Test
public void testSetUserActionMayIndirectlyRemove() {
- final HeadsUpManager hum = createHeadsUpManager();
+ final BaseHeadsUpManager hum = createHeadsUpManager();
final NotificationEntry notifEntry = createEntry(/* id = */ 0);
hum.showNotification(notifEntry);
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/data/repository/DeviceProvisioningRepositoryImplTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/data/repository/DeviceProvisioningRepositoryImplTest.kt
new file mode 100644
index 0000000..12694ae
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/data/repository/DeviceProvisioningRepositoryImplTest.kt
@@ -0,0 +1,108 @@
+/*
+ * Copyright (C) 2023 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.
+ */
+@file:OptIn(ExperimentalCoroutinesApi::class)
+
+package com.android.systemui.statusbar.policy.data.repository
+
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import androidx.test.filters.SmallTest
+import com.android.systemui.SysuiTestCase
+import com.android.systemui.coroutines.collectLastValue
+import com.android.systemui.statusbar.policy.DeviceProvisionedController
+import com.android.systemui.util.mockito.whenever
+import com.android.systemui.util.mockito.withArgCaptor
+import com.google.common.truth.Truth.assertThat
+import kotlinx.coroutines.ExperimentalCoroutinesApi
+import kotlinx.coroutines.test.runCurrent
+import kotlinx.coroutines.test.runTest
+import org.junit.Before
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.mockito.Mock
+import org.mockito.Mockito.verify
+import org.mockito.MockitoAnnotations
+
+@SmallTest
+@RunWith(AndroidJUnit4::class)
+class DeviceProvisioningRepositoryImplTest : SysuiTestCase() {
+
+ @Mock lateinit var deviceProvisionedController: DeviceProvisionedController
+
+ lateinit var underTest: DeviceProvisioningRepositoryImpl
+
+ @Before
+ fun setup() {
+ MockitoAnnotations.initMocks(this)
+ underTest =
+ DeviceProvisioningRepositoryImpl(
+ deviceProvisionedController,
+ )
+ }
+
+ @Test
+ fun isDeviceProvisioned_reflectsCurrentControllerState() = runTest {
+ whenever(deviceProvisionedController.isDeviceProvisioned).thenReturn(true)
+ val deviceProvisioned by collectLastValue(underTest.isDeviceProvisioned)
+ assertThat(deviceProvisioned).isTrue()
+ }
+
+ @Test
+ fun isDeviceProvisioned_updatesWhenControllerStateChanges_toTrue() = runTest {
+ val deviceProvisioned by collectLastValue(underTest.isDeviceProvisioned)
+ runCurrent()
+ whenever(deviceProvisionedController.isDeviceProvisioned).thenReturn(true)
+ withArgCaptor { verify(deviceProvisionedController).addCallback(capture()) }
+ .onDeviceProvisionedChanged()
+ assertThat(deviceProvisioned).isTrue()
+ }
+
+ @Test
+ fun isDeviceProvisioned_updatesWhenControllerStateChanges_toFalse() = runTest {
+ val deviceProvisioned by collectLastValue(underTest.isDeviceProvisioned)
+ runCurrent()
+ whenever(deviceProvisionedController.isDeviceProvisioned).thenReturn(false)
+ withArgCaptor { verify(deviceProvisionedController).addCallback(capture()) }
+ .onDeviceProvisionedChanged()
+ assertThat(deviceProvisioned).isFalse()
+ }
+
+ @Test
+ fun isFrpActive_reflectsCurrentControllerState() = runTest {
+ whenever(deviceProvisionedController.isFrpActive).thenReturn(true)
+ val frpActive by collectLastValue(underTest.isFactoryResetProtectionActive)
+ assertThat(frpActive).isTrue()
+ }
+
+ @Test
+ fun isFrpActive_updatesWhenControllerStateChanges_toTrue() = runTest {
+ val frpActive by collectLastValue(underTest.isFactoryResetProtectionActive)
+ runCurrent()
+ whenever(deviceProvisionedController.isFrpActive).thenReturn(true)
+ withArgCaptor { verify(deviceProvisionedController).addCallback(capture()) }
+ .onFrpActiveChanged()
+ assertThat(frpActive).isTrue()
+ }
+
+ @Test
+ fun isFrpActive_updatesWhenControllerStateChanges_toFalse() = runTest {
+ val frpActive by collectLastValue(underTest.isFactoryResetProtectionActive)
+ runCurrent()
+ whenever(deviceProvisionedController.isFrpActive).thenReturn(false)
+ withArgCaptor { verify(deviceProvisionedController).addCallback(capture()) }
+ .onFrpActiveChanged()
+ assertThat(frpActive).isFalse()
+ }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/user/domain/interactor/UserInteractorTest.kt b/packages/SystemUI/tests/src/com/android/systemui/user/domain/interactor/UserInteractorTest.kt
index af941d0..c56266d 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/user/domain/interactor/UserInteractorTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/user/domain/interactor/UserInteractorTest.kt
@@ -155,6 +155,9 @@
@Test
fun createUserInteractor_nonProcessUser_startsSecondaryService() {
+ val userId = Process.myUserHandle().identifier + 1
+ whenever(manager.aliveUsers).thenReturn(listOf(createUserInfo(userId, "abc")))
+
createUserInteractor(false /* startAsProcessUser */)
verify(spyContext).startServiceAsUser(any(), any())
}
@@ -655,9 +658,10 @@
@Test
fun userSwitchedBroadcast() {
- createUserInteractor()
testScope.runTest {
val userInfos = createUserInfos(count = 2, includeGuest = false)
+ whenever(manager.aliveUsers).thenReturn(userInfos)
+ createUserInteractor()
userRepository.setUserInfos(userInfos)
userRepository.setSelectedUserInfo(userInfos[0])
userRepository.setSettings(UserSwitcherSettingsModel(isUserSwitcherEnabled = true))
@@ -728,6 +732,26 @@
}
@Test
+ fun localeChanged_refreshUsers() {
+ createUserInteractor()
+ testScope.runTest {
+ val userInfos = createUserInfos(count = 2, includeGuest = false)
+ userRepository.setUserInfos(userInfos)
+ userRepository.setSelectedUserInfo(userInfos[0])
+ runCurrent()
+ val refreshUsersCallCount = userRepository.refreshUsersCallCount
+
+ fakeBroadcastDispatcher.sendIntentToMatchingReceiversOnly(
+ spyContext,
+ Intent(Intent.ACTION_LOCALE_CHANGED)
+ )
+ runCurrent()
+
+ assertThat(userRepository.refreshUsersCallCount).isEqualTo(refreshUsersCallCount + 1)
+ }
+ }
+
+ @Test
fun nonSystemUserUnlockedBroadcast_doNotRefreshUsers() {
createUserInteractor()
testScope.runTest {
@@ -985,6 +1009,13 @@
}
}
+ @Test
+ fun initWithNoAliveUsers() {
+ whenever(manager.aliveUsers).thenReturn(listOf())
+ createUserInteractor()
+ verify(spyContext, never()).startServiceAsUser(any(), any())
+ }
+
private fun assertUsers(
models: List<UserModel>?,
count: Int,
diff --git a/packages/SystemUI/tests/src/com/android/systemui/user/ui/viewmodel/UserSwitcherViewModelTest.kt b/packages/SystemUI/tests/src/com/android/systemui/user/ui/viewmodel/UserSwitcherViewModelTest.kt
index 6932f5e..c236b12 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/user/ui/viewmodel/UserSwitcherViewModelTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/user/ui/viewmodel/UserSwitcherViewModelTest.kt
@@ -28,6 +28,7 @@
import com.android.systemui.GuestResumeSessionReceiver
import com.android.systemui.SysuiTestCase
import com.android.systemui.common.shared.model.Text
+import com.android.systemui.coroutines.collectLastValue
import com.android.systemui.flags.FakeFeatureFlags
import com.android.systemui.flags.Flags
import com.android.systemui.keyguard.data.repository.FakeKeyguardRepository
@@ -347,6 +348,24 @@
}
@Test
+ fun isFinishRequested_finishesWhenUserButtonIsClicked() =
+ testScope.runTest {
+ setUsers(count = 2)
+ val isFinishRequested = mutableListOf<Boolean>()
+ val job =
+ launch(testDispatcher) { underTest.isFinishRequested.toList(isFinishRequested) }
+
+ val userViewModels = collectLastValue(underTest.users)
+ assertThat(isFinishRequested.last()).isFalse()
+
+ userViewModels.invoke()?.firstOrNull()?.onClicked?.invoke()
+
+ assertThat(isFinishRequested.last()).isTrue()
+
+ job.cancel()
+ }
+
+ @Test
fun guestSelected_nameIsExitGuest() =
testScope.runTest {
val userInfos =
diff --git a/packages/SystemUI/tests/src/com/android/systemui/wmshell/BubblesTest.java b/packages/SystemUI/tests/src/com/android/systemui/wmshell/BubblesTest.java
index 409ba48..c832702 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/wmshell/BubblesTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/wmshell/BubblesTest.java
@@ -86,20 +86,36 @@
import com.android.internal.colorextraction.ColorExtractor;
import com.android.internal.logging.UiEventLogger;
import com.android.internal.statusbar.IStatusBarService;
+import com.android.keyguard.KeyguardSecurityModel;
import com.android.launcher3.icons.BubbleIconFactory;
import com.android.systemui.SysuiTestCase;
import com.android.systemui.biometrics.AuthController;
+import com.android.systemui.bouncer.data.repository.FakeKeyguardBouncerRepository;
+import com.android.systemui.classifier.FalsingCollectorFake;
import com.android.systemui.colorextraction.SysuiColorExtractor;
import com.android.systemui.common.ui.data.repository.FakeConfigurationRepository;
+import com.android.systemui.deviceentry.data.repository.FakeDeviceEntryRepository;
import com.android.systemui.dump.DumpManager;
import com.android.systemui.flags.FakeFeatureFlags;
+import com.android.systemui.flags.FakeFeatureFlagsClassic;
import com.android.systemui.keyguard.KeyguardViewMediator;
+import com.android.systemui.keyguard.data.repository.FakeCommandQueue;
import com.android.systemui.keyguard.data.repository.FakeKeyguardRepository;
+import com.android.systemui.keyguard.data.repository.FakeKeyguardTransitionRepository;
+import com.android.systemui.keyguard.domain.interactor.FromLockscreenTransitionInteractor;
+import com.android.systemui.keyguard.domain.interactor.FromPrimaryBouncerTransitionInteractor;
+import com.android.systemui.keyguard.domain.interactor.KeyguardInteractor;
+import com.android.systemui.keyguard.domain.interactor.KeyguardTransitionInteractor;
import com.android.systemui.model.SysUiState;
import com.android.systemui.plugins.statusbar.StatusBarStateController;
+import com.android.systemui.power.data.repository.FakePowerRepository;
+import com.android.systemui.power.domain.interactor.PowerInteractor;
import com.android.systemui.scene.FakeWindowRootViewComponent;
import com.android.systemui.scene.SceneTestUtils;
+import com.android.systemui.scene.data.repository.SceneContainerRepository;
+import com.android.systemui.scene.domain.interactor.SceneInteractor;
import com.android.systemui.scene.shared.flag.FakeSceneContainerFlags;
+import com.android.systemui.scene.shared.logger.SceneLogger;
import com.android.systemui.settings.FakeDisplayTracker;
import com.android.systemui.settings.UserTracker;
import com.android.systemui.shade.NotificationShadeWindowControllerImpl;
@@ -139,6 +155,7 @@
import com.android.systemui.statusbar.policy.KeyguardStateController;
import com.android.systemui.statusbar.policy.ResourcesSplitShadeStateController;
import com.android.systemui.statusbar.policy.ZenModeController;
+import com.android.systemui.statusbar.policy.data.repository.FakeDeviceProvisioningRepository;
import com.android.systemui.user.domain.interactor.UserInteractor;
import com.android.wm.shell.ShellTaskOrganizer;
import com.android.wm.shell.WindowManagerShellWrapper;
@@ -329,6 +346,8 @@
private UserHandle mUser0;
private FakeBubbleProperties mBubbleProperties;
+ private FromLockscreenTransitionInteractor mFromLockscreenTransitionInteractor;
+ private FromPrimaryBouncerTransitionInteractor mFromPrimaryBouncerTransitionInteractor;
@Before
public void setUp() throws Exception {
@@ -350,21 +369,94 @@
when(mNotificationShadeWindowView.getViewTreeObserver())
.thenReturn(mock(ViewTreeObserver.class));
- mShadeInteractor = new ShadeInteractor(
+
+ FakeDeviceProvisioningRepository deviceProvisioningRepository =
+ new FakeDeviceProvisioningRepository();
+ deviceProvisioningRepository.setDeviceProvisioned(true);
+ FakeKeyguardRepository keyguardRepository = new FakeKeyguardRepository();
+ FakeFeatureFlagsClassic featureFlags = new FakeFeatureFlagsClassic();
+ FakeShadeRepository shadeRepository = new FakeShadeRepository();
+ FakePowerRepository powerRepository = new FakePowerRepository();
+ FakeConfigurationRepository configurationRepository = new FakeConfigurationRepository();
+
+ PowerInteractor powerInteractor = new PowerInteractor(
+ powerRepository,
+ new FalsingCollectorFake(),
+ mock(ScreenOffAnimationController.class),
+ mStatusBarStateController);
+
+ SceneInteractor sceneInteractor = new SceneInteractor(
mTestScope.getBackgroundScope(),
- new FakeDisableFlagsRepository(),
- new FakeSceneContainerFlags(),
- mUtils::sceneInteractor,
- new FakeKeyguardRepository(),
- new FakeUserSetupRepository(),
- mock(DeviceProvisionedController.class),
- mock(UserInteractor.class),
- new SharedNotificationContainerInteractor(
- new FakeConfigurationRepository(),
- mContext,
- new ResourcesSplitShadeStateController()),
- new FakeShadeRepository()
- );
+ new SceneContainerRepository(
+ mTestScope.getBackgroundScope(),
+ mUtils.fakeSceneContainerConfig(mUtils.fakeSceneKeys())),
+ powerRepository,
+ mock(SceneLogger.class));
+
+ FakeSceneContainerFlags sceneContainerFlags = new FakeSceneContainerFlags();
+ KeyguardInteractor keyguardInteractor = new KeyguardInteractor(
+ keyguardRepository,
+ new FakeCommandQueue(),
+ powerInteractor,
+ featureFlags,
+ sceneContainerFlags,
+ new FakeDeviceEntryRepository(),
+ new FakeKeyguardBouncerRepository(),
+ configurationRepository,
+ shadeRepository,
+ () -> sceneInteractor);
+
+ FakeKeyguardTransitionRepository keyguardTransitionRepository =
+ new FakeKeyguardTransitionRepository();
+
+ KeyguardTransitionInteractor keyguardTransitionInteractor =
+ new KeyguardTransitionInteractor(
+ mTestScope.getBackgroundScope(),
+ keyguardTransitionRepository,
+ () -> keyguardInteractor,
+ () -> mFromLockscreenTransitionInteractor,
+ () -> mFromPrimaryBouncerTransitionInteractor);
+
+ mFromLockscreenTransitionInteractor = new FromLockscreenTransitionInteractor(
+ keyguardTransitionRepository,
+ keyguardTransitionInteractor,
+ mTestScope.getBackgroundScope(),
+ keyguardInteractor,
+ featureFlags,
+ shadeRepository,
+ powerInteractor);
+
+ mFromPrimaryBouncerTransitionInteractor = new FromPrimaryBouncerTransitionInteractor(
+ keyguardTransitionRepository,
+ keyguardTransitionInteractor,
+ mTestScope.getBackgroundScope(),
+ keyguardInteractor,
+ featureFlags,
+ mock(KeyguardSecurityModel.class),
+ powerInteractor);
+
+ ResourcesSplitShadeStateController splitShadeStateController =
+ new ResourcesSplitShadeStateController();
+
+ mShadeInteractor =
+ new ShadeInteractor(
+ mTestScope.getBackgroundScope(),
+ deviceProvisioningRepository,
+ new FakeDisableFlagsRepository(),
+ mDozeParameters,
+ sceneContainerFlags,
+ () -> sceneInteractor,
+ keyguardRepository,
+ keyguardTransitionInteractor,
+ powerInteractor,
+ new FakeUserSetupRepository(),
+ mock(UserInteractor.class),
+ new SharedNotificationContainerInteractor(
+ configurationRepository,
+ mContext,
+ splitShadeStateController),
+ new FakeShadeRepository()
+ );
mNotificationShadeWindowController = new NotificationShadeWindowControllerImpl(
mContext,
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/FakeSystemUiModule.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/FakeSystemUiModule.kt
index 0e59496..813197b1 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/FakeSystemUiModule.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/FakeSystemUiModule.kt
@@ -15,21 +15,27 @@
*/
package com.android.systemui
+import com.android.systemui.classifier.FakeClassifierModule
import com.android.systemui.data.FakeSystemUiDataLayerModule
import com.android.systemui.flags.FakeFeatureFlagsClassicModule
import com.android.systemui.log.FakeUiEventLoggerModule
import com.android.systemui.scene.FakeSceneModule
import com.android.systemui.settings.FakeSettingsModule
+import com.android.systemui.statusbar.policy.FakeConfigurationControllerModule
+import com.android.systemui.statusbar.policy.FakeSplitShadeStateControllerModule
import com.android.systemui.util.concurrency.FakeExecutorModule
import dagger.Module
@Module(
includes =
[
+ FakeClassifierModule::class,
+ FakeConfigurationControllerModule::class,
FakeExecutorModule::class,
FakeFeatureFlagsClassicModule::class,
- FakeSettingsModule::class,
FakeSceneModule::class,
+ FakeSettingsModule::class,
+ FakeSplitShadeStateControllerModule::class,
FakeSystemUiDataLayerModule::class,
FakeUiEventLoggerModule::class,
]
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/RoboPilotTest.java b/packages/SystemUI/tests/utils/src/com/android/systemui/RoboPilotTest.java
deleted file mode 100644
index 3fff136..0000000
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/RoboPilotTest.java
+++ /dev/null
@@ -1,31 +0,0 @@
-/*
- * Copyright (C) 2023 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;
-
-import java.lang.annotation.ElementType;
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-import java.lang.annotation.Target;
-
-/**
- * Mark as tests for Robolectric pilot projects. The filter can better help grouping test results
- * that runs on CI
- */
-@Target({ElementType.METHOD, ElementType.TYPE})
-@Retention(RetentionPolicy.RUNTIME)
-public @interface RoboPilotTest {
-}
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/classifier/FakeClassifierModule.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/classifier/FakeClassifierModule.kt
new file mode 100644
index 0000000..23bad39
--- /dev/null
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/classifier/FakeClassifierModule.kt
@@ -0,0 +1,21 @@
+/*
+ * Copyright (C) 2023 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.classifier
+
+import dagger.Module
+
+@Module(includes = [FakeFalsingCollectorModule::class, FakeFalsingManagerModule::class])
+object FakeClassifierModule
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/classifier/FakeFalsingCollectorModule.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/classifier/FakeFalsingCollectorModule.kt
new file mode 100644
index 0000000..92acc94
--- /dev/null
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/classifier/FakeFalsingCollectorModule.kt
@@ -0,0 +1,25 @@
+/*
+ * Copyright (C) 2023 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.classifier
+
+import dagger.Binds
+import dagger.Module
+
+@Module
+interface FakeFalsingCollectorModule {
+ @Binds @FalsingCollectorActual fun bindFake(fake: FalsingCollectorFake): FalsingCollector
+ @Binds fun bindFakeLegacy(fake: FalsingCollectorFake): FalsingCollector
+}
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/classifier/FakeFalsingManagerModule.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/classifier/FakeFalsingManagerModule.kt
new file mode 100644
index 0000000..554fc75
--- /dev/null
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/classifier/FakeFalsingManagerModule.kt
@@ -0,0 +1,25 @@
+/*
+ * Copyright (C) 2023 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.classifier
+
+import com.android.systemui.plugins.FalsingManager
+import dagger.Binds
+import dagger.Module
+
+@Module
+interface FakeFalsingManagerModule {
+ @Binds fun bindFake(fake: FalsingManagerFake): FalsingManager
+}
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/classifier/FalsingManagerFake.java b/packages/SystemUI/tests/utils/src/com/android/systemui/classifier/FalsingManagerFake.java
index d47e88f..5038285 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/classifier/FalsingManagerFake.java
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/classifier/FalsingManagerFake.java
@@ -21,15 +21,19 @@
import android.net.Uri;
import com.android.internal.annotations.VisibleForTesting;
+import com.android.systemui.dagger.SysUISingleton;
import com.android.systemui.plugins.FalsingManager;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.List;
+import javax.inject.Inject;
+
/**
* Simple Fake for testing where {@link FalsingManager} is required.
*/
+@SysUISingleton
public class FalsingManagerFake implements FalsingManager {
private boolean mIsFalseTouch;
private boolean mIsSimpleTap;
@@ -46,6 +50,10 @@
private final List<FalsingBeliefListener> mFalsingBeliefListeners = new ArrayList<>();
private final List<FalsingTapListener> mTapListeners = new ArrayList<>();
+ @Inject
+ public FalsingManagerFake() {
+ }
+
@Override
public void onSuccessfulUnlock() {
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/data/FakeSystemUiDataLayerModule.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/data/FakeSystemUiDataLayerModule.kt
index f866932..29fb52a 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/data/FakeSystemUiDataLayerModule.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/data/FakeSystemUiDataLayerModule.kt
@@ -17,6 +17,7 @@
import com.android.systemui.bouncer.data.repository.FakeBouncerDataLayerModule
import com.android.systemui.common.ui.data.FakeCommonDataLayerModule
+import com.android.systemui.deviceentry.data.FakeDeviceEntryDataLayerModule
import com.android.systemui.keyguard.data.FakeKeyguardDataLayerModule
import com.android.systemui.power.data.FakePowerDataLayerModule
import com.android.systemui.shade.data.repository.FakeShadeDataLayerModule
@@ -28,8 +29,9 @@
@Module(
includes =
[
- FakeCommonDataLayerModule::class,
FakeBouncerDataLayerModule::class,
+ FakeCommonDataLayerModule::class,
+ FakeDeviceEntryDataLayerModule::class,
FakeKeyguardDataLayerModule::class,
FakePowerDataLayerModule::class,
FakeShadeDataLayerModule::class,
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/deviceentry/data/FakeDeviceEntryDataLayerModule.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/deviceentry/data/FakeDeviceEntryDataLayerModule.kt
new file mode 100644
index 0000000..ef02bdd
--- /dev/null
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/deviceentry/data/FakeDeviceEntryDataLayerModule.kt
@@ -0,0 +1,21 @@
+/*
+ * Copyright (C) 2023 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.deviceentry.data
+
+import com.android.systemui.deviceentry.data.repository.FakeDeviceEntryRepositoryModule
+import dagger.Module
+
+@Module(includes = [FakeDeviceEntryRepositoryModule::class]) object FakeDeviceEntryDataLayerModule
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/deviceentry/data/repository/FakeDeviceEntryRepository.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/deviceentry/data/repository/FakeDeviceEntryRepository.kt
index 5e60a09..26d95c0 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/deviceentry/data/repository/FakeDeviceEntryRepository.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/deviceentry/data/repository/FakeDeviceEntryRepository.kt
@@ -1,11 +1,16 @@
package com.android.systemui.deviceentry.data.repository
+import com.android.systemui.dagger.SysUISingleton
+import dagger.Binds
+import dagger.Module
+import javax.inject.Inject
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.asStateFlow
/** Fake implementation of [DeviceEntryRepository] */
-class FakeDeviceEntryRepository : DeviceEntryRepository {
+@SysUISingleton
+class FakeDeviceEntryRepository @Inject constructor() : DeviceEntryRepository {
private var isInsecureLockscreenEnabled = true
private var isBypassEnabled = false
@@ -33,3 +38,8 @@
this.isBypassEnabled = isBypassEnabled
}
}
+
+@Module
+interface FakeDeviceEntryRepositoryModule {
+ @Binds fun bindFake(fake: FakeDeviceEntryRepository): DeviceEntryRepository
+}
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/data/FakeStatusBarDataLayerModule.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/data/FakeStatusBarDataLayerModule.kt
index 1bec82b..822edfc7 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/data/FakeStatusBarDataLayerModule.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/data/FakeStatusBarDataLayerModule.kt
@@ -17,6 +17,7 @@
import com.android.systemui.statusbar.disableflags.data.FakeStatusBarDisableFlagsDataLayerModule
import com.android.systemui.statusbar.pipeline.data.FakeStatusBarPipelineDataLayerModule
+import com.android.systemui.statusbar.policy.data.FakeStatusBarPolicyDataLayerModule
import dagger.Module
@Module(
@@ -24,6 +25,7 @@
[
FakeStatusBarDisableFlagsDataLayerModule::class,
FakeStatusBarPipelineDataLayerModule::class,
+ FakeStatusBarPolicyDataLayerModule::class,
]
)
object FakeStatusBarDataLayerModule
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/policy/FakeConfigurationController.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/policy/FakeConfigurationController.kt
index 16a3268..23477d8 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/policy/FakeConfigurationController.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/policy/FakeConfigurationController.kt
@@ -1,9 +1,14 @@
package com.android.systemui.statusbar.policy
import android.content.res.Configuration
+import com.android.systemui.dagger.SysUISingleton
+import dagger.Binds
+import dagger.Module
+import javax.inject.Inject
/** Fake implementation of [ConfigurationController] for tests. */
-class FakeConfigurationController : ConfigurationController {
+@SysUISingleton
+class FakeConfigurationController @Inject constructor() : ConfigurationController {
private var listeners = mutableListOf<ConfigurationController.ConfigurationListener>()
@@ -33,3 +38,8 @@
override fun isLayoutRtl(): Boolean = false
}
+
+@Module
+interface FakeConfigurationControllerModule {
+ @Binds fun bindFake(fake: FakeConfigurationController): ConfigurationController
+}
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/policy/FakeSplitShadeStateControllerModule.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/policy/FakeSplitShadeStateControllerModule.kt
new file mode 100644
index 0000000..14bab84
--- /dev/null
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/policy/FakeSplitShadeStateControllerModule.kt
@@ -0,0 +1,24 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the
+ * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the specific language governing
+ * permissions and limitations under the License.
+ *
+ */
+
+package com.android.systemui.statusbar.policy
+
+import dagger.Binds
+import dagger.Module
+
+@Module
+interface FakeSplitShadeStateControllerModule {
+ @Binds fun bindFake(fake: ResourcesSplitShadeStateController): SplitShadeStateController
+}
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/policy/data/FakeStatusBarPolicyDataLayerModule.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/policy/data/FakeStatusBarPolicyDataLayerModule.kt
new file mode 100644
index 0000000..5aece1b
--- /dev/null
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/policy/data/FakeStatusBarPolicyDataLayerModule.kt
@@ -0,0 +1,22 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.systemui.statusbar.policy.data
+
+import com.android.systemui.statusbar.policy.data.repository.FakeDeviceProvisioningRepositoryModule
+import dagger.Module
+
+@Module(includes = [FakeDeviceProvisioningRepositoryModule::class])
+object FakeStatusBarPolicyDataLayerModule
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/policy/data/repository/FakeDeviceProvisioningRepository.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/policy/data/repository/FakeDeviceProvisioningRepository.kt
new file mode 100644
index 0000000..3002299
--- /dev/null
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/policy/data/repository/FakeDeviceProvisioningRepository.kt
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.systemui.statusbar.policy.data.repository
+
+import com.android.systemui.dagger.SysUISingleton
+import dagger.Binds
+import dagger.Module
+import javax.inject.Inject
+import kotlinx.coroutines.flow.Flow
+import kotlinx.coroutines.flow.MutableStateFlow
+
+@SysUISingleton
+class FakeDeviceProvisioningRepository @Inject constructor() : DeviceProvisioningRepository {
+ private val _isDeviceProvisioned = MutableStateFlow(false)
+ override val isDeviceProvisioned: Flow<Boolean> = _isDeviceProvisioned
+ private val _isFactoryResetProtectionActive = MutableStateFlow(false)
+ override val isFactoryResetProtectionActive: Flow<Boolean> = _isFactoryResetProtectionActive
+ fun setDeviceProvisioned(isProvisioned: Boolean) {
+ _isDeviceProvisioned.value = isProvisioned
+ }
+ fun setFactoryResetProtectionActive(isActive: Boolean) {
+ _isFactoryResetProtectionActive.value = isActive
+ }
+}
+
+@Module
+interface FakeDeviceProvisioningRepositoryModule {
+ @Binds fun bindFake(fake: FakeDeviceProvisioningRepository): DeviceProvisioningRepository
+}
diff --git a/packages/WallpaperBackup/Android.bp b/packages/WallpaperBackup/Android.bp
index 155dc1a..18f78314 100644
--- a/packages/WallpaperBackup/Android.bp
+++ b/packages/WallpaperBackup/Android.bp
@@ -49,7 +49,7 @@
"androidx.test.core",
"androidx.test.rules",
"mockito-target-minus-junit4",
- "truth-prebuilt",
+ "truth",
],
resource_dirs: ["test/res"],
certificate: "platform",
diff --git a/packages/overlays/tests/Android.bp b/packages/overlays/tests/Android.bp
index b781602..0244c0f 100644
--- a/packages/overlays/tests/Android.bp
+++ b/packages/overlays/tests/Android.bp
@@ -34,7 +34,7 @@
"androidx.test.rules",
"androidx.test.espresso.core",
"mockito-target-minus-junit4",
- "truth-prebuilt",
+ "truth",
],
dxflags: ["--multi-dex"],
}
diff --git a/services/appwidget/java/com/android/server/appwidget/AppWidgetServiceImpl.java b/services/appwidget/java/com/android/server/appwidget/AppWidgetServiceImpl.java
index 7e09b5e..258820a 100644
--- a/services/appwidget/java/com/android/server/appwidget/AppWidgetServiceImpl.java
+++ b/services/appwidget/java/com/android/server/appwidget/AppWidgetServiceImpl.java
@@ -24,6 +24,7 @@
import static com.android.server.pm.PackageManagerService.PLATFORM_PACKAGE_NAME;
+import android.Manifest;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.RequiresPermission;
@@ -1660,8 +1661,21 @@
synchronized (mLock) {
ensureGroupStateLoadedLocked(userId);
+ final String pkg = componentName.getPackageName();
+ final ProviderId id;
+ if (!mPackageManagerInternal.isSameApp(pkg, callingUid, userId)) {
+ // If the calling process is requesting to pin appwidgets from another process,
+ // check if the calling process has the necessary permission.
+ if (!injectHasAccessWidgetsPermission(Binder.getCallingPid(), callingUid)) {
+ return false;
+ }
+ id = new ProviderId(mPackageManagerInternal.getPackageUid(
+ pkg, 0 /* flags */, userId), componentName);
+ } else {
+ id = new ProviderId(callingUid, componentName);
+ }
// Look for the widget associated with the caller.
- Provider provider = lookupProviderLocked(new ProviderId(callingUid, componentName));
+ Provider provider = lookupProviderLocked(id);
if (provider == null || provider.zombie) {
return false;
}
@@ -1675,6 +1689,14 @@
.requestPinAppWidget(callingPackage, info, extras, resultSender, userId);
}
+ /**
+ * Returns true if the caller has the proper permission to access app widgets.
+ */
+ private boolean injectHasAccessWidgetsPermission(int callingPid, int callingUid) {
+ return mContext.checkPermission(Manifest.permission.CLEAR_APP_USER_DATA,
+ callingPid, callingUid) == PackageManager.PERMISSION_GRANTED;
+ }
+
@Override
public ParceledListSlice<AppWidgetProviderInfo> getInstalledProvidersForProfile(int categoryFilter,
int profileId, String packageName) {
@@ -4131,7 +4153,7 @@
return false;
}
- @GuardedBy("mLock")
+ @GuardedBy("AppWidgetServiceImpl.mLock")
public AppWidgetProviderInfo getInfoLocked(Context context) {
if (!mInfoParsed) {
// parse
@@ -4159,18 +4181,18 @@
* be completely parsed and only contain placeHolder information like
* {@link AppWidgetProviderInfo#providerInfo}
*/
- @GuardedBy("mLock")
+ @GuardedBy("AppWidgetServiceImpl.mLock")
public AppWidgetProviderInfo getPartialInfoLocked() {
return info;
}
- @GuardedBy("mLock")
+ @GuardedBy("AppWidgetServiceImpl.mLock")
public void setPartialInfoLocked(AppWidgetProviderInfo info) {
this.info = info;
mInfoParsed = false;
}
- @GuardedBy("mLock")
+ @GuardedBy("AppWidgetServiceImpl.mLock")
public void setInfoLocked(AppWidgetProviderInfo info) {
this.info = info;
mInfoParsed = true;
diff --git a/services/autofill/Android.bp b/services/autofill/Android.bp
index d43a219..eb23f2f 100644
--- a/services/autofill/Android.bp
+++ b/services/autofill/Android.bp
@@ -19,19 +19,4 @@
defaults: ["platform_service_defaults"],
srcs: [":services.autofill-sources"],
libs: ["services.core"],
- static_libs: ["autofill_flags_java_lib"],
-}
-
-aconfig_declarations {
- name: "autofill_flags",
- package: "android.service.autofill",
- srcs: [
- "bugfixes.aconfig",
- "features.aconfig",
- ],
-}
-
-java_aconfig_library {
- name: "autofill_flags_java_lib",
- aconfig_declarations: "autofill_flags",
}
diff --git a/services/autofill/bugfixes.aconfig b/services/autofill/bugfixes.aconfig
index ef23754..123b65c 100644
--- a/services/autofill/bugfixes.aconfig
+++ b/services/autofill/bugfixes.aconfig
@@ -5,4 +5,11 @@
namespace: "autofill"
description: "Test flag "
bug: "297380045"
-}
\ No newline at end of file
+}
+
+flag {
+ name: "relayout"
+ namespace: "autofill"
+ description: "Mitigation for relayout issue"
+ bug: "294330426"
+}
diff --git a/services/core/java/com/android/server/PinnerService.java b/services/core/java/com/android/server/PinnerService.java
index 9bab261..93dca2f 100644
--- a/services/core/java/com/android/server/PinnerService.java
+++ b/services/core/java/com/android/server/PinnerService.java
@@ -359,8 +359,10 @@
@Override
public void onChange(boolean selfChange, Uri uri) {
if (userSetupCompleteUri.equals(uri)) {
- sendPinAppMessage(KEY_HOME, ActivityManager.getCurrentUser(),
- true /* force */);
+ if (mConfiguredToPinHome) {
+ sendPinAppMessage(KEY_HOME, ActivityManager.getCurrentUser(),
+ true /* force */);
+ }
}
}
}, UserHandle.USER_ALL);
diff --git a/services/core/java/com/android/server/StorageManagerService.java b/services/core/java/com/android/server/StorageManagerService.java
index 8cc2665..962f38f 100644
--- a/services/core/java/com/android/server/StorageManagerService.java
+++ b/services/core/java/com/android/server/StorageManagerService.java
@@ -214,6 +214,9 @@
// external storage service.
public static final int FAILED_MOUNT_RESET_TIMEOUT_SECONDS = 10;
+ /** Extended timeout for the system server watchdog. */
+ private static final int SLOW_OPERATION_WATCHDOG_TIMEOUT_MS = 60 * 1000;
+
@GuardedBy("mLock")
private final Set<Integer> mFuseMountedUser = new ArraySet<>();
@@ -1230,6 +1233,8 @@
private void onUserStopped(int userId) {
Slog.d(TAG, "onUserStopped " + userId);
+ Watchdog.getInstance().setOneOffTimeoutForMonitors(
+ SLOW_OPERATION_WATCHDOG_TIMEOUT_MS, "#onUserStopped might be slow");
try {
mVold.onUserStopped(userId);
mStoraged.onUserStopped(userId);
@@ -1312,6 +1317,8 @@
unlockedUsers.add(userId);
}
}
+ Watchdog.getInstance().setOneOffTimeoutForMonitors(
+ SLOW_OPERATION_WATCHDOG_TIMEOUT_MS, "#onUserStopped might be slow");
for (Integer userId : unlockedUsers) {
try {
mVold.onUserStopped(userId);
@@ -3600,6 +3607,8 @@
@Override
public ParcelFileDescriptor open() throws AppFuseMountException {
+ Watchdog.getInstance().setOneOffTimeoutForMonitors(
+ SLOW_OPERATION_WATCHDOG_TIMEOUT_MS, "#open might be slow");
try {
final FileDescriptor fd = mVold.mountAppFuse(uid, mountId);
mMounted = true;
@@ -3612,6 +3621,8 @@
@Override
public ParcelFileDescriptor openFile(int mountId, int fileId, int flags)
throws AppFuseMountException {
+ Watchdog.getInstance().setOneOffTimeoutForMonitors(
+ SLOW_OPERATION_WATCHDOG_TIMEOUT_MS, "#openFile might be slow");
try {
return new ParcelFileDescriptor(
mVold.openAppFuseFile(uid, mountId, fileId, flags));
@@ -3622,6 +3633,8 @@
@Override
public void close() throws Exception {
+ Watchdog.getInstance().setOneOffTimeoutForMonitors(
+ SLOW_OPERATION_WATCHDOG_TIMEOUT_MS, "#close might be slow");
if (mMounted) {
mVold.unmountAppFuse(uid, mountId);
mMounted = false;
diff --git a/services/core/java/com/android/server/Watchdog.java b/services/core/java/com/android/server/Watchdog.java
index b05b397..55aa716 100644
--- a/services/core/java/com/android/server/Watchdog.java
+++ b/services/core/java/com/android/server/Watchdog.java
@@ -644,6 +644,16 @@
}
/**
+ * Sets a one-off timeout for the next run of the watchdog for the monitor thread.
+ *
+ * <p>Simiar to {@link setOneOffTimeoutForCurrentThread} but used for monitors added through
+ * {@link #addMonitor}
+ */
+ public void setOneOffTimeoutForMonitors(int oneOffTimeoutMillis, String reason) {
+ mMonitorChecker.setOneOffTimeoutLocked(oneOffTimeoutMillis, reason);
+ }
+
+ /**
* Pauses Watchdog action for the currently running thread. Useful before executing long running
* operations that could falsely trigger the watchdog. Each call to this will require a matching
* call to {@link #resumeWatchingCurrentThread}.
diff --git a/services/core/java/com/android/server/am/AnrTimer.java b/services/core/java/com/android/server/am/AnrTimer.java
index 378a386..9ba49ce 100644
--- a/services/core/java/com/android/server/am/AnrTimer.java
+++ b/services/core/java/com/android/server/am/AnrTimer.java
@@ -108,6 +108,14 @@
private static final boolean ENABLE_TRACING = false;
/**
+ * Return true if the feature is enabled. By default, the value is take from the Flags class
+ * but it can be changed for local testing.
+ */
+ private static boolean anrTimerServiceEnabled() {
+ return Flags.anrTimerServiceEnabled();
+ }
+
+ /**
* The status of an ANR timer. TIMER_INVALID status is returned when an error is detected.
*/
private static final int TIMER_INVALID = 0;
@@ -327,18 +335,33 @@
*/
@VisibleForTesting
static class Injector {
- /**
- * Return a handler for the given Callback.
- */
- Handler getHandler(@NonNull Handler.Callback callback) {
- return null;
- };
+ private final Handler mReferenceHandler;
+
+ Injector(@NonNull Handler handler) {
+ mReferenceHandler = handler;
+ }
/**
- * Return a CpuTracker.
+ * Return a handler for the given Callback, based on the reference handler. The handler
+ * might be mocked, in which case it does not have a valid Looper. In this case, use the
+ * main Looper.
*/
+ @NonNull
+ Handler getHandler(@NonNull Handler.Callback callback) {
+ Looper looper = mReferenceHandler.getLooper();
+ if (looper == null) looper = Looper.getMainLooper();
+ return new Handler(looper, callback);
+ };
+
+ /** Return a CpuTracker. */
+ @NonNull
CpuTracker getTracker() {
- return null;
+ return new CpuTracker();
+ }
+
+ /** Return true if the feature is enabled. */
+ boolean getFeatureEnabled() {
+ return anrTimerServiceEnabled();
}
}
@@ -375,12 +398,6 @@
/** The interface to fetch process statistics that might extend an ANR timeout. */
private final CpuTracker mCpu;
- /** Create a HandlerTimerService based on the input handler. */
- HandlerTimerService(@NonNull Handler handler) {
- mHandler = new Handler(handler.getLooper(), this::expires);
- mCpu = new CpuTracker();
- }
-
/** Create a HandlerTimerService that directly uses the supplied handler and tracker. */
@VisibleForTesting
HandlerTimerService(@NonNull Injector injector) {
@@ -491,38 +508,56 @@
private final boolean mLenientCancel = true;
/**
+ * The top-level switch for the feature enabled or disabled.
+ */
+ private final FeatureSwitch mFeature;
+
+ /**
* The common constructor. A null injector results in a normal, production timer.
*/
@VisibleForTesting
AnrTimer(@NonNull Handler handler, int what, @NonNull String label, boolean extend,
- @Nullable Injector injector) {
+ @NonNull Injector injector) {
mHandler = handler;
mWhat = what;
mLabel = label;
mExtend = extend;
- if (injector == null) {
- mTimerService = new HandlerTimerService(handler);
+ boolean enabled = injector.getFeatureEnabled();
+ if (!enabled) {
+ mFeature = new FeatureDisabled();
+ mTimerService = null;
} else {
+ mFeature = new FeatureEnabled();
mTimerService = new HandlerTimerService(injector);
+
+ synchronized (sAnrTimerList) {
+ sAnrTimerList.add(new WeakReference(this));
+ }
}
- synchronized (sAnrTimerList) {
- sAnrTimerList.add(new WeakReference(this));
- }
- Log.i(TAG, formatSimple("created %s label: \"%s\"", mTimerService.toString(), label));
+ Log.i(TAG, formatSimple("created %s label: \"%s\"", mTimerService, label));
}
/**
* Create one timer instance for production. The client can ask for extensible timeouts.
*/
AnrTimer(@NonNull Handler handler, int what, @NonNull String label, boolean extend) {
- this(handler, what, label, extend, null);
+ this(handler, what, label, extend, new Injector(handler));
}
/**
* Create one timer instance for production. There are no extensible timeouts.
*/
AnrTimer(@NonNull Handler handler, int what, @NonNull String label) {
- this(handler, what, label, false, null);
+ this(handler, what, label, false);
+ }
+
+ /**
+ * Return true if the service is enabled on this instance. Clients should use this method to
+ * decide if the feature is enabled, and not read the flags directly. This method should be
+ * deleted if and when the feature is enabled permanently.
+ */
+ boolean serviceEnabled() {
+ return mFeature.enabled();
}
/**
@@ -613,93 +648,186 @@
Log.i(TAG, msg + " " + timer + " " + Objects.toString(timer.arg));
}
- /**
- * Start a timer.
+ /**
+ * The FeatureSwitch class provides a quick switch between feature-enabled behavior and
+ * feature-disabled behavior.
*/
- boolean start(@NonNull V arg, int pid, int uid, long timeoutMs) {
- final Timer timer = Timer.obtain(pid, uid, arg, timeoutMs, this);
- synchronized (mLock) {
- Timer old = mTimerMap.get(arg);
- if (old != null) {
- // There is an existing timer. This is a protocol error in the client. Record
- // the error and then clean up by canceling running timers and discarding expired
- // timers.
- restartedLocked(old.status, arg);
- if (old.status == TIMER_EXPIRED) {
- discard(arg);
+ private abstract class FeatureSwitch {
+ abstract boolean start(@NonNull V arg, int pid, int uid, long timeoutMs);
+ abstract boolean cancel(@NonNull V arg);
+ abstract boolean accept(@NonNull V arg);
+ abstract boolean discard(@NonNull V arg);
+ abstract boolean enabled();
+ }
+
+ /**
+ * The FeatureDisabled class bypasses almost all AnrTimer logic. It is used when the AnrTimer
+ * service is disabled via Flags.anrTimerServiceEnabled.
+ */
+ private class FeatureDisabled extends FeatureSwitch {
+ /** Start a timer by sending a message to the client's handler. */
+ boolean start(@NonNull V arg, int pid, int uid, long timeoutMs) {
+ final Message msg = mHandler.obtainMessage(mWhat, arg);
+ mHandler.sendMessageDelayed(msg, timeoutMs);
+ return true;
+ }
+
+ /** Cancel a timer by removing the message from the client's handler. */
+ boolean cancel(@NonNull V arg) {
+ mHandler.removeMessages(mWhat, arg);
+ return true;
+ }
+
+ /** accept() is a no-op when the feature is disabled. */
+ boolean accept(@NonNull V arg) {
+ return true;
+ }
+
+ /** discard() is a no-op when the feature is disabled. */
+ boolean discard(@NonNull V arg) {
+ return true;
+ }
+
+ /** The feature is not enabled. */
+ boolean enabled() {
+ return false;
+ }
+ }
+
+ /**
+ * The FeatureEnabled class enables the AnrTimer logic. It is used when the AnrTimer service
+ * is enabled via Flags.anrTimerServiceEnabled.
+ */
+ private class FeatureEnabled extends FeatureSwitch {
+
+ /**
+ * Start a timer.
+ */
+ boolean start(@NonNull V arg, int pid, int uid, long timeoutMs) {
+ final Timer timer = Timer.obtain(pid, uid, arg, timeoutMs, AnrTimer.this);
+ synchronized (mLock) {
+ Timer old = mTimerMap.get(arg);
+ if (old != null) {
+ // There is an existing timer. This is a protocol error in the client.
+ // Record the error and then clean up by canceling running timers and
+ // discarding expired timers.
+ restartedLocked(old.status, arg);
+ if (old.status == TIMER_EXPIRED) {
+ discard(arg);
+ } else {
+ cancel(arg);
+ }
+ }
+ if (mTimerService.start(timer)) {
+ timer.status = TIMER_RUNNING;
+ mTimerMap.put(arg, timer);
+ mTotalStarted++;
+ mMaxStarted = Math.max(mMaxStarted, mTimerMap.size());
+ if (DEBUG) report(timer, "start");
+ return true;
} else {
- cancel(arg);
+ Log.e(TAG, "AnrTimer.start failed");
+ return false;
}
}
- if (mTimerService.start(timer)) {
- timer.status = TIMER_RUNNING;
- mTimerMap.put(arg, timer);
- mTotalStarted++;
- mMaxStarted = Math.max(mMaxStarted, mTimerMap.size());
- if (DEBUG) report(timer, "start");
+ }
+
+ /**
+ * Cancel a timer. Return false if the timer was not found.
+ */
+ boolean cancel(@NonNull V arg) {
+ synchronized (mLock) {
+ Timer timer = removeLocked(arg);
+ if (timer == null) {
+ if (!mLenientCancel) notFoundLocked("cancel", arg);
+ return false;
+ }
+ mTimerService.cancel(timer);
+ // There may be an expiration message in flight. Cancel it.
+ mHandler.removeMessages(mWhat, arg);
+ if (DEBUG) report(timer, "cancel");
+ timer.release();
return true;
- } else {
- Log.e(TAG, "AnrTimer.start failed");
- return false;
}
}
+
+ /**
+ * Accept a timer in the framework-level handler. The timeout has been accepted and the
+ * timeout handler is executing. Return false if the timer was not found.
+ */
+ boolean accept(@NonNull V arg) {
+ synchronized (mLock) {
+ Timer timer = removeLocked(arg);
+ if (timer == null) {
+ notFoundLocked("accept", arg);
+ return false;
+ }
+ mTimerService.accept(timer);
+ traceEnd(timer);
+ if (DEBUG) report(timer, "accept");
+ timer.release();
+ return true;
+ }
+ }
+
+ /**
+ * Discard a timer in the framework-level handler. For whatever reason, the timer is no
+ * longer interesting. No statistics are collected. Return false if the time was not
+ * found.
+ */
+ boolean discard(@NonNull V arg) {
+ synchronized (mLock) {
+ Timer timer = removeLocked(arg);
+ if (timer == null) {
+ notFoundLocked("discard", arg);
+ return false;
+ }
+ mTimerService.discard(timer);
+ traceEnd(timer);
+ if (DEBUG) report(timer, "discard");
+ timer.release();
+ return true;
+ }
+ }
+
+ /** The feature is enabled. */
+ boolean enabled() {
+ return true;
+ }
}
/**
- * Cancel a timer. Return false if the timer was not found.
+ * Start a timer associated with arg. If a timer already exists with the same arg, then that
+ * timer is canceled and a new timer is created. This returns false if the timer cannot be
+ * created.
+ */
+ boolean start(@NonNull V arg, int pid, int uid, long timeoutMs) {
+ return mFeature.start(arg, pid, uid, timeoutMs);
+ }
+
+ /**
+ * Cancel a running timer and remove it from any list. This returns true if the timer was
+ * found and false otherwise. It is not an error to cancel a non-existent timer. It is also
+ * not an error to cancel an expired timer.
*/
boolean cancel(@NonNull V arg) {
- synchronized (mLock) {
- Timer timer = removeLocked(arg);
- if (timer == null) {
- if (!mLenientCancel) notFoundLocked("cancel", arg);
- return false;
- }
- mTimerService.cancel(timer);
- // There may be an expiration message in flight. Cancel it.
- mHandler.removeMessages(mWhat, arg);
- if (DEBUG) report(timer, "cancel");
- timer.release();
- return true;
- }
+ return mFeature.cancel(arg);
}
/**
- * Accept a timer in the framework-level handler. The timeout has been accepted and the
- * timeout handler is executing. Return false if the timer was not found.
+ * Accept an expired timer. This returns false if the timer was not found or if the timer was
+ * not expired.
*/
boolean accept(@NonNull V arg) {
- synchronized (mLock) {
- Timer timer = removeLocked(arg);
- if (timer == null) {
- notFoundLocked("accept", arg);
- return false;
- }
- mTimerService.accept(timer);
- traceEnd(timer);
- if (DEBUG) report(timer, "accept");
- timer.release();
- return true;
- }
+ return mFeature.accept(arg);
}
/**
- * Discard a timer in the framework-level handler. For whatever reason, the timer is no
- * longer interesting. No statistics are collected. Return false if the time was not found.
+ * Discard an expired timer. This returns false if the timer was not found or if the timer was
+ * not expired.
*/
boolean discard(@NonNull V arg) {
- synchronized (mLock) {
- Timer timer = removeLocked(arg);
- if (timer == null) {
- notFoundLocked("discard", arg);
- return false;
- }
- mTimerService.discard(timer);
- traceEnd(timer);
- if (DEBUG) report(timer, "discard");
- timer.release();
- return true;
- }
+ return mFeature.discard(arg);
}
/**
diff --git a/services/core/java/com/android/server/am/AppBatteryTracker.java b/services/core/java/com/android/server/am/AppBatteryTracker.java
index 907069d..147f8d1 100644
--- a/services/core/java/com/android/server/am/AppBatteryTracker.java
+++ b/services/core/java/com/android/server/am/AppBatteryTracker.java
@@ -580,7 +580,11 @@
batteryStatsInternal);
curDuration += curStart - lastUidBatteryUsageStartTs;
try {
- statsCommit.close();
+ if (statsCommit != null) {
+ statsCommit.close();
+ } else {
+ Slog.w(TAG, "Stat was null");
+ }
} catch (IOException e) {
Slog.w(TAG, "Failed to close a stat");
}
@@ -660,7 +664,11 @@
}
}
try {
- stats.close();
+ if (stats != null) {
+ stats.close();
+ } else {
+ Slog.w(TAG, "Stat was null");
+ }
} catch (IOException e) {
Slog.w(TAG, "Failed to close a stat");
}
@@ -684,7 +692,11 @@
final BatteryUsageStats stats = statsList.get(0);
for (int i = 1; i < statsList.size(); i++) {
try {
- statsList.get(i).close();
+ if (statsList.get(i) != null) {
+ statsList.get(i).close();
+ } else {
+ Slog.w(TAG, "Stat was null");
+ }
} catch (IOException e) {
Slog.w(TAG, "Failed to close a stat in BatteryUsageStats List");
}
diff --git a/services/core/java/com/android/server/am/BroadcastProcessQueue.java b/services/core/java/com/android/server/am/BroadcastProcessQueue.java
index 5d31d15..e07c2bc 100644
--- a/services/core/java/com/android/server/am/BroadcastProcessQueue.java
+++ b/services/core/java/com/android/server/am/BroadcastProcessQueue.java
@@ -106,6 +106,14 @@
private boolean mTimeoutScheduled;
/**
+ * Snapshotted value of {@link ProcessRecord#getCpuDelayTime()}, typically
+ * used when deciding if we should extend the soft ANR timeout.
+ *
+ * Required when Flags.anrTimerServiceEnabled is false.
+ */
+ long lastCpuDelayTime;
+
+ /**
* Snapshotted value of {@link ProcessStateRecord#getCurProcState()} before
* dispatching the current broadcast to the receiver in this process.
*/
diff --git a/services/core/java/com/android/server/am/BroadcastQueueModernImpl.java b/services/core/java/com/android/server/am/BroadcastQueueModernImpl.java
index eb219a8..a428907 100644
--- a/services/core/java/com/android/server/am/BroadcastQueueModernImpl.java
+++ b/services/core/java/com/android/server/am/BroadcastQueueModernImpl.java
@@ -258,6 +258,9 @@
private static final int MSG_PROCESS_FREEZABLE_CHANGED = 6;
private static final int MSG_UID_STATE_CHANGED = 7;
+ // Required when Flags.anrTimerServiceEnabled is false.
+ private static final int MSG_DELIVERY_TIMEOUT_SOFT = 8;
+
private void enqueueUpdateRunningList() {
mLocalHandler.removeMessages(MSG_UPDATE_RUNNING_LIST);
mLocalHandler.sendEmptyMessage(MSG_UPDATE_RUNNING_LIST);
@@ -271,6 +274,13 @@
updateRunningList();
return true;
}
+ // Required when Flags.anrTimerServiceEnabled is false.
+ case MSG_DELIVERY_TIMEOUT_SOFT: {
+ synchronized (mService) {
+ deliveryTimeoutSoftLocked((BroadcastProcessQueue) msg.obj, msg.arg1);
+ return true;
+ }
+ }
case MSG_DELIVERY_TIMEOUT: {
deliveryTimeout((BroadcastProcessQueue) msg.obj);
return true;
@@ -1030,7 +1040,7 @@
queue.setTimeoutScheduled(true);
final int softTimeoutMillis = (int) (r.isForeground() ? mFgConstants.TIMEOUT
: mBgConstants.TIMEOUT);
- mAnrTimer.start(queue, softTimeoutMillis);
+ startDeliveryTimeoutLocked(queue, softTimeoutMillis);
} else {
queue.setTimeoutScheduled(false);
}
@@ -1110,7 +1120,7 @@
// If we were trying to deliver a manifest broadcast, throw the error as we need
// to try redelivering the broadcast to this receiver.
if (receiver instanceof ResolveInfo) {
- mAnrTimer.cancel(queue);
+ cancelDeliveryTimeoutLocked(queue);
throw new BroadcastDeliveryFailedException(e);
}
finishReceiverActiveLocked(queue, BroadcastRecord.DELIVERY_FAILURE,
@@ -1159,6 +1169,41 @@
r.resultTo = null;
}
+ // Required when Flags.anrTimerServiceEnabled is false.
+ private void startDeliveryTimeoutLocked(@NonNull BroadcastProcessQueue queue,
+ int softTimeoutMillis) {
+ if (mAnrTimer.serviceEnabled()) {
+ mAnrTimer.start(queue, softTimeoutMillis);
+ } else {
+ queue.lastCpuDelayTime = queue.app.getCpuDelayTime();
+ mLocalHandler.sendMessageDelayed(Message.obtain(mLocalHandler,
+ MSG_DELIVERY_TIMEOUT_SOFT, softTimeoutMillis, 0, queue), softTimeoutMillis);
+ }
+ }
+
+ // Required when Flags.anrTimerServiceEnabled is false.
+ private void cancelDeliveryTimeoutLocked(@NonNull BroadcastProcessQueue queue) {
+ mAnrTimer.cancel(queue);
+ if (!mAnrTimer.serviceEnabled()) {
+ mLocalHandler.removeMessages(MSG_DELIVERY_TIMEOUT_SOFT, queue);
+ }
+ }
+
+ // Required when Flags.anrTimerServiceEnabled is false.
+ private void deliveryTimeoutSoftLocked(@NonNull BroadcastProcessQueue queue,
+ int softTimeoutMillis) {
+ if (queue.app != null) {
+ // Instead of immediately triggering an ANR, extend the timeout by
+ // the amount of time the process was runnable-but-waiting; we're
+ // only willing to do this once before triggering an hard ANR
+ final long cpuDelayTime = queue.app.getCpuDelayTime() - queue.lastCpuDelayTime;
+ final long hardTimeoutMillis = MathUtils.constrain(cpuDelayTime, 0, softTimeoutMillis);
+ mAnrTimer.start(queue, hardTimeoutMillis);
+ } else {
+ deliveryTimeoutLocked(queue);
+ }
+ }
+
private void deliveryTimeout(@NonNull BroadcastProcessQueue queue) {
synchronized (mService) {
deliveryTimeoutLocked(queue);
@@ -1292,7 +1337,7 @@
mAnrTimer.discard(queue);
}
} else if (queue.timeoutScheduled()) {
- mAnrTimer.cancel(queue);
+ cancelDeliveryTimeoutLocked(queue);
}
// Given that a receiver just finished, check if the "waitingFor" conditions are met.
diff --git a/services/core/java/com/android/server/am/OomConnection.java b/services/core/java/com/android/server/am/OomConnection.java
new file mode 100644
index 0000000..17a4ce5
--- /dev/null
+++ b/services/core/java/com/android/server/am/OomConnection.java
@@ -0,0 +1,63 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.am;
+
+import android.os.OomKillRecord;
+import android.util.Slog;
+
+/** Connection to the out-of-memory (OOM) events' file */
+public final class OomConnection {
+ private static final String TAG = "OomConnection";
+
+ /** Connection listener interface */
+ public interface OomConnectionListener {
+
+ /**
+ * Callback function to handle the newest OOM kills.
+ *
+ * @param oomKills List of oom kills received from `waitOom()`
+ */
+ void handleOomEvent(OomKillRecord[] oomKills);
+ }
+
+ private final OomConnectionListener mOomListener;
+
+ private final OomConnectionThread mOomConnectionThread;
+
+ private static native OomKillRecord[] waitOom();
+
+ public OomConnection(OomConnectionListener listener) {
+ mOomListener = listener;
+ mOomConnectionThread = new OomConnectionThread();
+ mOomConnectionThread.start();
+ }
+
+ private final class OomConnectionThread extends Thread {
+ public void run() {
+ while (true) {
+ OomKillRecord[] oom_kills = null;
+ try {
+ oom_kills = waitOom();
+ mOomListener.handleOomEvent(oom_kills);
+ } catch (RuntimeException e) {
+ Slog.e(TAG, "failed waiting for OOM events: " + e);
+ break;
+ }
+ }
+ }
+ }
+}
diff --git a/services/core/java/com/android/server/am/ProcessList.java b/services/core/java/com/android/server/am/ProcessList.java
index a97675f..4572766 100644
--- a/services/core/java/com/android/server/am/ProcessList.java
+++ b/services/core/java/com/android/server/am/ProcessList.java
@@ -97,6 +97,7 @@
import android.os.IBinder;
import android.os.Looper;
import android.os.Message;
+import android.os.OomKillRecord;
import android.os.PowerManager;
import android.os.Process;
import android.os.RemoteCallbackList;
@@ -412,6 +413,8 @@
private static LmkdConnection sLmkdConnection = null;
+ private static OomConnection sOomConnection = null;
+
private boolean mOomLevelsSet = false;
private boolean mAppDataIsolationEnabled = false;
@@ -855,6 +858,21 @@
THREAD_PRIORITY_BACKGROUND, true /* allowIo */);
sKillThread.start();
sKillHandler = new KillHandler(sKillThread.getLooper());
+ sOomConnection = new OomConnection(new OomConnection.OomConnectionListener() {
+ @Override
+ public void handleOomEvent(OomKillRecord[] oomKills) {
+ for (OomKillRecord oomKill: oomKills) {
+ synchronized (mProcLock) {
+ noteAppKill(
+ oomKill.getPid(),
+ oomKill.getUid(),
+ ApplicationExitInfo.REASON_LOW_MEMORY,
+ ApplicationExitInfo.SUBREASON_OOM_KILL,
+ "oom");
+ }
+ }
+ }
+ });
sLmkdConnection = new LmkdConnection(sKillThread.getLooper().getQueue(),
new LmkdConnection.LmkdConnectionListener() {
@Override
diff --git a/services/core/java/com/android/server/am/SettingsToPropertiesMapper.java b/services/core/java/com/android/server/am/SettingsToPropertiesMapper.java
index 4a0bc4b..1ba1f55 100644
--- a/services/core/java/com/android/server/am/SettingsToPropertiesMapper.java
+++ b/services/core/java/com/android/server/am/SettingsToPropertiesMapper.java
@@ -131,13 +131,17 @@
"car_telemetry",
"codec_fwk",
"companion",
+ "content_protection",
"context_hub",
"core_experiments_team_internal",
"core_graphics",
"haptics",
"hardware_backed_security_mainline",
+ "input",
"machine_learning",
+ "mainline_sdk",
"media_audio",
+ "media_drm",
"media_solutions",
"nfc",
"pixel_audio_android",
diff --git a/services/core/java/com/android/server/am/flags.aconfig b/services/core/java/com/android/server/am/flags.aconfig
index b03cc62..26d99d8 100644
--- a/services/core/java/com/android/server/am/flags.aconfig
+++ b/services/core/java/com/android/server/am/flags.aconfig
@@ -6,4 +6,12 @@
description: "Utilize new OomAdjuster implementation"
bug: "298055811"
is_fixed_read_only: true
-}
\ No newline at end of file
+}
+
+flag {
+ name: "anr_timer_service_enabled"
+ namespace: "system_performance"
+ is_fixed_read_only: true
+ description: "Feature flag for the ANR timer service"
+ bug: "282428924"
+}
diff --git a/services/core/java/com/android/server/content/SyncStorageEngine.java b/services/core/java/com/android/server/content/SyncStorageEngine.java
index 9805fd3..333f62a 100644
--- a/services/core/java/com/android/server/content/SyncStorageEngine.java
+++ b/services/core/java/com/android/server/content/SyncStorageEngine.java
@@ -1845,7 +1845,7 @@
private void parseListenForTickles(TypedXmlPullParser parser) {
int userId = 0;
try {
- parser.getAttributeInt(null, XML_ATTR_USER);
+ userId = parser.getAttributeInt(null, XML_ATTR_USER);
} catch (XmlPullParserException e) {
Slog.e(TAG, "error parsing the user for listen-for-tickles", e);
}
diff --git a/services/core/java/com/android/server/display/DisplayDeviceConfig.java b/services/core/java/com/android/server/display/DisplayDeviceConfig.java
index 9e92c8d..cfbe0c6 100644
--- a/services/core/java/com/android/server/display/DisplayDeviceConfig.java
+++ b/services/core/java/com/android/server/display/DisplayDeviceConfig.java
@@ -60,6 +60,9 @@
import com.android.server.display.config.NitsMap;
import com.android.server.display.config.NonNegativeFloatToFloatPoint;
import com.android.server.display.config.Point;
+import com.android.server.display.config.PowerThrottlingConfig;
+import com.android.server.display.config.PowerThrottlingMap;
+import com.android.server.display.config.PowerThrottlingPoint;
import com.android.server.display.config.PredefinedBrightnessLimitNames;
import com.android.server.display.config.RefreshRateConfigs;
import com.android.server.display.config.RefreshRateRange;
@@ -139,6 +142,30 @@
* </screenBrightnessMap>
*
* <screenBrightnessDefault>0.65</screenBrightnessDefault>
+ * <powerThrottlingConfig>
+ * <brightnessLowestCapAllowed>0.1</brightnessLowestCapAllowed>
+ * <pollingWindowMillis>15</pollingWindowMillis>
+ * <powerThrottlingMap>
+ * <powerThrottlingPoint>
+ * <thermalStatus>severe</thermalStatus>
+ * <powerQuotaMilliWatts>200.6</powerQuotaMilliWatts>
+ * </powerThrottlingPoint>
+ * <powerThrottlingPoint>
+ * <thermalStatus>critical</thermalStatus>
+ * <powerQuotaMilliWatts>300</powerQuotaMilliWatts>
+ * </powerThrottlingPoint>
+ * </powerThrottlingMap>
+ * <powerThrottlingMap id="id_2"> // optional attribute, leave blank for default
+ * <powerThrottlingPoint>
+ * <thermalStatus>moderate</thermalStatus>
+ * <powerQuotaMilliWatts>400</powerQuotaMilliWatts>
+ * </powerThrottlingPoint>
+ * <powerThrottlingPoint>
+ * <thermalStatus>severe</thermalStatus>
+ * <powerQuotaMilliWatts>250</powerQuotaMilliWatts>
+ * </powerThrottlingPoint>
+ * </powerThrottlingMap>
+ * </powerThrottlingConfig>
*
* <thermalThrottling>
* <brightnessThrottlingMap>
@@ -669,6 +696,8 @@
private List<String> mQuirks;
private boolean mIsHighBrightnessModeEnabled = false;
private HighBrightnessModeData mHbmData;
+ @Nullable
+ private PowerThrottlingConfigData mPowerThrottlingConfigData;
private DensityMapping mDensityMapping;
private String mLoadedFrom = null;
private Spline mSdrToHdrRatioSpline;
@@ -781,6 +810,9 @@
private final HashMap<String, ThermalBrightnessThrottlingData>
mThermalBrightnessThrottlingDataMapByThrottlingId = new HashMap<>();
+ private final HashMap<String, PowerThrottlingData>
+ mPowerThrottlingDataMapByThrottlingId = new HashMap<>();
+
private final Map<String, SparseArray<SurfaceControl.RefreshRateRange>>
mRefreshRateThrottlingMap = new HashMap<>();
@@ -1458,6 +1490,14 @@
return hbmData;
}
+ /**
+ * @return Power throttling configuration data for the display.
+ */
+ @Nullable
+ public PowerThrottlingConfigData getPowerThrottlingConfigData() {
+ return mPowerThrottlingConfigData;
+ }
+
@NonNull
public Map<BrightnessLimitMapType, Map<Float, Float>> getLuxThrottlingData() {
return mLuxThrottlingData;
@@ -1491,6 +1531,14 @@
}
/**
+ * @return power throttling configuration data for this display, for each throttling id.
+ **/
+ public HashMap<String, PowerThrottlingData>
+ getPowerThrottlingDataMapByThrottlingId() {
+ return mPowerThrottlingDataMapByThrottlingId;
+ }
+
+ /**
* @return Auto brightness darkening light debounce
*/
public long getAutoBrightnessDarkeningLightDebounce() {
@@ -1702,6 +1750,9 @@
+ ", mThermalBrightnessThrottlingDataMapByThrottlingId="
+ mThermalBrightnessThrottlingDataMapByThrottlingId
+ "\n"
+ + ", mPowerThrottlingDataMapByThrottlingId="
+ + mPowerThrottlingDataMapByThrottlingId
+ + "\n"
+ "mBrightnessRampFastDecrease=" + mBrightnessRampFastDecrease
+ ", mBrightnessRampFastIncrease=" + mBrightnessRampFastIncrease
+ ", mBrightnessRampSlowDecrease=" + mBrightnessRampSlowDecrease
@@ -1853,6 +1904,7 @@
loadBrightnessConstraintsFromConfigXml();
loadBrightnessMap(config);
loadThermalThrottlingConfig(config);
+ loadPowerThrottlingConfigData(config);
loadHighBrightnessModeData(config);
loadLuxThrottling(config);
loadQuirks(config);
@@ -2171,6 +2223,59 @@
}
}
+ private boolean loadPowerThrottlingMaps(PowerThrottlingConfig throttlingConfig) {
+ final List<PowerThrottlingMap> maps = throttlingConfig.getPowerThrottlingMap();
+ if (maps == null || maps.isEmpty()) {
+ Slog.i(TAG, "No power throttling map found");
+ return false;
+ }
+
+ for (PowerThrottlingMap map : maps) {
+ final List<PowerThrottlingPoint> points = map.getPowerThrottlingPoint();
+ // At least 1 point is guaranteed by the display device config schema
+ List<PowerThrottlingData.ThrottlingLevel> throttlingLevels =
+ new ArrayList<>(points.size());
+
+ boolean badConfig = false;
+ for (PowerThrottlingPoint point : points) {
+ ThermalStatus status = point.getThermalStatus();
+ if (!thermalStatusIsValid(status)) {
+ badConfig = true;
+ break;
+ }
+
+ throttlingLevels.add(new PowerThrottlingData.ThrottlingLevel(
+ convertThermalStatus(status),
+ point.getPowerQuotaMilliWatts().floatValue()));
+ }
+
+ if (!badConfig) {
+ String id = map.getId() == null ? DEFAULT_ID : map.getId();
+ if (mPowerThrottlingDataMapByThrottlingId.containsKey(id)) {
+ throw new RuntimeException("Power throttling data with ID " + id
+ + " already exists");
+ }
+ mPowerThrottlingDataMapByThrottlingId.put(id,
+ PowerThrottlingData.create(throttlingLevels));
+ }
+ }
+ return true;
+ }
+
+ private void loadPowerThrottlingConfigData(DisplayConfiguration config) {
+ final PowerThrottlingConfig powerThrottlingCfg = config.getPowerThrottlingConfig();
+ if (powerThrottlingCfg == null) {
+ return;
+ }
+ if (!loadPowerThrottlingMaps(powerThrottlingCfg)) {
+ return;
+ }
+ float lowestBrightnessCap = powerThrottlingCfg.getBrightnessLowestCapAllowed().floatValue();
+ int pollingWindowMillis = powerThrottlingCfg.getPollingWindowMillis().intValue();
+ mPowerThrottlingConfigData = new PowerThrottlingConfigData(lowestBrightnessCap,
+ pollingWindowMillis);
+ }
+
private void loadRefreshRateSetting(DisplayConfiguration config) {
final RefreshRateConfigs refreshRateConfigs =
(config == null) ? null : config.getRefreshRate();
@@ -3379,6 +3484,148 @@
}
/**
+ * Container for Power throttling configuration data.
+ * TODO(b/302814899): extract to separate class.
+ */
+ public static class PowerThrottlingConfigData {
+ /** Lowest brightness cap allowed for this device. */
+ public final float brightnessLowestCapAllowed;
+ /** Time window for polling power in seconds. */
+ public final int pollingWindowMillis;
+ public PowerThrottlingConfigData(float brightnessLowestCapAllowed,
+ int pollingWindowMillis) {
+ this.brightnessLowestCapAllowed = brightnessLowestCapAllowed;
+ this.pollingWindowMillis = pollingWindowMillis;
+ }
+
+ @Override
+ public String toString() {
+ return "PowerThrottlingConfigData{"
+ + "brightnessLowestCapAllowed: "
+ + brightnessLowestCapAllowed
+ + ", pollingWindowMillis: " + pollingWindowMillis
+ + "} ";
+ }
+ }
+
+ /**
+ * Container for power throttling data.
+ * TODO(b/302814899): extract to separate class and unify with ThermalBrightnessThrottlingData.
+ */
+ public static class PowerThrottlingData {
+ public List<ThrottlingLevel> throttlingLevels;
+
+ /**
+ * thermal status to power quota mapping.
+ */
+ public static class ThrottlingLevel {
+ public @PowerManager.ThermalStatus int thermalStatus;
+ public float powerQuotaMilliWatts;
+
+ public ThrottlingLevel(
+ @PowerManager.ThermalStatus int thermalStatus, float powerQuotaMilliWatts) {
+ this.thermalStatus = thermalStatus;
+ this.powerQuotaMilliWatts = powerQuotaMilliWatts;
+ }
+
+ @Override
+ public String toString() {
+ return "[" + thermalStatus + "," + powerQuotaMilliWatts + "]";
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (!(obj instanceof ThrottlingLevel)) {
+ return false;
+ }
+ ThrottlingLevel otherThrottlingLevel = (ThrottlingLevel) obj;
+
+ return otherThrottlingLevel.thermalStatus == this.thermalStatus
+ && otherThrottlingLevel.powerQuotaMilliWatts == this.powerQuotaMilliWatts;
+ }
+
+ @Override
+ public int hashCode() {
+ int result = 1;
+ result = 31 * result + thermalStatus;
+ result = 31 * result + Float.hashCode(powerQuotaMilliWatts);
+ return result;
+ }
+ }
+
+
+ /**
+ * Creates multiple temperature based throttling levels of power quota.
+ */
+ public static PowerThrottlingData create(
+ List<ThrottlingLevel> throttlingLevels) {
+ if (throttlingLevels == null || throttlingLevels.size() == 0) {
+ Slog.e(TAG, "PowerThrottlingData received null or empty throttling levels");
+ return null;
+ }
+
+ ThrottlingLevel prevLevel = throttlingLevels.get(0);
+ final int numLevels = throttlingLevels.size();
+ for (int i = 1; i < numLevels; i++) {
+ ThrottlingLevel thisLevel = throttlingLevels.get(i);
+
+ if (thisLevel.thermalStatus <= prevLevel.thermalStatus) {
+ Slog.e(TAG, "powerThrottlingMap must be strictly increasing, ignoring "
+ + "configuration. ThermalStatus " + thisLevel.thermalStatus + " <= "
+ + prevLevel.thermalStatus);
+ return null;
+ }
+
+ if (thisLevel.powerQuotaMilliWatts >= prevLevel.powerQuotaMilliWatts) {
+ Slog.e(TAG, "powerThrottlingMap must be strictly decreasing, ignoring "
+ + "configuration. powerQuotaMilliWatts "
+ + thisLevel.powerQuotaMilliWatts + " >= "
+ + prevLevel.powerQuotaMilliWatts);
+ return null;
+ }
+
+ prevLevel = thisLevel;
+ }
+ return new PowerThrottlingData(throttlingLevels);
+ }
+
+ @Override
+ public String toString() {
+ return "PowerThrottlingData{"
+ + "throttlingLevels:" + throttlingLevels
+ + "} ";
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+
+ if (!(obj instanceof PowerThrottlingData)) {
+ return false;
+ }
+
+ PowerThrottlingData otherData = (PowerThrottlingData) obj;
+ return throttlingLevels.equals(otherData.throttlingLevels);
+ }
+
+ @Override
+ public int hashCode() {
+ return throttlingLevels.hashCode();
+ }
+
+ @VisibleForTesting
+ PowerThrottlingData(List<ThrottlingLevel> inLevels) {
+ throttlingLevels = new ArrayList<>(inLevels.size());
+ for (ThrottlingLevel level : inLevels) {
+ throttlingLevels.add(new ThrottlingLevel(level.thermalStatus,
+ level.powerQuotaMilliWatts));
+ }
+ }
+ }
+
+ /**
* Container for brightness throttling data.
*/
public static class ThermalBrightnessThrottlingData {
diff --git a/services/core/java/com/android/server/display/feature/DisplayManagerFlags.java b/services/core/java/com/android/server/display/feature/DisplayManagerFlags.java
index b6273e1..d5382cb 100644
--- a/services/core/java/com/android/server/display/feature/DisplayManagerFlags.java
+++ b/services/core/java/com/android/server/display/feature/DisplayManagerFlags.java
@@ -51,22 +51,10 @@
Flags.FLAG_ENABLE_DISPLAY_OFFLOAD,
Flags::enableDisplayOffload);
- private final FlagState mDisplayResolutionRangeVotingState = new FlagState(
- Flags.FLAG_ENABLE_DISPLAY_RESOLUTION_RANGE_VOTING,
- Flags::enableDisplayResolutionRangeVoting);
-
- private final FlagState mUserPreferredModeVoteState = new FlagState(
- Flags.FLAG_ENABLE_USER_PREFERRED_MODE_VOTE,
- Flags::enableUserPreferredModeVote);
-
private final FlagState mExternalDisplayLimitModeState = new FlagState(
Flags.FLAG_ENABLE_MODE_LIMIT_FOR_EXTERNAL_DISPLAY,
Flags::enableModeLimitForExternalDisplay);
- private final FlagState mDisplaysRefreshRatesSynchronizationState = new FlagState(
- Flags.FLAG_ENABLE_DISPLAYS_REFRESH_RATES_SYNCHRONIZATION,
- Flags::enableDisplaysRefreshRatesSynchronization);
-
/** Returns whether connected display management is enabled or not. */
public boolean isConnectedDisplayManagementEnabled() {
return mConnectedDisplayManagementFlagState.isEnabled();
@@ -90,7 +78,7 @@
/** Returns whether resolution range voting feature is enabled or not. */
public boolean isDisplayResolutionRangeVotingEnabled() {
- return mDisplayResolutionRangeVotingState.isEnabled();
+ return isExternalDisplayLimitModeEnabled();
}
/**
@@ -98,7 +86,7 @@
* {@link com.android.server.display.mode.DisplayModeDirector}
*/
public boolean isUserPreferredModeVoteEnabled() {
- return mUserPreferredModeVoteState.isEnabled();
+ return isExternalDisplayLimitModeEnabled();
}
/**
@@ -112,7 +100,7 @@
* @return Whether displays refresh rate synchronization is enabled.
*/
public boolean isDisplaysRefreshRatesSynchronizationEnabled() {
- return mDisplaysRefreshRatesSynchronizationState.isEnabled();
+ return isExternalDisplayLimitModeEnabled();
}
/** Returns whether displayoffload is enabled on not */
diff --git a/services/core/java/com/android/server/input/FocusEventDebugView.java b/services/core/java/com/android/server/input/FocusEventDebugView.java
deleted file mode 100644
index 4b8fabde..0000000
--- a/services/core/java/com/android/server/input/FocusEventDebugView.java
+++ /dev/null
@@ -1,848 +0,0 @@
-/*
- * Copyright 2023 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.server.input;
-
-import static android.util.TypedValue.COMPLEX_UNIT_DIP;
-import static android.util.TypedValue.COMPLEX_UNIT_SP;
-import static android.view.ViewGroup.LayoutParams.WRAP_CONTENT;
-
-import android.animation.LayoutTransition;
-import android.annotation.AnyThread;
-import android.annotation.Nullable;
-import android.content.Context;
-import android.graphics.Canvas;
-import android.graphics.Color;
-import android.graphics.ColorFilter;
-import android.graphics.ColorMatrixColorFilter;
-import android.graphics.Paint;
-import android.graphics.Typeface;
-import android.util.DisplayMetrics;
-import android.util.Pair;
-import android.util.Slog;
-import android.util.TypedValue;
-import android.view.Gravity;
-import android.view.InputDevice;
-import android.view.KeyEvent;
-import android.view.MotionEvent;
-import android.view.RoundedCorner;
-import android.view.View;
-import android.view.ViewConfiguration;
-import android.view.WindowInsets;
-import android.view.animation.AccelerateInterpolator;
-import android.widget.HorizontalScrollView;
-import android.widget.LinearLayout;
-import android.widget.RelativeLayout;
-import android.widget.TextView;
-
-import com.android.internal.R;
-import com.android.internal.annotations.VisibleForTesting;
-
-import java.util.HashMap;
-import java.util.Iterator;
-import java.util.Locale;
-import java.util.Map;
-import java.util.concurrent.TimeUnit;
-import java.util.function.Supplier;
-
-/**
- * Displays focus events, such as physical keyboard KeyEvents and non-pointer MotionEvents on
- * the screen.
- */
-class FocusEventDebugView extends RelativeLayout {
-
- private static final String TAG = FocusEventDebugView.class.getSimpleName();
-
- private static final int KEY_FADEOUT_DURATION_MILLIS = 1000;
- private static final int KEY_TRANSITION_DURATION_MILLIS = 100;
-
- private static final int OUTER_PADDING_DP = 16;
- private static final int KEY_SEPARATION_MARGIN_DP = 16;
- private static final int KEY_VIEW_SIDE_PADDING_DP = 16;
- private static final int KEY_VIEW_VERTICAL_PADDING_DP = 8;
- private static final int KEY_VIEW_MIN_WIDTH_DP = 32;
- private static final int KEY_VIEW_TEXT_SIZE_SP = 12;
- private static final double ROTATY_GRAPH_HEIGHT_FRACTION = 0.5;
-
- private final InputManagerService mService;
- private final int mOuterPadding;
- private final DisplayMetrics mDm;
-
- // Tracks all keys that are currently pressed/down.
- private final Map<Pair<Integer /*deviceId*/, Integer /*scanCode*/>, PressedKeyView>
- mPressedKeys = new HashMap<>();
-
- @Nullable
- private FocusEventDebugGlobalMonitor mFocusEventDebugGlobalMonitor;
- @Nullable
- private PressedKeyContainer mPressedKeyContainer;
- @Nullable
- private PressedKeyContainer mPressedModifierContainer;
- private final Supplier<RotaryInputValueView> mRotaryInputValueViewFactory;
- @Nullable
- private RotaryInputValueView mRotaryInputValueView;
- private final Supplier<RotaryInputGraphView> mRotaryInputGraphViewFactory;
- @Nullable
- private RotaryInputGraphView mRotaryInputGraphView;
-
- @VisibleForTesting
- FocusEventDebugView(Context c, InputManagerService service,
- Supplier<RotaryInputValueView> rotaryInputValueViewFactory,
- Supplier<RotaryInputGraphView> rotaryInputGraphViewFactory) {
- super(c);
- setFocusableInTouchMode(true);
-
- mService = service;
- mRotaryInputValueViewFactory = rotaryInputValueViewFactory;
- mRotaryInputGraphViewFactory = rotaryInputGraphViewFactory;
- mDm = mContext.getResources().getDisplayMetrics();
- mOuterPadding = (int) TypedValue.applyDimension(COMPLEX_UNIT_DIP, OUTER_PADDING_DP, mDm);
- }
-
- FocusEventDebugView(Context c, InputManagerService service) {
- this(c, service, () -> new RotaryInputValueView(c), () -> new RotaryInputGraphView(c));
- }
-
- @Override
- public WindowInsets onApplyWindowInsets(WindowInsets insets) {
- int paddingBottom = 0;
-
- final RoundedCorner bottomLeft =
- insets.getRoundedCorner(RoundedCorner.POSITION_BOTTOM_LEFT);
- if (bottomLeft != null && !insets.isRound()) {
- paddingBottom = bottomLeft.getRadius();
- }
-
- final RoundedCorner bottomRight =
- insets.getRoundedCorner(RoundedCorner.POSITION_BOTTOM_RIGHT);
- if (bottomRight != null && !insets.isRound()) {
- paddingBottom = Math.max(paddingBottom, bottomRight.getRadius());
- }
-
- if (insets.getDisplayCutout() != null) {
- paddingBottom =
- Math.max(paddingBottom, insets.getDisplayCutout().getSafeInsetBottom());
- }
-
- setPadding(mOuterPadding, mOuterPadding, mOuterPadding, mOuterPadding + paddingBottom);
- setClipToPadding(false);
- invalidate();
- return super.onApplyWindowInsets(insets);
- }
-
- @Override
- public boolean dispatchKeyEvent(KeyEvent event) {
- handleKeyEvent(event);
- return super.dispatchKeyEvent(event);
- }
-
- @AnyThread
- public void updateShowKeyPresses(boolean enabled) {
- post(() -> handleUpdateShowKeyPresses(enabled));
- }
-
- @AnyThread
- public void updateShowRotaryInput(boolean enabled) {
- post(() -> handleUpdateShowRotaryInput(enabled));
- }
-
- private void handleUpdateShowKeyPresses(boolean enabled) {
- if (enabled == showKeyPresses()) {
- return;
- }
-
- if (!enabled) {
- removeView(mPressedKeyContainer);
- mPressedKeyContainer = null;
- removeView(mPressedModifierContainer);
- mPressedModifierContainer = null;
- return;
- }
-
- mPressedKeyContainer = new PressedKeyContainer(mContext);
- mPressedKeyContainer.setOrientation(LinearLayout.HORIZONTAL);
- mPressedKeyContainer.setGravity(Gravity.RIGHT | Gravity.BOTTOM);
- mPressedKeyContainer.setLayoutDirection(LAYOUT_DIRECTION_LTR);
- final var scroller = new HorizontalScrollView(mContext);
- scroller.addView(mPressedKeyContainer);
- scroller.setHorizontalScrollBarEnabled(false);
- scroller.addOnLayoutChangeListener(
- (view, l, t, r, b, ol, ot, or, ob) -> scroller.fullScroll(View.FOCUS_RIGHT));
- scroller.setHorizontalFadingEdgeEnabled(true);
- LayoutParams scrollerLayoutParams = new LayoutParams(WRAP_CONTENT, WRAP_CONTENT);
- scrollerLayoutParams.addRule(ALIGN_PARENT_BOTTOM);
- scrollerLayoutParams.addRule(ALIGN_PARENT_RIGHT);
- addView(scroller, scrollerLayoutParams);
-
- mPressedModifierContainer = new PressedKeyContainer(mContext);
- mPressedModifierContainer.setOrientation(LinearLayout.VERTICAL);
- mPressedModifierContainer.setGravity(Gravity.LEFT | Gravity.BOTTOM);
- LayoutParams modifierLayoutParams = new LayoutParams(WRAP_CONTENT, WRAP_CONTENT);
- modifierLayoutParams.addRule(ALIGN_PARENT_BOTTOM);
- modifierLayoutParams.addRule(ALIGN_PARENT_LEFT);
- modifierLayoutParams.addRule(LEFT_OF, scroller.getId());
- addView(mPressedModifierContainer, modifierLayoutParams);
- }
-
- @VisibleForTesting
- void handleUpdateShowRotaryInput(boolean enabled) {
- if (enabled == showRotaryInput()) {
- return;
- }
-
- if (!enabled) {
- mFocusEventDebugGlobalMonitor.dispose();
- mFocusEventDebugGlobalMonitor = null;
- removeView(mRotaryInputValueView);
- mRotaryInputValueView = null;
- removeView(mRotaryInputGraphView);
- mRotaryInputGraphView = null;
- return;
- }
-
- mFocusEventDebugGlobalMonitor = new FocusEventDebugGlobalMonitor(this, mService);
-
- mRotaryInputValueView = mRotaryInputValueViewFactory.get();
- LayoutParams valueLayoutParams = new LayoutParams(WRAP_CONTENT, WRAP_CONTENT);
- valueLayoutParams.addRule(CENTER_HORIZONTAL);
- valueLayoutParams.addRule(ALIGN_PARENT_BOTTOM);
- addView(mRotaryInputValueView, valueLayoutParams);
-
- mRotaryInputGraphView = mRotaryInputGraphViewFactory.get();
- LayoutParams graphLayoutParams = new LayoutParams(LayoutParams.MATCH_PARENT,
- (int) (ROTATY_GRAPH_HEIGHT_FRACTION * mDm.heightPixels));
- graphLayoutParams.addRule(CENTER_IN_PARENT);
- addView(mRotaryInputGraphView, graphLayoutParams);
- }
-
- /** Report a key event to the debug view. */
- @AnyThread
- public void reportKeyEvent(KeyEvent event) {
- post(() -> handleKeyEvent(KeyEvent.obtain((KeyEvent) event)));
- }
-
- /** Report a motion event to the debug view. */
- @AnyThread
- public void reportMotionEvent(MotionEvent event) {
- if (event.getSource() != InputDevice.SOURCE_ROTARY_ENCODER) {
- return;
- }
-
- post(() -> handleRotaryInput(MotionEvent.obtain((MotionEvent) event)));
- }
-
- private void handleKeyEvent(KeyEvent keyEvent) {
- if (!showKeyPresses()) {
- return;
- }
-
- final var identifier = new Pair<>(keyEvent.getDeviceId(), keyEvent.getScanCode());
- final var container = KeyEvent.isModifierKey(keyEvent.getKeyCode())
- ? mPressedModifierContainer
- : mPressedKeyContainer;
- PressedKeyView pressedKeyView = mPressedKeys.get(identifier);
- switch (keyEvent.getAction()) {
- case KeyEvent.ACTION_DOWN: {
- if (pressedKeyView != null) {
- if (keyEvent.getRepeatCount() == 0) {
- Slog.w(TAG, "Got key down for "
- + KeyEvent.keyCodeToString(keyEvent.getKeyCode())
- + " that was already tracked as being down.");
- break;
- }
- container.handleKeyRepeat(pressedKeyView);
- break;
- }
-
- pressedKeyView = new PressedKeyView(mContext, getLabel(keyEvent));
- mPressedKeys.put(identifier, pressedKeyView);
- container.handleKeyPressed(pressedKeyView);
- break;
- }
- case KeyEvent.ACTION_UP: {
- if (pressedKeyView == null) {
- Slog.w(TAG, "Got key up for " + KeyEvent.keyCodeToString(keyEvent.getKeyCode())
- + " that was not tracked as being down.");
- break;
- }
- mPressedKeys.remove(identifier);
- container.handleKeyRelease(pressedKeyView);
- break;
- }
- default:
- break;
- }
- keyEvent.recycle();
- }
-
- @VisibleForTesting
- void handleRotaryInput(MotionEvent motionEvent) {
- if (!showRotaryInput()) {
- return;
- }
-
- float scrollAxisValue = motionEvent.getAxisValue(MotionEvent.AXIS_SCROLL);
- mRotaryInputValueView.updateValue(scrollAxisValue);
- mRotaryInputGraphView.addValue(scrollAxisValue, motionEvent.getEventTime());
-
- motionEvent.recycle();
- }
-
- private static String getLabel(KeyEvent event) {
- switch (event.getKeyCode()) {
- case KeyEvent.KEYCODE_SPACE:
- return "\u2423";
- case KeyEvent.KEYCODE_TAB:
- return "\u21e5";
- case KeyEvent.KEYCODE_ENTER:
- case KeyEvent.KEYCODE_NUMPAD_ENTER:
- return "\u23CE";
- case KeyEvent.KEYCODE_DEL:
- return "\u232B";
- case KeyEvent.KEYCODE_FORWARD_DEL:
- return "\u2326";
- case KeyEvent.KEYCODE_ESCAPE:
- return "ESC";
- case KeyEvent.KEYCODE_DPAD_UP:
- return "\u2191";
- case KeyEvent.KEYCODE_DPAD_DOWN:
- return "\u2193";
- case KeyEvent.KEYCODE_DPAD_LEFT:
- return "\u2190";
- case KeyEvent.KEYCODE_DPAD_RIGHT:
- return "\u2192";
- case KeyEvent.KEYCODE_DPAD_UP_RIGHT:
- return "\u2197";
- case KeyEvent.KEYCODE_DPAD_UP_LEFT:
- return "\u2196";
- case KeyEvent.KEYCODE_DPAD_DOWN_RIGHT:
- return "\u2198";
- case KeyEvent.KEYCODE_DPAD_DOWN_LEFT:
- return "\u2199";
- default:
- break;
- }
-
- final int unicodeChar = event.getUnicodeChar();
- if (unicodeChar != 0) {
- return new String(Character.toChars(unicodeChar));
- }
-
- final var label = KeyEvent.keyCodeToString(event.getKeyCode());
- if (label.startsWith("KEYCODE_")) {
- return label.substring(8);
- }
- return label;
- }
-
- /** Determine whether to show key presses by checking one of the key-related objects. */
- private boolean showKeyPresses() {
- return mPressedKeyContainer != null;
- }
-
- /** Determine whether to show rotary input by checking one of the rotary-related objects. */
- private boolean showRotaryInput() {
- return mRotaryInputValueView != null;
- }
-
- /**
- * Converts a dimension in scaled pixel units to integer display pixels.
- */
- private static int applyDimensionSp(int dimensionSp, DisplayMetrics dm) {
- return (int) TypedValue.applyDimension(COMPLEX_UNIT_SP, dimensionSp, dm);
- }
-
- private static class PressedKeyView extends TextView {
-
- private static final ColorFilter sInvertColors = new ColorMatrixColorFilter(new float[]{
- -1.0f, 0, 0, 0, 255, // red
- 0, -1.0f, 0, 0, 255, // green
- 0, 0, -1.0f, 0, 255, // blue
- 0, 0, 0, 1.0f, 0 // alpha
- });
-
- PressedKeyView(Context c, String label) {
- super(c);
-
- final var dm = c.getResources().getDisplayMetrics();
- final int keyViewSidePadding =
- (int) TypedValue.applyDimension(COMPLEX_UNIT_DIP, KEY_VIEW_SIDE_PADDING_DP, dm);
- final int keyViewVerticalPadding =
- (int) TypedValue.applyDimension(COMPLEX_UNIT_DIP, KEY_VIEW_VERTICAL_PADDING_DP,
- dm);
- final int keyViewMinWidth =
- (int) TypedValue.applyDimension(COMPLEX_UNIT_DIP, KEY_VIEW_MIN_WIDTH_DP, dm);
- final int textSize =
- (int) TypedValue.applyDimension(COMPLEX_UNIT_SP, KEY_VIEW_TEXT_SIZE_SP, dm);
-
- setText(label);
- setGravity(Gravity.CENTER);
- setMinimumWidth(keyViewMinWidth);
- setTextSize(textSize);
- setTypeface(Typeface.SANS_SERIF);
- setBackgroundResource(R.drawable.focus_event_pressed_key_background);
- setPaddingRelative(keyViewSidePadding, keyViewVerticalPadding, keyViewSidePadding,
- keyViewVerticalPadding);
-
- setHighlighted(true);
- }
-
- void setHighlighted(boolean isHighlighted) {
- if (isHighlighted) {
- setTextColor(Color.BLACK);
- getBackground().setColorFilter(sInvertColors);
- } else {
- setTextColor(Color.WHITE);
- getBackground().clearColorFilter();
- }
- invalidate();
- }
- }
-
- private static class PressedKeyContainer extends LinearLayout {
-
- private final MarginLayoutParams mPressedKeyLayoutParams;
-
- PressedKeyContainer(Context c) {
- super(c);
-
- final var dm = c.getResources().getDisplayMetrics();
- final int keySeparationMargin =
- (int) TypedValue.applyDimension(COMPLEX_UNIT_DIP, KEY_SEPARATION_MARGIN_DP, dm);
-
- final var transition = new LayoutTransition();
- transition.disableTransitionType(LayoutTransition.APPEARING);
- transition.disableTransitionType(LayoutTransition.DISAPPEARING);
- transition.disableTransitionType(LayoutTransition.CHANGE_DISAPPEARING);
- transition.setDuration(KEY_TRANSITION_DURATION_MILLIS);
- setLayoutTransition(transition);
-
- mPressedKeyLayoutParams = new MarginLayoutParams(WRAP_CONTENT, WRAP_CONTENT);
- if (getOrientation() == VERTICAL) {
- mPressedKeyLayoutParams.setMargins(0, keySeparationMargin, 0, 0);
- } else {
- mPressedKeyLayoutParams.setMargins(keySeparationMargin, 0, 0, 0);
- }
- }
-
- public void handleKeyPressed(PressedKeyView pressedKeyView) {
- addView(pressedKeyView, getChildCount(), mPressedKeyLayoutParams);
- invalidate();
- }
-
- public void handleKeyRepeat(PressedKeyView repeatedKeyView) {
- // Do nothing for now.
- }
-
- public void handleKeyRelease(PressedKeyView releasedKeyView) {
- releasedKeyView.setHighlighted(false);
- releasedKeyView.clearAnimation();
- releasedKeyView.animate()
- .alpha(0)
- .setDuration(KEY_FADEOUT_DURATION_MILLIS)
- .setInterpolator(new AccelerateInterpolator())
- .withEndAction(this::cleanUpPressedKeyViews)
- .start();
- }
-
- private void cleanUpPressedKeyViews() {
- int numChildrenToRemove = 0;
- for (int i = 0; i < getChildCount(); i++) {
- final View child = getChildAt(i);
- if (child.getAlpha() != 0) {
- break;
- }
- child.setVisibility(View.GONE);
- child.clearAnimation();
- numChildrenToRemove++;
- }
- removeViews(0, numChildrenToRemove);
- invalidate();
- }
- }
-
- // TODO(b/286086154): move RotaryInputGraphView and RotaryInputValueView to a subpackage.
-
- /** Draws the most recent rotary input value and indicates whether the source is active. */
- @VisibleForTesting
- static class RotaryInputValueView extends TextView {
-
- private static final int INACTIVE_TEXT_COLOR = 0xffff00ff;
- private static final int ACTIVE_TEXT_COLOR = 0xff420f28;
- private static final int TEXT_SIZE_SP = 8;
- private static final int SIDE_PADDING_SP = 4;
- /** Determines how long the active status lasts. */
- private static final int ACTIVE_STATUS_DURATION = 250 /* milliseconds */;
- private static final ColorFilter ACTIVE_BACKGROUND_FILTER =
- new ColorMatrixColorFilter(new float[]{
- 0, 0, 0, 0, 255, // red
- 0, 0, 0, 0, 0, // green
- 0, 0, 0, 0, 255, // blue
- 0, 0, 0, 0, 200 // alpha
- });
-
- private final Runnable mUpdateActivityStatusCallback = () -> updateActivityStatus(false);
- private final float mScaledVerticalScrollFactor;
-
- @VisibleForTesting
- RotaryInputValueView(Context c) {
- super(c);
-
- DisplayMetrics dm = mContext.getResources().getDisplayMetrics();
- mScaledVerticalScrollFactor = ViewConfiguration.get(c).getScaledVerticalScrollFactor();
-
- setText(getFormattedValue(0));
- setTextColor(INACTIVE_TEXT_COLOR);
- setTextSize(applyDimensionSp(TEXT_SIZE_SP, dm));
- setPaddingRelative(applyDimensionSp(SIDE_PADDING_SP, dm), 0,
- applyDimensionSp(SIDE_PADDING_SP, dm), 0);
- setTypeface(null, Typeface.BOLD);
- setBackgroundResource(R.drawable.focus_event_rotary_input_background);
- }
-
- void updateValue(float value) {
- removeCallbacks(mUpdateActivityStatusCallback);
-
- setText(getFormattedValue(value * mScaledVerticalScrollFactor));
-
- updateActivityStatus(true);
- postDelayed(mUpdateActivityStatusCallback, ACTIVE_STATUS_DURATION);
- }
-
- @VisibleForTesting
- void updateActivityStatus(boolean active) {
- if (active) {
- setTextColor(ACTIVE_TEXT_COLOR);
- getBackground().setColorFilter(ACTIVE_BACKGROUND_FILTER);
- } else {
- setTextColor(INACTIVE_TEXT_COLOR);
- getBackground().clearColorFilter();
- }
- }
-
- private static String getFormattedValue(float value) {
- return String.format("%s%.1f", value < 0 ? "-" : "+", Math.abs(value));
- }
- }
-
- /**
- * Shows a graph with the rotary input values as a function of time.
- * The graph gets reset if no action is received for a certain amount of time.
- */
- @VisibleForTesting
- static class RotaryInputGraphView extends View {
-
- private static final int FRAME_COLOR = 0xbf741b47;
- private static final int FRAME_WIDTH_SP = 2;
- private static final int FRAME_BORDER_GAP_SP = 10;
- private static final int FRAME_TEXT_SIZE_SP = 10;
- private static final int FRAME_TEXT_OFFSET_SP = 2;
- private static final int GRAPH_COLOR = 0xffff00ff;
- private static final int GRAPH_LINE_WIDTH_SP = 1;
- private static final int GRAPH_POINT_RADIUS_SP = 4;
- private static final long MAX_SHOWN_TIME_INTERVAL = TimeUnit.SECONDS.toMillis(5);
- private static final float DEFAULT_FRAME_CENTER_POSITION = 0;
- private static final int MAX_GRAPH_VALUES_SIZE = 400;
- /** Maximum time between values so that they are considered part of the same gesture. */
- private static final long MAX_GESTURE_TIME = TimeUnit.SECONDS.toMillis(1);
-
- private final DisplayMetrics mDm;
- /**
- * Distance in position units (amount scrolled in display pixels) from the center to the
- * top/bottom frame lines.
- */
- private final float mFrameCenterToBorderDistance;
- private final float mScaledVerticalScrollFactor;
- private final Locale mDefaultLocale;
- private final Paint mFramePaint = new Paint();
- private final Paint mFrameTextPaint = new Paint();
- private final Paint mGraphLinePaint = new Paint();
- private final Paint mGraphPointPaint = new Paint();
-
- private final CyclicBuffer mGraphValues = new CyclicBuffer(MAX_GRAPH_VALUES_SIZE);
- /** Position at which graph values are placed at the center of the graph. */
- private float mFrameCenterPosition = DEFAULT_FRAME_CENTER_POSITION;
-
- @VisibleForTesting
- RotaryInputGraphView(Context c) {
- super(c);
-
- mDm = mContext.getResources().getDisplayMetrics();
- // This makes the center-to-border distance equivalent to the display height, meaning
- // that the total height of the graph is equivalent to 2x the display height.
- mFrameCenterToBorderDistance = mDm.heightPixels;
- mScaledVerticalScrollFactor = ViewConfiguration.get(c).getScaledVerticalScrollFactor();
- mDefaultLocale = Locale.getDefault();
-
- mFramePaint.setColor(FRAME_COLOR);
- mFramePaint.setStrokeWidth(applyDimensionSp(FRAME_WIDTH_SP, mDm));
-
- mFrameTextPaint.setColor(GRAPH_COLOR);
- mFrameTextPaint.setTextSize(applyDimensionSp(FRAME_TEXT_SIZE_SP, mDm));
-
- mGraphLinePaint.setColor(GRAPH_COLOR);
- mGraphLinePaint.setStrokeWidth(applyDimensionSp(GRAPH_LINE_WIDTH_SP, mDm));
- mGraphLinePaint.setStrokeCap(Paint.Cap.ROUND);
- mGraphLinePaint.setStrokeJoin(Paint.Join.ROUND);
-
- mGraphPointPaint.setColor(GRAPH_COLOR);
- mGraphPointPaint.setStrokeWidth(applyDimensionSp(GRAPH_POINT_RADIUS_SP, mDm));
- mGraphPointPaint.setStrokeCap(Paint.Cap.ROUND);
- mGraphPointPaint.setStrokeJoin(Paint.Join.ROUND);
- }
-
- /**
- * Reads new scroll axis value and updates the list accordingly. Old positions are
- * kept at the front (what you would get with getFirst), while the recent positions are
- * kept at the back (what you would get with getLast). Also updates the frame center
- * position to handle out-of-bounds cases.
- */
- void addValue(float scrollAxisValue, long eventTime) {
- // Remove values that are too old.
- while (mGraphValues.getSize() > 0
- && (eventTime - mGraphValues.getFirst().mTime) > MAX_SHOWN_TIME_INTERVAL) {
- mGraphValues.removeFirst();
- }
-
- // If there are no recent values, reset the frame center.
- if (mGraphValues.getSize() == 0) {
- mFrameCenterPosition = DEFAULT_FRAME_CENTER_POSITION;
- }
-
- // Handle new value. We multiply the scroll axis value by the scaled scroll factor to
- // get the amount of pixels to be scrolled. We also compute the accumulated position
- // by adding the current value to the last one (if not empty).
- final float displacement = scrollAxisValue * mScaledVerticalScrollFactor;
- final float prevPos = (mGraphValues.getSize() == 0 ? 0 : mGraphValues.getLast().mPos);
- final float pos = prevPos + displacement;
-
- mGraphValues.add(pos, eventTime);
-
- // The difference between the distance of the most recent position from the center
- // frame (pos - mFrameCenterPosition) and the maximum allowed distance from the center
- // frame (mFrameCenterToBorderDistance).
- final float verticalDiff = Math.abs(pos - mFrameCenterPosition)
- - mFrameCenterToBorderDistance;
- // If needed, translate frame.
- if (verticalDiff > 0) {
- final int sign = pos - mFrameCenterPosition < 0 ? -1 : 1;
- // Here, we update the center frame position by the exact amount needed for us to
- // stay within the maximum allowed distance from the center frame.
- mFrameCenterPosition += sign * verticalDiff;
- }
-
- // Redraw canvas.
- invalidate();
- }
-
- @Override
- protected void onDraw(Canvas canvas) {
- super.onDraw(canvas);
-
- // Note: vertical coordinates in Canvas go from top to bottom,
- // that is bottomY > middleY > topY.
- final int verticalMargin = applyDimensionSp(FRAME_BORDER_GAP_SP, mDm);
- final int topY = verticalMargin;
- final int bottomY = getHeight() - verticalMargin;
- final int middleY = (topY + bottomY) / 2;
-
- // Note: horizontal coordinates in Canvas go from left to right,
- // that is rightX > leftX.
- final int leftX = 0;
- final int rightX = getWidth();
-
- // Draw the frame, which includes 3 lines that show the maximum,
- // minimum and middle positions of the graph.
- canvas.drawLine(leftX, topY, rightX, topY, mFramePaint);
- canvas.drawLine(leftX, middleY, rightX, middleY, mFramePaint);
- canvas.drawLine(leftX, bottomY, rightX, bottomY, mFramePaint);
-
- // Draw the position that each frame line corresponds to.
- final int frameTextOffset = applyDimensionSp(FRAME_TEXT_OFFSET_SP, mDm);
- canvas.drawText(
- String.format(mDefaultLocale, "%.1f",
- mFrameCenterPosition + mFrameCenterToBorderDistance),
- leftX,
- topY - frameTextOffset, mFrameTextPaint
- );
- canvas.drawText(
- String.format(mDefaultLocale, "%.1f", mFrameCenterPosition),
- leftX,
- middleY - frameTextOffset, mFrameTextPaint
- );
- canvas.drawText(
- String.format(mDefaultLocale, "%.1f",
- mFrameCenterPosition - mFrameCenterToBorderDistance),
- leftX,
- bottomY - frameTextOffset, mFrameTextPaint
- );
-
- // If there are no graph values to be drawn, stop here.
- if (mGraphValues.getSize() == 0) {
- return;
- }
-
- // Draw the graph using the times and positions.
- // We start at the most recent value (which should be drawn at the right) and move
- // to the older values (which should be drawn to the left of more recent ones). Negative
- // indices are handled by circuling back to the end of the buffer.
- final long mostRecentTime = mGraphValues.getLast().mTime;
- float prevCoordX = 0;
- float prevCoordY = 0;
- float prevAge = 0;
- for (Iterator<GraphValue> iter = mGraphValues.reverseIterator(); iter.hasNext();) {
- final GraphValue value = iter.next();
-
- final int age = (int) (mostRecentTime - value.mTime);
- final float pos = value.mPos;
-
- // We get the horizontal coordinate in time units from left to right with
- // (MAX_SHOWN_TIME_INTERVAL - age). Then, we rescale it to match the canvas
- // units by dividing it by the time-domain length (MAX_SHOWN_TIME_INTERVAL)
- // and by multiplying it by the canvas length (rightX - leftX). Finally, we
- // offset the coordinate by adding it to leftX.
- final float coordX = leftX + ((float) (MAX_SHOWN_TIME_INTERVAL - age)
- / MAX_SHOWN_TIME_INTERVAL) * (rightX - leftX);
-
- // We get the vertical coordinate in position units from middle to top with
- // (pos - mFrameCenterPosition). Then, we rescale it to match the canvas
- // units by dividing it by half of the position-domain length
- // (mFrameCenterToBorderDistance) and by multiplying it by half of the canvas
- // length (middleY - topY). Finally, we offset the coordinate by subtracting
- // it from middleY (we can't "add" here because the coordinate grows from top
- // to bottom).
- final float coordY = middleY - ((pos - mFrameCenterPosition)
- / mFrameCenterToBorderDistance) * (middleY - topY);
-
- // Draw a point for this value.
- canvas.drawPoint(coordX, coordY, mGraphPointPaint);
-
- // If this value is part of the same gesture as the previous one, draw a line
- // between them. We ignore the first value (with age = 0).
- if (age != 0 && (age - prevAge) <= MAX_GESTURE_TIME) {
- canvas.drawLine(prevCoordX, prevCoordY, coordX, coordY, mGraphLinePaint);
- }
-
- prevCoordX = coordX;
- prevCoordY = coordY;
- prevAge = age;
- }
- }
-
- @VisibleForTesting
- float getFrameCenterPosition() {
- return mFrameCenterPosition;
- }
-
- /**
- * Holds data needed to draw each entry in the graph.
- */
- private static class GraphValue {
- /** Position. */
- float mPos;
- /** Time when this value was added. */
- long mTime;
-
- GraphValue(float pos, long time) {
- this.mPos = pos;
- this.mTime = time;
- }
- }
-
- /**
- * Holds the graph values as a cyclic buffer. It has a fixed capacity, and it replaces the
- * old values with new ones to avoid creating new objects.
- */
- private static class CyclicBuffer {
- private final GraphValue[] mValues;
- private final int mCapacity;
- private int mSize = 0;
- private int mLastIndex = 0;
-
- // The iteration index and counter are here to make it easier to reset them.
- /** Determines the value currently pointed by the iterator. */
- private int mIteratorIndex;
- /** Counts how many values have been iterated through. */
- private int mIteratorCount;
-
- /** Used traverse the values in reverse order. */
- private final Iterator<GraphValue> mReverseIterator = new Iterator<GraphValue>() {
- @Override
- public boolean hasNext() {
- return mIteratorCount <= mSize;
- }
-
- @Override
- public GraphValue next() {
- // Returns the value currently pointed by the iterator and moves the iterator to
- // the previous one.
- mIteratorCount++;
- return mValues[(mIteratorIndex-- + mCapacity) % mCapacity];
- }
- };
-
- CyclicBuffer(int capacity) {
- mCapacity = capacity;
- mValues = new GraphValue[capacity];
- }
-
- /**
- * Add new graph value. If there is an existing object, we replace its data with the
- * new one. With this, we re-use old objects instead of creating new ones.
- */
- void add(float pos, long time) {
- mLastIndex = (mLastIndex + 1) % mCapacity;
- if (mValues[mLastIndex] == null) {
- mValues[mLastIndex] = new GraphValue(pos, time);
- } else {
- final GraphValue oldValue = mValues[mLastIndex];
- oldValue.mPos = pos;
- oldValue.mTime = time;
- }
-
- // If needed, account for new value in the buffer size.
- if (mSize != mCapacity) {
- mSize++;
- }
- }
-
- int getSize() {
- return mSize;
- }
-
- GraphValue getFirst() {
- final int distanceBetweenLastAndFirst = (mCapacity - mSize) + 1;
- final int firstIndex = (mLastIndex + distanceBetweenLastAndFirst) % mCapacity;
- return mValues[firstIndex];
- }
-
- GraphValue getLast() {
- return mValues[mLastIndex];
- }
-
- void removeFirst() {
- mSize--;
- }
-
- /** Returns an iterator pointing at the last value. */
- Iterator<GraphValue> reverseIterator() {
- mIteratorIndex = mLastIndex;
- mIteratorCount = 1;
- return mReverseIterator;
- }
- }
- }
-}
diff --git a/services/core/java/com/android/server/input/GestureMonitorSpyWindow.java b/services/core/java/com/android/server/input/GestureMonitorSpyWindow.java
index 2ede56d..a2c8748 100644
--- a/services/core/java/com/android/server/input/GestureMonitorSpyWindow.java
+++ b/services/core/java/com/android/server/input/GestureMonitorSpyWindow.java
@@ -62,10 +62,10 @@
mWindowHandle.ownerUid = uid;
mWindowHandle.scaleFactor = 1.0f;
mWindowHandle.replaceTouchableRegionWithCrop(null /* use this surface's bounds */);
- mWindowHandle.inputConfig =
- InputConfig.NOT_FOCUSABLE | InputConfig.SPY | InputConfig.TRUSTED_OVERLAY;
+ mWindowHandle.inputConfig = InputConfig.NOT_FOCUSABLE | InputConfig.SPY;
final SurfaceControl.Transaction t = new SurfaceControl.Transaction();
+ mWindowHandle.setTrustedOverlay(t, mInputSurface, true);
t.setInputWindowInfo(mInputSurface, mWindowHandle);
t.setLayer(mInputSurface, InputManagerService.INPUT_OVERLAY_LAYER_GESTURE_MONITOR);
t.setPosition(mInputSurface, 0, 0);
diff --git a/services/core/java/com/android/server/input/InputManagerService.java b/services/core/java/com/android/server/input/InputManagerService.java
index 6b399de..2533e02 100644
--- a/services/core/java/com/android/server/input/InputManagerService.java
+++ b/services/core/java/com/android/server/input/InputManagerService.java
@@ -117,6 +117,7 @@
import com.android.server.LocalServices;
import com.android.server.Watchdog;
import com.android.server.input.InputManagerInternal.LidSwitchCallback;
+import com.android.server.input.debug.FocusEventDebugView;
import com.android.server.inputmethod.InputMethodManagerInternal;
import com.android.server.policy.WindowManagerPolicy;
diff --git a/services/core/java/com/android/server/input/FocusEventDebugGlobalMonitor.java b/services/core/java/com/android/server/input/debug/FocusEventDebugGlobalMonitor.java
similarity index 94%
rename from services/core/java/com/android/server/input/FocusEventDebugGlobalMonitor.java
rename to services/core/java/com/android/server/input/debug/FocusEventDebugGlobalMonitor.java
index 67c221f..2b21e49 100644
--- a/services/core/java/com/android/server/input/FocusEventDebugGlobalMonitor.java
+++ b/services/core/java/com/android/server/input/debug/FocusEventDebugGlobalMonitor.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package com.android.server.input;
+package com.android.server.input.debug;
import android.view.Display;
import android.view.InputEvent;
@@ -22,6 +22,7 @@
import android.view.MotionEvent;
import com.android.server.UiThread;
+import com.android.server.input.InputManagerService;
/**
* Receives input events before they are dispatched and reports them to FocusEventDebugView.
diff --git a/services/core/java/com/android/server/input/debug/FocusEventDebugView.java b/services/core/java/com/android/server/input/debug/FocusEventDebugView.java
new file mode 100644
index 0000000..6eec0de
--- /dev/null
+++ b/services/core/java/com/android/server/input/debug/FocusEventDebugView.java
@@ -0,0 +1,466 @@
+/*
+ * Copyright 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.input.debug;
+
+import static android.util.TypedValue.COMPLEX_UNIT_DIP;
+import static android.util.TypedValue.COMPLEX_UNIT_SP;
+import static android.view.ViewGroup.LayoutParams.WRAP_CONTENT;
+
+import android.animation.LayoutTransition;
+import android.annotation.AnyThread;
+import android.annotation.Nullable;
+import android.content.Context;
+import android.graphics.Color;
+import android.graphics.ColorFilter;
+import android.graphics.ColorMatrixColorFilter;
+import android.graphics.Typeface;
+import android.util.DisplayMetrics;
+import android.util.Pair;
+import android.util.Slog;
+import android.util.TypedValue;
+import android.view.Gravity;
+import android.view.InputDevice;
+import android.view.KeyEvent;
+import android.view.MotionEvent;
+import android.view.RoundedCorner;
+import android.view.View;
+import android.view.WindowInsets;
+import android.view.animation.AccelerateInterpolator;
+import android.widget.HorizontalScrollView;
+import android.widget.LinearLayout;
+import android.widget.RelativeLayout;
+import android.widget.TextView;
+
+import com.android.internal.R;
+import com.android.internal.annotations.VisibleForTesting;
+import com.android.server.input.InputManagerService;
+
+import java.util.HashMap;
+import java.util.Map;
+import java.util.function.Supplier;
+
+/**
+ * Displays focus events, such as physical keyboard KeyEvents and non-pointer MotionEvents on
+ * the screen.
+ */
+public class FocusEventDebugView extends RelativeLayout {
+
+ private static final String TAG = FocusEventDebugView.class.getSimpleName();
+
+ private static final int KEY_FADEOUT_DURATION_MILLIS = 1000;
+ private static final int KEY_TRANSITION_DURATION_MILLIS = 100;
+
+ private static final int OUTER_PADDING_DP = 16;
+ private static final int KEY_SEPARATION_MARGIN_DP = 16;
+ private static final int KEY_VIEW_SIDE_PADDING_DP = 16;
+ private static final int KEY_VIEW_VERTICAL_PADDING_DP = 8;
+ private static final int KEY_VIEW_MIN_WIDTH_DP = 32;
+ private static final int KEY_VIEW_TEXT_SIZE_SP = 12;
+ private static final double ROTATY_GRAPH_HEIGHT_FRACTION = 0.5;
+
+ private final InputManagerService mService;
+ private final int mOuterPadding;
+ private final DisplayMetrics mDm;
+
+ // Tracks all keys that are currently pressed/down.
+ private final Map<Pair<Integer /*deviceId*/, Integer /*scanCode*/>, PressedKeyView>
+ mPressedKeys = new HashMap<>();
+
+ @Nullable
+ private FocusEventDebugGlobalMonitor mFocusEventDebugGlobalMonitor;
+ @Nullable
+ private PressedKeyContainer mPressedKeyContainer;
+ @Nullable
+ private PressedKeyContainer mPressedModifierContainer;
+ private final Supplier<RotaryInputValueView> mRotaryInputValueViewFactory;
+ @Nullable
+ private RotaryInputValueView mRotaryInputValueView;
+ private final Supplier<RotaryInputGraphView> mRotaryInputGraphViewFactory;
+ @Nullable
+ private RotaryInputGraphView mRotaryInputGraphView;
+
+ @VisibleForTesting
+ FocusEventDebugView(Context c, InputManagerService service,
+ Supplier<RotaryInputValueView> rotaryInputValueViewFactory,
+ Supplier<RotaryInputGraphView> rotaryInputGraphViewFactory) {
+ super(c);
+ setFocusableInTouchMode(true);
+
+ mService = service;
+ mRotaryInputValueViewFactory = rotaryInputValueViewFactory;
+ mRotaryInputGraphViewFactory = rotaryInputGraphViewFactory;
+ mDm = mContext.getResources().getDisplayMetrics();
+ mOuterPadding = (int) TypedValue.applyDimension(COMPLEX_UNIT_DIP, OUTER_PADDING_DP, mDm);
+ }
+
+ public FocusEventDebugView(Context c, InputManagerService service) {
+ this(c, service, () -> new RotaryInputValueView(c), () -> new RotaryInputGraphView(c));
+ }
+
+ @Override
+ public WindowInsets onApplyWindowInsets(WindowInsets insets) {
+ int paddingBottom = 0;
+
+ final RoundedCorner bottomLeft =
+ insets.getRoundedCorner(RoundedCorner.POSITION_BOTTOM_LEFT);
+ if (bottomLeft != null && !insets.isRound()) {
+ paddingBottom = bottomLeft.getRadius();
+ }
+
+ final RoundedCorner bottomRight =
+ insets.getRoundedCorner(RoundedCorner.POSITION_BOTTOM_RIGHT);
+ if (bottomRight != null && !insets.isRound()) {
+ paddingBottom = Math.max(paddingBottom, bottomRight.getRadius());
+ }
+
+ if (insets.getDisplayCutout() != null) {
+ paddingBottom =
+ Math.max(paddingBottom, insets.getDisplayCutout().getSafeInsetBottom());
+ }
+
+ setPadding(mOuterPadding, mOuterPadding, mOuterPadding, mOuterPadding + paddingBottom);
+ setClipToPadding(false);
+ invalidate();
+ return super.onApplyWindowInsets(insets);
+ }
+
+ @Override
+ public boolean dispatchKeyEvent(KeyEvent event) {
+ handleKeyEvent(event);
+ return super.dispatchKeyEvent(event);
+ }
+
+ /** Determines whether to show the key presses visualization. */
+ @AnyThread
+ public void updateShowKeyPresses(boolean enabled) {
+ post(() -> handleUpdateShowKeyPresses(enabled));
+ }
+
+ /** Determines whether to show the rotary input visualization. */
+ @AnyThread
+ public void updateShowRotaryInput(boolean enabled) {
+ post(() -> handleUpdateShowRotaryInput(enabled));
+ }
+
+ private void handleUpdateShowKeyPresses(boolean enabled) {
+ if (enabled == showKeyPresses()) {
+ return;
+ }
+
+ if (!enabled) {
+ removeView(mPressedKeyContainer);
+ mPressedKeyContainer = null;
+ removeView(mPressedModifierContainer);
+ mPressedModifierContainer = null;
+ return;
+ }
+
+ mPressedKeyContainer = new PressedKeyContainer(mContext);
+ mPressedKeyContainer.setOrientation(LinearLayout.HORIZONTAL);
+ mPressedKeyContainer.setGravity(Gravity.RIGHT | Gravity.BOTTOM);
+ mPressedKeyContainer.setLayoutDirection(LAYOUT_DIRECTION_LTR);
+ final var scroller = new HorizontalScrollView(mContext);
+ scroller.addView(mPressedKeyContainer);
+ scroller.setHorizontalScrollBarEnabled(false);
+ scroller.addOnLayoutChangeListener(
+ (view, l, t, r, b, ol, ot, or, ob) -> scroller.fullScroll(View.FOCUS_RIGHT));
+ scroller.setHorizontalFadingEdgeEnabled(true);
+ LayoutParams scrollerLayoutParams = new LayoutParams(WRAP_CONTENT, WRAP_CONTENT);
+ scrollerLayoutParams.addRule(ALIGN_PARENT_BOTTOM);
+ scrollerLayoutParams.addRule(ALIGN_PARENT_RIGHT);
+ addView(scroller, scrollerLayoutParams);
+
+ mPressedModifierContainer = new PressedKeyContainer(mContext);
+ mPressedModifierContainer.setOrientation(LinearLayout.VERTICAL);
+ mPressedModifierContainer.setGravity(Gravity.LEFT | Gravity.BOTTOM);
+ LayoutParams modifierLayoutParams = new LayoutParams(WRAP_CONTENT, WRAP_CONTENT);
+ modifierLayoutParams.addRule(ALIGN_PARENT_BOTTOM);
+ modifierLayoutParams.addRule(ALIGN_PARENT_LEFT);
+ modifierLayoutParams.addRule(LEFT_OF, scroller.getId());
+ addView(mPressedModifierContainer, modifierLayoutParams);
+ }
+
+ @VisibleForTesting
+ void handleUpdateShowRotaryInput(boolean enabled) {
+ if (enabled == showRotaryInput()) {
+ return;
+ }
+
+ if (!enabled) {
+ mFocusEventDebugGlobalMonitor.dispose();
+ mFocusEventDebugGlobalMonitor = null;
+ removeView(mRotaryInputValueView);
+ mRotaryInputValueView = null;
+ removeView(mRotaryInputGraphView);
+ mRotaryInputGraphView = null;
+ return;
+ }
+
+ mFocusEventDebugGlobalMonitor = new FocusEventDebugGlobalMonitor(this, mService);
+
+ mRotaryInputValueView = mRotaryInputValueViewFactory.get();
+ LayoutParams valueLayoutParams = new LayoutParams(WRAP_CONTENT, WRAP_CONTENT);
+ valueLayoutParams.addRule(CENTER_HORIZONTAL);
+ valueLayoutParams.addRule(ALIGN_PARENT_BOTTOM);
+ addView(mRotaryInputValueView, valueLayoutParams);
+
+ mRotaryInputGraphView = mRotaryInputGraphViewFactory.get();
+ LayoutParams graphLayoutParams = new LayoutParams(LayoutParams.MATCH_PARENT,
+ (int) (ROTATY_GRAPH_HEIGHT_FRACTION * mDm.heightPixels));
+ graphLayoutParams.addRule(CENTER_IN_PARENT);
+ addView(mRotaryInputGraphView, graphLayoutParams);
+ }
+
+ /** Report a key event to the debug view. */
+ @AnyThread
+ public void reportKeyEvent(KeyEvent event) {
+ post(() -> handleKeyEvent(KeyEvent.obtain((KeyEvent) event)));
+ }
+
+ /** Report a motion event to the debug view. */
+ @AnyThread
+ public void reportMotionEvent(MotionEvent event) {
+ if (event.getSource() != InputDevice.SOURCE_ROTARY_ENCODER) {
+ return;
+ }
+
+ post(() -> handleRotaryInput(MotionEvent.obtain((MotionEvent) event)));
+ }
+
+ private void handleKeyEvent(KeyEvent keyEvent) {
+ if (!showKeyPresses()) {
+ return;
+ }
+
+ final var identifier = new Pair<>(keyEvent.getDeviceId(), keyEvent.getScanCode());
+ final var container = KeyEvent.isModifierKey(keyEvent.getKeyCode())
+ ? mPressedModifierContainer
+ : mPressedKeyContainer;
+ PressedKeyView pressedKeyView = mPressedKeys.get(identifier);
+ switch (keyEvent.getAction()) {
+ case KeyEvent.ACTION_DOWN: {
+ if (pressedKeyView != null) {
+ if (keyEvent.getRepeatCount() == 0) {
+ Slog.w(TAG, "Got key down for "
+ + KeyEvent.keyCodeToString(keyEvent.getKeyCode())
+ + " that was already tracked as being down.");
+ break;
+ }
+ container.handleKeyRepeat(pressedKeyView);
+ break;
+ }
+
+ pressedKeyView = new PressedKeyView(mContext, getLabel(keyEvent));
+ mPressedKeys.put(identifier, pressedKeyView);
+ container.handleKeyPressed(pressedKeyView);
+ break;
+ }
+ case KeyEvent.ACTION_UP: {
+ if (pressedKeyView == null) {
+ Slog.w(TAG, "Got key up for " + KeyEvent.keyCodeToString(keyEvent.getKeyCode())
+ + " that was not tracked as being down.");
+ break;
+ }
+ mPressedKeys.remove(identifier);
+ container.handleKeyRelease(pressedKeyView);
+ break;
+ }
+ default:
+ break;
+ }
+ keyEvent.recycle();
+ }
+
+ @VisibleForTesting
+ void handleRotaryInput(MotionEvent motionEvent) {
+ if (!showRotaryInput()) {
+ return;
+ }
+
+ float scrollAxisValue = motionEvent.getAxisValue(MotionEvent.AXIS_SCROLL);
+ mRotaryInputValueView.updateValue(scrollAxisValue);
+ mRotaryInputGraphView.addValue(scrollAxisValue, motionEvent.getEventTime());
+
+ motionEvent.recycle();
+ }
+
+ private static String getLabel(KeyEvent event) {
+ switch (event.getKeyCode()) {
+ case KeyEvent.KEYCODE_SPACE:
+ return "\u2423";
+ case KeyEvent.KEYCODE_TAB:
+ return "\u21e5";
+ case KeyEvent.KEYCODE_ENTER:
+ case KeyEvent.KEYCODE_NUMPAD_ENTER:
+ return "\u23CE";
+ case KeyEvent.KEYCODE_DEL:
+ return "\u232B";
+ case KeyEvent.KEYCODE_FORWARD_DEL:
+ return "\u2326";
+ case KeyEvent.KEYCODE_ESCAPE:
+ return "ESC";
+ case KeyEvent.KEYCODE_DPAD_UP:
+ return "\u2191";
+ case KeyEvent.KEYCODE_DPAD_DOWN:
+ return "\u2193";
+ case KeyEvent.KEYCODE_DPAD_LEFT:
+ return "\u2190";
+ case KeyEvent.KEYCODE_DPAD_RIGHT:
+ return "\u2192";
+ case KeyEvent.KEYCODE_DPAD_UP_RIGHT:
+ return "\u2197";
+ case KeyEvent.KEYCODE_DPAD_UP_LEFT:
+ return "\u2196";
+ case KeyEvent.KEYCODE_DPAD_DOWN_RIGHT:
+ return "\u2198";
+ case KeyEvent.KEYCODE_DPAD_DOWN_LEFT:
+ return "\u2199";
+ default:
+ break;
+ }
+
+ final int unicodeChar = event.getUnicodeChar();
+ if (unicodeChar != 0) {
+ return new String(Character.toChars(unicodeChar));
+ }
+
+ final var label = KeyEvent.keyCodeToString(event.getKeyCode());
+ if (label.startsWith("KEYCODE_")) {
+ return label.substring(8);
+ }
+ return label;
+ }
+
+ /** Determine whether to show key presses by checking one of the key-related objects. */
+ private boolean showKeyPresses() {
+ return mPressedKeyContainer != null;
+ }
+
+ /** Determine whether to show rotary input by checking one of the rotary-related objects. */
+ private boolean showRotaryInput() {
+ return mRotaryInputValueView != null;
+ }
+
+ private static class PressedKeyView extends TextView {
+
+ private static final ColorFilter sInvertColors = new ColorMatrixColorFilter(new float[]{
+ -1.0f, 0, 0, 0, 255, // red
+ 0, -1.0f, 0, 0, 255, // green
+ 0, 0, -1.0f, 0, 255, // blue
+ 0, 0, 0, 1.0f, 0 // alpha
+ });
+
+ PressedKeyView(Context c, String label) {
+ super(c);
+
+ final var dm = c.getResources().getDisplayMetrics();
+ final int keyViewSidePadding =
+ (int) TypedValue.applyDimension(COMPLEX_UNIT_DIP, KEY_VIEW_SIDE_PADDING_DP, dm);
+ final int keyViewVerticalPadding =
+ (int) TypedValue.applyDimension(COMPLEX_UNIT_DIP, KEY_VIEW_VERTICAL_PADDING_DP,
+ dm);
+ final int keyViewMinWidth =
+ (int) TypedValue.applyDimension(COMPLEX_UNIT_DIP, KEY_VIEW_MIN_WIDTH_DP, dm);
+ final int textSize =
+ (int) TypedValue.applyDimension(COMPLEX_UNIT_SP, KEY_VIEW_TEXT_SIZE_SP, dm);
+
+ setText(label);
+ setGravity(Gravity.CENTER);
+ setMinimumWidth(keyViewMinWidth);
+ setTextSize(textSize);
+ setTypeface(Typeface.SANS_SERIF);
+ setBackgroundResource(R.drawable.focus_event_pressed_key_background);
+ setPaddingRelative(keyViewSidePadding, keyViewVerticalPadding, keyViewSidePadding,
+ keyViewVerticalPadding);
+
+ setHighlighted(true);
+ }
+
+ void setHighlighted(boolean isHighlighted) {
+ if (isHighlighted) {
+ setTextColor(Color.BLACK);
+ getBackground().setColorFilter(sInvertColors);
+ } else {
+ setTextColor(Color.WHITE);
+ getBackground().clearColorFilter();
+ }
+ invalidate();
+ }
+ }
+
+ private static class PressedKeyContainer extends LinearLayout {
+
+ private final MarginLayoutParams mPressedKeyLayoutParams;
+
+ PressedKeyContainer(Context c) {
+ super(c);
+
+ final var dm = c.getResources().getDisplayMetrics();
+ final int keySeparationMargin =
+ (int) TypedValue.applyDimension(COMPLEX_UNIT_DIP, KEY_SEPARATION_MARGIN_DP, dm);
+
+ final var transition = new LayoutTransition();
+ transition.disableTransitionType(LayoutTransition.APPEARING);
+ transition.disableTransitionType(LayoutTransition.DISAPPEARING);
+ transition.disableTransitionType(LayoutTransition.CHANGE_DISAPPEARING);
+ transition.setDuration(KEY_TRANSITION_DURATION_MILLIS);
+ setLayoutTransition(transition);
+
+ mPressedKeyLayoutParams = new MarginLayoutParams(WRAP_CONTENT, WRAP_CONTENT);
+ if (getOrientation() == VERTICAL) {
+ mPressedKeyLayoutParams.setMargins(0, keySeparationMargin, 0, 0);
+ } else {
+ mPressedKeyLayoutParams.setMargins(keySeparationMargin, 0, 0, 0);
+ }
+ }
+
+ public void handleKeyPressed(PressedKeyView pressedKeyView) {
+ addView(pressedKeyView, getChildCount(), mPressedKeyLayoutParams);
+ invalidate();
+ }
+
+ public void handleKeyRepeat(PressedKeyView repeatedKeyView) {
+ // Do nothing for now.
+ }
+
+ public void handleKeyRelease(PressedKeyView releasedKeyView) {
+ releasedKeyView.setHighlighted(false);
+ releasedKeyView.clearAnimation();
+ releasedKeyView.animate()
+ .alpha(0)
+ .setDuration(KEY_FADEOUT_DURATION_MILLIS)
+ .setInterpolator(new AccelerateInterpolator())
+ .withEndAction(this::cleanUpPressedKeyViews)
+ .start();
+ }
+
+ private void cleanUpPressedKeyViews() {
+ int numChildrenToRemove = 0;
+ for (int i = 0; i < getChildCount(); i++) {
+ final View child = getChildAt(i);
+ if (child.getAlpha() != 0) {
+ break;
+ }
+ child.setVisibility(View.GONE);
+ child.clearAnimation();
+ numChildrenToRemove++;
+ }
+ removeViews(0, numChildrenToRemove);
+ invalidate();
+ }
+ }
+}
diff --git a/services/core/java/com/android/server/input/debug/RotaryInputGraphView.java b/services/core/java/com/android/server/input/debug/RotaryInputGraphView.java
new file mode 100644
index 0000000..95635d9
--- /dev/null
+++ b/services/core/java/com/android/server/input/debug/RotaryInputGraphView.java
@@ -0,0 +1,342 @@
+/*
+ * Copyright 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.input.debug;
+
+import static android.util.TypedValue.COMPLEX_UNIT_SP;
+
+import android.content.Context;
+import android.graphics.Canvas;
+import android.graphics.Paint;
+import android.util.DisplayMetrics;
+import android.util.TypedValue;
+import android.view.View;
+import android.view.ViewConfiguration;
+
+import java.util.Iterator;
+import java.util.Locale;
+import java.util.concurrent.TimeUnit;
+
+/**
+ * Shows a graph with the rotary input values as a function of time.
+ * The graph gets reset if no action is received for a certain amount of time.
+ */
+public class RotaryInputGraphView extends View {
+
+ private static final int FRAME_COLOR = 0xbf741b47;
+ private static final int FRAME_WIDTH_SP = 2;
+ private static final int FRAME_BORDER_GAP_SP = 10;
+ private static final int FRAME_TEXT_SIZE_SP = 10;
+ private static final int FRAME_TEXT_OFFSET_SP = 2;
+ private static final int GRAPH_COLOR = 0xffff00ff;
+ private static final int GRAPH_LINE_WIDTH_SP = 1;
+ private static final int GRAPH_POINT_RADIUS_SP = 4;
+ private static final long MAX_SHOWN_TIME_INTERVAL = TimeUnit.SECONDS.toMillis(5);
+ private static final float DEFAULT_FRAME_CENTER_POSITION = 0;
+ private static final int MAX_GRAPH_VALUES_SIZE = 400;
+ /** Maximum time between values so that they are considered part of the same gesture. */
+ private static final long MAX_GESTURE_TIME = TimeUnit.SECONDS.toMillis(1);
+
+ private final DisplayMetrics mDm;
+ /**
+ * Distance in position units (amount scrolled in display pixels) from the center to the
+ * top/bottom frame lines.
+ */
+ private final float mFrameCenterToBorderDistance;
+ private final float mScaledVerticalScrollFactor;
+ private final Locale mDefaultLocale = Locale.getDefault();
+ private final Paint mFramePaint = new Paint();
+ private final Paint mFrameTextPaint = new Paint();
+ private final Paint mGraphLinePaint = new Paint();
+ private final Paint mGraphPointPaint = new Paint();
+
+ private final CyclicBuffer mGraphValues = new CyclicBuffer(MAX_GRAPH_VALUES_SIZE);
+ /** Position at which graph values are placed at the center of the graph. */
+ private float mFrameCenterPosition = DEFAULT_FRAME_CENTER_POSITION;
+
+ public RotaryInputGraphView(Context c) {
+ super(c);
+
+ mDm = mContext.getResources().getDisplayMetrics();
+ // This makes the center-to-border distance equivalent to the display height, meaning
+ // that the total height of the graph is equivalent to 2x the display height.
+ mFrameCenterToBorderDistance = mDm.heightPixels;
+ mScaledVerticalScrollFactor = ViewConfiguration.get(c).getScaledVerticalScrollFactor();
+
+ mFramePaint.setColor(FRAME_COLOR);
+ mFramePaint.setStrokeWidth(applyDimensionSp(FRAME_WIDTH_SP, mDm));
+
+ mFrameTextPaint.setColor(GRAPH_COLOR);
+ mFrameTextPaint.setTextSize(applyDimensionSp(FRAME_TEXT_SIZE_SP, mDm));
+
+ mGraphLinePaint.setColor(GRAPH_COLOR);
+ mGraphLinePaint.setStrokeWidth(applyDimensionSp(GRAPH_LINE_WIDTH_SP, mDm));
+ mGraphLinePaint.setStrokeCap(Paint.Cap.ROUND);
+ mGraphLinePaint.setStrokeJoin(Paint.Join.ROUND);
+
+ mGraphPointPaint.setColor(GRAPH_COLOR);
+ mGraphPointPaint.setStrokeWidth(applyDimensionSp(GRAPH_POINT_RADIUS_SP, mDm));
+ mGraphPointPaint.setStrokeCap(Paint.Cap.ROUND);
+ mGraphPointPaint.setStrokeJoin(Paint.Join.ROUND);
+ }
+
+ /**
+ * Reads new scroll axis value and updates the list accordingly. Old positions are
+ * kept at the front (what you would get with getFirst), while the recent positions are
+ * kept at the back (what you would get with getLast). Also updates the frame center
+ * position to handle out-of-bounds cases.
+ */
+ public void addValue(float scrollAxisValue, long eventTime) {
+ // Remove values that are too old.
+ while (mGraphValues.getSize() > 0
+ && (eventTime - mGraphValues.getFirst().mTime) > MAX_SHOWN_TIME_INTERVAL) {
+ mGraphValues.removeFirst();
+ }
+
+ // If there are no recent values, reset the frame center.
+ if (mGraphValues.getSize() == 0) {
+ mFrameCenterPosition = DEFAULT_FRAME_CENTER_POSITION;
+ }
+
+ // Handle new value. We multiply the scroll axis value by the scaled scroll factor to
+ // get the amount of pixels to be scrolled. We also compute the accumulated position
+ // by adding the current value to the last one (if not empty).
+ final float displacement = scrollAxisValue * mScaledVerticalScrollFactor;
+ final float prevPos = (mGraphValues.getSize() == 0 ? 0 : mGraphValues.getLast().mPos);
+ final float pos = prevPos + displacement;
+
+ mGraphValues.add(pos, eventTime);
+
+ // The difference between the distance of the most recent position from the center
+ // frame (pos - mFrameCenterPosition) and the maximum allowed distance from the center
+ // frame (mFrameCenterToBorderDistance).
+ final float verticalDiff = Math.abs(pos - mFrameCenterPosition)
+ - mFrameCenterToBorderDistance;
+ // If needed, translate frame.
+ if (verticalDiff > 0) {
+ final int sign = pos - mFrameCenterPosition < 0 ? -1 : 1;
+ // Here, we update the center frame position by the exact amount needed for us to
+ // stay within the maximum allowed distance from the center frame.
+ mFrameCenterPosition += sign * verticalDiff;
+ }
+
+ // Redraw canvas.
+ invalidate();
+ }
+
+ @Override
+ protected void onDraw(Canvas canvas) {
+ super.onDraw(canvas);
+
+ // Note: vertical coordinates in Canvas go from top to bottom,
+ // that is bottomY > middleY > topY.
+ final int verticalMargin = applyDimensionSp(FRAME_BORDER_GAP_SP, mDm);
+ final int topY = verticalMargin;
+ final int bottomY = getHeight() - verticalMargin;
+ final int middleY = (topY + bottomY) / 2;
+
+ // Note: horizontal coordinates in Canvas go from left to right,
+ // that is rightX > leftX.
+ final int leftX = 0;
+ final int rightX = getWidth();
+
+ // Draw the frame, which includes 3 lines that show the maximum,
+ // minimum and middle positions of the graph.
+ canvas.drawLine(leftX, topY, rightX, topY, mFramePaint);
+ canvas.drawLine(leftX, middleY, rightX, middleY, mFramePaint);
+ canvas.drawLine(leftX, bottomY, rightX, bottomY, mFramePaint);
+
+ // Draw the position that each frame line corresponds to.
+ final int frameTextOffset = applyDimensionSp(FRAME_TEXT_OFFSET_SP, mDm);
+ canvas.drawText(
+ String.format(mDefaultLocale, "%.1f",
+ mFrameCenterPosition + mFrameCenterToBorderDistance),
+ leftX,
+ topY - frameTextOffset, mFrameTextPaint
+ );
+ canvas.drawText(
+ String.format(mDefaultLocale, "%.1f", mFrameCenterPosition),
+ leftX,
+ middleY - frameTextOffset, mFrameTextPaint
+ );
+ canvas.drawText(
+ String.format(mDefaultLocale, "%.1f",
+ mFrameCenterPosition - mFrameCenterToBorderDistance),
+ leftX,
+ bottomY - frameTextOffset, mFrameTextPaint
+ );
+
+ // If there are no graph values to be drawn, stop here.
+ if (mGraphValues.getSize() == 0) {
+ return;
+ }
+
+ // Draw the graph using the times and positions.
+ // We start at the most recent value (which should be drawn at the right) and move
+ // to the older values (which should be drawn to the left of more recent ones). Negative
+ // indices are handled by circuling back to the end of the buffer.
+ final long mostRecentTime = mGraphValues.getLast().mTime;
+ float prevCoordX = 0;
+ float prevCoordY = 0;
+ float prevAge = 0;
+ for (Iterator<GraphValue> iter = mGraphValues.reverseIterator(); iter.hasNext();) {
+ final GraphValue value = iter.next();
+
+ final int age = (int) (mostRecentTime - value.mTime);
+ final float pos = value.mPos;
+
+ // We get the horizontal coordinate in time units from left to right with
+ // (MAX_SHOWN_TIME_INTERVAL - age). Then, we rescale it to match the canvas
+ // units by dividing it by the time-domain length (MAX_SHOWN_TIME_INTERVAL)
+ // and by multiplying it by the canvas length (rightX - leftX). Finally, we
+ // offset the coordinate by adding it to leftX.
+ final float coordX = leftX + ((float) (MAX_SHOWN_TIME_INTERVAL - age)
+ / MAX_SHOWN_TIME_INTERVAL) * (rightX - leftX);
+
+ // We get the vertical coordinate in position units from middle to top with
+ // (pos - mFrameCenterPosition). Then, we rescale it to match the canvas
+ // units by dividing it by half of the position-domain length
+ // (mFrameCenterToBorderDistance) and by multiplying it by half of the canvas
+ // length (middleY - topY). Finally, we offset the coordinate by subtracting
+ // it from middleY (we can't "add" here because the coordinate grows from top
+ // to bottom).
+ final float coordY = middleY - ((pos - mFrameCenterPosition)
+ / mFrameCenterToBorderDistance) * (middleY - topY);
+
+ // Draw a point for this value.
+ canvas.drawPoint(coordX, coordY, mGraphPointPaint);
+
+ // If this value is part of the same gesture as the previous one, draw a line
+ // between them. We ignore the first value (with age = 0).
+ if (age != 0 && (age - prevAge) <= MAX_GESTURE_TIME) {
+ canvas.drawLine(prevCoordX, prevCoordY, coordX, coordY, mGraphLinePaint);
+ }
+
+ prevCoordX = coordX;
+ prevCoordY = coordY;
+ prevAge = age;
+ }
+ }
+
+ public float getFrameCenterPosition() {
+ return mFrameCenterPosition;
+ }
+
+ /**
+ * Converts a dimension in scaled pixel units to integer display pixels.
+ */
+ private static int applyDimensionSp(int dimensionSp, DisplayMetrics dm) {
+ return (int) TypedValue.applyDimension(COMPLEX_UNIT_SP, dimensionSp, dm);
+ }
+
+ /**
+ * Holds data needed to draw each entry in the graph.
+ */
+ private static class GraphValue {
+ /** Position. */
+ float mPos;
+ /** Time when this value was added. */
+ long mTime;
+
+ GraphValue(float pos, long time) {
+ this.mPos = pos;
+ this.mTime = time;
+ }
+ }
+
+ /**
+ * Holds the graph values as a cyclic buffer. It has a fixed capacity, and it replaces the
+ * old values with new ones to avoid creating new objects.
+ */
+ private static class CyclicBuffer {
+ private final GraphValue[] mValues;
+ private final int mCapacity;
+ private int mSize = 0;
+ private int mLastIndex = 0;
+
+ // The iteration index and counter are here to make it easier to reset them.
+ /** Determines the value currently pointed by the iterator. */
+ private int mIteratorIndex;
+ /** Counts how many values have been iterated through. */
+ private int mIteratorCount;
+
+ /** Used traverse the values in reverse order. */
+ private final Iterator<GraphValue> mReverseIterator = new Iterator<GraphValue>() {
+ @Override
+ public boolean hasNext() {
+ return mIteratorCount <= mSize;
+ }
+
+ @Override
+ public GraphValue next() {
+ // Returns the value currently pointed by the iterator and moves the iterator to
+ // the previous one.
+ mIteratorCount++;
+ return mValues[(mIteratorIndex-- + mCapacity) % mCapacity];
+ }
+ };
+
+ CyclicBuffer(int capacity) {
+ mCapacity = capacity;
+ mValues = new GraphValue[capacity];
+ }
+
+ /**
+ * Add new graph value. If there is an existing object, we replace its data with the
+ * new one. With this, we re-use old objects instead of creating new ones.
+ */
+ void add(float pos, long time) {
+ mLastIndex = (mLastIndex + 1) % mCapacity;
+ if (mValues[mLastIndex] == null) {
+ mValues[mLastIndex] = new GraphValue(pos, time);
+ } else {
+ final GraphValue oldValue = mValues[mLastIndex];
+ oldValue.mPos = pos;
+ oldValue.mTime = time;
+ }
+
+ // If needed, account for new value in the buffer size.
+ if (mSize != mCapacity) {
+ mSize++;
+ }
+ }
+
+ int getSize() {
+ return mSize;
+ }
+
+ GraphValue getFirst() {
+ final int distanceBetweenLastAndFirst = (mCapacity - mSize) + 1;
+ final int firstIndex = (mLastIndex + distanceBetweenLastAndFirst) % mCapacity;
+ return mValues[firstIndex];
+ }
+
+ GraphValue getLast() {
+ return mValues[mLastIndex];
+ }
+
+ void removeFirst() {
+ mSize--;
+ }
+
+ /** Returns an iterator pointing at the last value. */
+ Iterator<GraphValue> reverseIterator() {
+ mIteratorIndex = mLastIndex;
+ mIteratorCount = 1;
+ return mReverseIterator;
+ }
+ }
+}
diff --git a/services/core/java/com/android/server/input/debug/RotaryInputValueView.java b/services/core/java/com/android/server/input/debug/RotaryInputValueView.java
new file mode 100644
index 0000000..9fadac5
--- /dev/null
+++ b/services/core/java/com/android/server/input/debug/RotaryInputValueView.java
@@ -0,0 +1,103 @@
+/*
+ * Copyright 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.input.debug;
+
+import static android.util.TypedValue.COMPLEX_UNIT_SP;
+
+import android.content.Context;
+import android.graphics.ColorFilter;
+import android.graphics.ColorMatrixColorFilter;
+import android.graphics.Typeface;
+import android.util.DisplayMetrics;
+import android.util.TypedValue;
+import android.view.ViewConfiguration;
+import android.widget.TextView;
+
+import com.android.internal.R;
+
+import java.util.Locale;
+
+/**
+ * Draws the most recent rotary input value and indicates whether the source is active.
+ */
+public class RotaryInputValueView extends TextView {
+
+ private static final int INACTIVE_TEXT_COLOR = 0xffff00ff;
+ private static final int ACTIVE_TEXT_COLOR = 0xff420f28;
+ private static final int TEXT_SIZE_SP = 8;
+ private static final int SIDE_PADDING_SP = 4;
+ /** Determines how long the active status lasts. */
+ private static final int ACTIVE_STATUS_DURATION = 250 /* milliseconds */;
+ private static final ColorFilter ACTIVE_BACKGROUND_FILTER =
+ new ColorMatrixColorFilter(new float[]{
+ 0, 0, 0, 0, 255, // red
+ 0, 0, 0, 0, 0, // green
+ 0, 0, 0, 0, 255, // blue
+ 0, 0, 0, 0, 200 // alpha
+ });
+
+ private final Runnable mUpdateActivityStatusCallback = () -> updateActivityStatus(false);
+ private final float mScaledVerticalScrollFactor;
+ private final Locale mDefaultLocale = Locale.getDefault();
+
+ public RotaryInputValueView(Context c) {
+ super(c);
+
+ DisplayMetrics dm = mContext.getResources().getDisplayMetrics();
+ mScaledVerticalScrollFactor = ViewConfiguration.get(c).getScaledVerticalScrollFactor();
+
+ setText(getFormattedValue(0));
+ setTextColor(INACTIVE_TEXT_COLOR);
+ setTextSize(applyDimensionSp(TEXT_SIZE_SP, dm));
+ setPaddingRelative(applyDimensionSp(SIDE_PADDING_SP, dm), 0,
+ applyDimensionSp(SIDE_PADDING_SP, dm), 0);
+ setTypeface(null, Typeface.BOLD);
+ setBackgroundResource(R.drawable.focus_event_rotary_input_background);
+ }
+
+ /** Updates the shown text with the formatted value. */
+ public void updateValue(float value) {
+ removeCallbacks(mUpdateActivityStatusCallback);
+
+ setText(getFormattedValue(value * mScaledVerticalScrollFactor));
+
+ updateActivityStatus(true);
+ postDelayed(mUpdateActivityStatusCallback, ACTIVE_STATUS_DURATION);
+ }
+
+ /** Updates whether or not there's active rotary input. */
+ public void updateActivityStatus(boolean active) {
+ if (active) {
+ setTextColor(ACTIVE_TEXT_COLOR);
+ getBackground().setColorFilter(ACTIVE_BACKGROUND_FILTER);
+ } else {
+ setTextColor(INACTIVE_TEXT_COLOR);
+ getBackground().clearColorFilter();
+ }
+ }
+
+ private String getFormattedValue(float value) {
+ return String.format(mDefaultLocale, "%s%.1f", value < 0 ? "-" : "+", Math.abs(value));
+ }
+
+ /**
+ * Converts a dimension in scaled pixel units to integer display pixels.
+ */
+ private static int applyDimensionSp(int dimensionSp, DisplayMetrics dm) {
+ return (int) TypedValue.applyDimension(COMPLEX_UNIT_SP, dimensionSp, dm);
+ }
+}
diff --git a/services/core/java/com/android/server/inputmethod/HandwritingEventReceiverSurface.java b/services/core/java/com/android/server/inputmethod/HandwritingEventReceiverSurface.java
index 7726f40..dbbbed3 100644
--- a/services/core/java/com/android/server/inputmethod/HandwritingEventReceiverSurface.java
+++ b/services/core/java/com/android/server/inputmethod/HandwritingEventReceiverSurface.java
@@ -57,13 +57,13 @@
InputConfig.NOT_FOCUSABLE
| InputConfig.NOT_TOUCHABLE
| InputConfig.SPY
- | InputConfig.INTERCEPTS_STYLUS
- | InputConfig.TRUSTED_OVERLAY;
+ | InputConfig.INTERCEPTS_STYLUS;
// Configure the surface to receive stylus events across the entire display.
mWindowHandle.replaceTouchableRegionWithCrop(null /* use this surface's bounds */);
final SurfaceControl.Transaction t = new SurfaceControl.Transaction();
+ mWindowHandle.setTrustedOverlay(t, mInputSurface, true);
t.setInputWindowInfo(mInputSurface, mWindowHandle);
t.setLayer(mInputSurface, InputManagerService.INPUT_OVERLAY_LAYER_HANDWRITING_SURFACE);
t.setPosition(mInputSurface, 0, 0);
diff --git a/services/core/java/com/android/server/location/contexthub/ContextHubService.java b/services/core/java/com/android/server/location/contexthub/ContextHubService.java
index 93c66a1..08cf3f7 100644
--- a/services/core/java/com/android/server/location/contexthub/ContextHubService.java
+++ b/services/core/java/com/android/server/location/contexthub/ContextHubService.java
@@ -1431,13 +1431,17 @@
mContextHubWrapper.onBtMainSettingChanged(btEnabled);
}
} else {
- Log.d(TAG, "BT adapter not available. Defaulting to disabled");
- if (forceUpdate || mIsBtMainEnabled) {
- mIsBtMainEnabled = false;
+ Log.d(TAG, "BT adapter not available. Getting permissions from user settings");
+ boolean btEnabled = Settings.Global.getInt(mContext.getContentResolver(),
+ Settings.Global.BLUETOOTH_ON, 0) == 1;
+ boolean btScanEnabled = Settings.Global.getInt(mContext.getContentResolver(),
+ Settings.Global.BLE_SCAN_ALWAYS_AVAILABLE, 0) == 1;
+ if (forceUpdate || mIsBtMainEnabled != btEnabled) {
+ mIsBtMainEnabled = btEnabled;
mContextHubWrapper.onBtMainSettingChanged(mIsBtMainEnabled);
}
- if (forceUpdate || mIsBtScanningEnabled) {
- mIsBtScanningEnabled = false;
+ if (forceUpdate || mIsBtScanningEnabled != btScanEnabled) {
+ mIsBtScanningEnabled = btScanEnabled;
mContextHubWrapper.onBtScanningSettingChanged(mIsBtScanningEnabled);
}
}
diff --git a/services/core/java/com/android/server/notification/NotificationBitmapJobService.java b/services/core/java/com/android/server/notification/NotificationBitmapJobService.java
index 4335a1d..e1a0707 100644
--- a/services/core/java/com/android/server/notification/NotificationBitmapJobService.java
+++ b/services/core/java/com/android/server/notification/NotificationBitmapJobService.java
@@ -29,7 +29,12 @@
import com.android.internal.annotations.VisibleForTesting;
import com.android.server.LocalServices;
-import java.util.Calendar;
+import java.time.Duration;
+import java.time.Instant;
+import java.time.LocalDate;
+import java.time.LocalTime;
+import java.time.ZonedDateTime;
+import java.time.ZoneId;
/**
* This service runs everyday at 2am local time to remove expired bitmaps.
@@ -69,26 +74,25 @@
* @return Milliseconds until the next time the job should run.
*/
private static long getRunAfterMs() {
- Calendar cal = Calendar.getInstance(); // Uses local time zone
- final long now = cal.getTimeInMillis();
+ ZoneId zoneId = ZoneId.systemDefault();
+ ZonedDateTime now = Instant.now().atZone(zoneId);
- cal.set(Calendar.HOUR_OF_DAY, 2);
- cal.set(Calendar.MINUTE, 0);
- cal.set(Calendar.MILLISECOND, 0);
- final long today2AM = cal.getTimeInMillis();
+ LocalDate today = now.toLocalDate();
+ LocalTime twoAM = LocalTime.of(/* hour= */ 2, /* minute= */ 0);
- cal.add(Calendar.DAY_OF_YEAR, 1);
- final long tomorrow2AM = cal.getTimeInMillis();
+ ZonedDateTime today2AM = ZonedDateTime.of(today, twoAM, zoneId);
+ ZonedDateTime tomorrow2AM = today2AM.plusDays(1);
return getTimeUntilRemoval(now, today2AM, tomorrow2AM);
}
@VisibleForTesting
- static long getTimeUntilRemoval(long now, long today2AM, long tomorrow2AM) {
- if (now < today2AM) {
- return today2AM - now;
+ static long getTimeUntilRemoval(ZonedDateTime now, ZonedDateTime today2AM,
+ ZonedDateTime tomorrow2AM) {
+ if (Duration.between(now, today2AM).isNegative()) {
+ return Duration.between(now, tomorrow2AM).toMillis();
}
- return tomorrow2AM - now;
+ return Duration.between(now, today2AM).toMillis();
}
@Override
diff --git a/services/core/java/com/android/server/notification/NotificationHistoryJobService.java b/services/core/java/com/android/server/notification/NotificationHistoryJobService.java
index 3776ad7..c9317d1 100644
--- a/services/core/java/com/android/server/notification/NotificationHistoryJobService.java
+++ b/services/core/java/com/android/server/notification/NotificationHistoryJobService.java
@@ -27,6 +27,7 @@
import android.os.CancellationSignal;
import android.util.Slog;
+import com.android.internal.annotations.VisibleForTesting;
import com.android.server.LocalServices;
import java.util.concurrent.TimeUnit;
@@ -77,5 +78,11 @@
}
return false;
}
+
+ @Override
+ @VisibleForTesting
+ protected void attachBaseContext(Context base) {
+ super.attachBaseContext(base);
+ }
}
diff --git a/services/core/java/com/android/server/notification/NotificationManagerService.java b/services/core/java/com/android/server/notification/NotificationManagerService.java
index db69d93..87c3067 100755
--- a/services/core/java/com/android/server/notification/NotificationManagerService.java
+++ b/services/core/java/com/android/server/notification/NotificationManagerService.java
@@ -396,7 +396,7 @@
static final int MESSAGE_FINISH_TOKEN_TIMEOUT = 7;
static final int MESSAGE_ON_PACKAGE_CHANGED = 8;
- static final long BITMAP_EXPIRATION_TIME_MS = TimeUnit.HOURS.toMillis(24);
+ static final Duration BITMAP_DURATION = Duration.ofHours(24);
// ranking thread messages
private static final int MESSAGE_RECONSIDER_RANKING = 1000;
@@ -6705,7 +6705,7 @@
final long timePostedMs = r.getSbn().getPostTime();
final long timeNowMs = System.currentTimeMillis();
- if (isBitmapExpired(timePostedMs, timeNowMs, BITMAP_EXPIRATION_TIME_MS)) {
+ if (isBitmapExpired(timePostedMs, timeNowMs, BITMAP_DURATION.toMillis())) {
removeBitmapAndRepost(r);
}
}
diff --git a/services/core/java/com/android/server/pm/UserManagerService.java b/services/core/java/com/android/server/pm/UserManagerService.java
index 82d3e91..68a8e40 100644
--- a/services/core/java/com/android/server/pm/UserManagerService.java
+++ b/services/core/java/com/android/server/pm/UserManagerService.java
@@ -286,6 +286,8 @@
private static final int USER_VERSION = 11;
+ private static final int MAX_USER_STRING_LENGTH = 500;
+
private static final long EPOCH_PLUS_30_YEARS = 30L * 365 * 24 * 60 * 60 * 1000L; // ms
static final int WRITE_USER_MSG = 1;
@@ -4374,15 +4376,17 @@
// Write seed data
if (userData.persistSeedData) {
if (userData.seedAccountName != null) {
- serializer.attribute(null, ATTR_SEED_ACCOUNT_NAME, userData.seedAccountName);
+ serializer.attribute(null, ATTR_SEED_ACCOUNT_NAME,
+ truncateString(userData.seedAccountName));
}
if (userData.seedAccountType != null) {
- serializer.attribute(null, ATTR_SEED_ACCOUNT_TYPE, userData.seedAccountType);
+ serializer.attribute(null, ATTR_SEED_ACCOUNT_TYPE,
+ truncateString(userData.seedAccountType));
}
}
if (userInfo.name != null) {
serializer.startTag(null, TAG_NAME);
- serializer.text(userInfo.name);
+ serializer.text(truncateString(userInfo.name));
serializer.endTag(null, TAG_NAME);
}
synchronized (mRestrictionsLock) {
@@ -4431,6 +4435,13 @@
serializer.endDocument();
}
+ private String truncateString(String original) {
+ if (original == null || original.length() <= MAX_USER_STRING_LENGTH) {
+ return original;
+ }
+ return original.substring(0, MAX_USER_STRING_LENGTH);
+ }
+
/*
* Writes the user list file in this format:
*
@@ -4869,7 +4880,7 @@
@UserIdInt int parentId, boolean preCreate, @Nullable String[] disallowedPackages,
@NonNull TimingsTraceAndSlog t, @Nullable Object token)
throws UserManager.CheckedUserOperationException {
-
+ String truncatedName = truncateString(name);
final UserTypeDetails userTypeDetails = mUserTypes.get(userType);
if (userTypeDetails == null) {
throwCheckedUserOperationException(
@@ -4904,8 +4915,8 @@
// Try to use a pre-created user (if available).
if (!preCreate && parentId < 0 && isUserTypeEligibleForPreCreation(userTypeDetails)) {
- final UserInfo preCreatedUser = convertPreCreatedUserIfPossible(userType, flags, name,
- token);
+ final UserInfo preCreatedUser = convertPreCreatedUserIfPossible(userType, flags,
+ truncatedName, token);
if (preCreatedUser != null) {
return preCreatedUser;
}
@@ -5000,7 +5011,7 @@
flags |= UserInfo.FLAG_EPHEMERAL_ON_CREATE;
}
- userInfo = new UserInfo(userId, name, null, flags, userType);
+ userInfo = new UserInfo(userId, truncatedName, null, flags, userType);
userInfo.serialNumber = mNextSerialNumber++;
userInfo.creationTime = getCreationTime();
userInfo.partial = true;
@@ -6456,8 +6467,8 @@
Slog.e(LOG_TAG, "No such user for settings seed data u=" + userId);
return;
}
- userData.seedAccountName = accountName;
- userData.seedAccountType = accountType;
+ userData.seedAccountName = truncateString(accountName);
+ userData.seedAccountType = truncateString(accountType);
userData.seedAccountOptions = accountOptions;
userData.persistSeedData = persist;
}
diff --git a/services/core/java/com/android/server/policy/AppOpsPolicy.java b/services/core/java/com/android/server/policy/AppOpsPolicy.java
index ebc7163..b83421f 100644
--- a/services/core/java/com/android/server/policy/AppOpsPolicy.java
+++ b/services/core/java/com/android/server/policy/AppOpsPolicy.java
@@ -42,6 +42,7 @@
import android.os.Process;
import android.os.SystemProperties;
import android.os.UserHandle;
+import android.permission.flags.Flags;
import android.service.voice.VoiceInteractionManagerInternal;
import android.service.voice.VoiceInteractionManagerInternal.HotwordDetectionServiceIdentity;
import android.text.TextUtils;
@@ -75,9 +76,6 @@
private static final boolean SYSPROP_HOTWORD_DETECTION_SERVICE_REQUIRED =
SystemProperties.getBoolean("ro.hotword.detection_service_required", false);
- //TODO(b/289087412): import this from the flag value in set up in device config.
- private static final boolean IS_VOICE_ACTIVATION_OP_ENABLED = false;
-
@NonNull
private final Object mLock = new Object();
@@ -212,7 +210,7 @@
* @return the op that should be noted for the voice activations of the app by detected hotword.
*/
public static int getVoiceActivationOp() {
- if (IS_VOICE_ACTIVATION_OP_ENABLED) {
+ if (Flags.voiceActivationPermissionApis()) {
return OP_RECEIVE_SANDBOX_TRIGGER_AUDIO;
}
return OP_RECORD_AUDIO_HOTWORD;
diff --git a/services/core/java/com/android/server/vibrator/HapticFeedbackVibrationProvider.java b/services/core/java/com/android/server/vibrator/HapticFeedbackVibrationProvider.java
index 3d89afa..becbbf2 100644
--- a/services/core/java/com/android/server/vibrator/HapticFeedbackVibrationProvider.java
+++ b/services/core/java/com/android/server/vibrator/HapticFeedbackVibrationProvider.java
@@ -25,6 +25,8 @@
import android.util.Slog;
import android.util.SparseArray;
import android.view.HapticFeedbackConstants;
+import android.view.flags.FeatureFlags;
+import android.view.flags.FeatureFlagsImpl;
import com.android.internal.annotations.VisibleForTesting;
@@ -54,6 +56,7 @@
// If present and valid, a vibration here will be used for an effect.
// Otherwise, the system's default vibration will be used.
@Nullable private final SparseArray<VibrationEffect> mHapticCustomizations;
+ private final FeatureFlags mViewFeatureFlags;
/** @hide */
public HapticFeedbackVibrationProvider(Resources res, Vibrator vibrator) {
@@ -62,14 +65,16 @@
/** @hide */
public HapticFeedbackVibrationProvider(Resources res, VibratorInfo vibratorInfo) {
- this(res, vibratorInfo, loadHapticCustomizations(res, vibratorInfo));
+ this(res, vibratorInfo, loadHapticCustomizations(res, vibratorInfo),
+ new FeatureFlagsImpl());
}
/** @hide */
@VisibleForTesting HapticFeedbackVibrationProvider(
Resources res,
VibratorInfo vibratorInfo,
- @Nullable SparseArray<VibrationEffect> hapticCustomizations) {
+ @Nullable SparseArray<VibrationEffect> hapticCustomizations,
+ FeatureFlags viewFeatureFlags) {
mVibratorInfo = vibratorInfo;
mHapticTextHandleEnabled = res.getBoolean(
com.android.internal.R.bool.config_enableHapticTextHandle);
@@ -78,6 +83,7 @@
hapticCustomizations = null;
}
mHapticCustomizations = hapticCustomizations;
+ mViewFeatureFlags = viewFeatureFlags;
mSafeModeEnabledVibrationEffect =
effectHasCustomization(HapticFeedbackConstants.SAFE_MODE_ENABLED)
@@ -201,12 +207,16 @@
default:
attrs = TOUCH_VIBRATION_ATTRIBUTES;
}
+
+ int flags = 0;
if (bypassVibrationIntensitySetting) {
- attrs = new VibrationAttributes.Builder(attrs)
- .setFlags(VibrationAttributes.FLAG_BYPASS_USER_VIBRATION_INTENSITY_OFF)
- .build();
+ flags |= VibrationAttributes.FLAG_BYPASS_USER_VIBRATION_INTENSITY_OFF;
}
- return attrs;
+ if (shouldBypassInterruptionPolicy(effectId, mViewFeatureFlags)) {
+ flags |= VibrationAttributes.FLAG_BYPASS_INTERRUPTION_POLICY;
+ }
+
+ return flags == 0 ? attrs : new VibrationAttributes.Builder(attrs).setFlags(flags).build();
}
/** Dumps relevant state. */
@@ -295,4 +305,19 @@
return null;
}
}
+
+ private static boolean shouldBypassInterruptionPolicy(
+ int effectId, FeatureFlags viewFeatureFlags) {
+ switch (effectId) {
+ case HapticFeedbackConstants.SCROLL_TICK:
+ case HapticFeedbackConstants.SCROLL_ITEM_FOCUS:
+ case HapticFeedbackConstants.SCROLL_LIMIT:
+ // The SCROLL_* constants should bypass interruption filter, so that scroll haptics
+ // can play regardless of focus modes like DND. Guard this behavior by the feature
+ // flag controlling the general scroll feedback APIs.
+ return viewFeatureFlags.scrollFeedbackApi();
+ default:
+ return false;
+ }
+ }
}
diff --git a/services/core/java/com/android/server/vibrator/VibratorManagerService.java b/services/core/java/com/android/server/vibrator/VibratorManagerService.java
index ee3d697..45bd152 100644
--- a/services/core/java/com/android/server/vibrator/VibratorManagerService.java
+++ b/services/core/java/com/android/server/vibrator/VibratorManagerService.java
@@ -448,6 +448,7 @@
String reason, IBinder token) {
Trace.traceBegin(Trace.TRACE_TAG_VIBRATOR, "vibrate, reason = " + reason);
try {
+ attrs = fixupVibrationAttributes(attrs, effect);
mContext.enforceCallingOrSelfPermission(
android.Manifest.permission.VIBRATE, "vibrate");
return vibrateInternal(uid, displayId, opPkg, effect, attrs, reason, token);
@@ -457,7 +458,7 @@
}
HalVibration vibrateWithoutPermissionCheck(int uid, int displayId, String opPkg,
- @NonNull CombinedVibration effect, @Nullable VibrationAttributes attrs,
+ @NonNull CombinedVibration effect, @NonNull VibrationAttributes attrs,
String reason, IBinder token) {
Trace.traceBegin(Trace.TRACE_TAG_VIBRATOR, "vibrate no perm check, reason = " + reason);
try {
@@ -468,7 +469,7 @@
}
private HalVibration vibrateInternal(int uid, int displayId, String opPkg,
- @NonNull CombinedVibration effect, @Nullable VibrationAttributes attrs,
+ @NonNull CombinedVibration effect, @NonNull VibrationAttributes attrs,
String reason, IBinder token) {
if (token == null) {
Slog.e(TAG, "token must not be null");
@@ -478,7 +479,6 @@
if (!isEffectValid(effect)) {
return null;
}
- attrs = fixupVibrationAttributes(attrs, effect);
// Create Vibration.Stats as close to the received request as possible, for tracking.
HalVibration vib = new HalVibration(token, effect,
new Vibration.CallerInfo(attrs, uid, displayId, opPkg, reason));
diff --git a/services/core/java/com/android/server/wm/ActivityStartController.java b/services/core/java/com/android/server/wm/ActivityStartController.java
index c39b266..4a5311b 100644
--- a/services/core/java/com/android/server/wm/ActivityStartController.java
+++ b/services/core/java/com/android/server/wm/ActivityStartController.java
@@ -577,7 +577,8 @@
.getRootTask(WINDOWING_MODE_UNDEFINED, activityType);
if (rootTask == null) return false;
final ActivityRecord r = rootTask.topRunningActivity();
- if (r == null || r.isVisibleRequested() || !r.attachedToProcess()
+ if (r == null || (r.isVisibleRequested() && rootTask.isTopRootTaskInDisplayArea())
+ || !r.attachedToProcess()
|| !r.mActivityComponent.equals(intent.getComponent())
|| !mService.isCallerRecents(r.getUid())
// Recents keeps invisible while device is locked.
diff --git a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
index 61bae71..0b67321 100644
--- a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
+++ b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
@@ -6448,19 +6448,8 @@
if (!restarting && hasVisibleActivities) {
deferWindowLayout();
try {
- final Task topTask = mRootWindowContainer.getTopDisplayFocusedRootTask();
- if (topTask != null
- && topTask.topRunningActivity(true /* focusableOnly */) == null) {
- topTask.adjustFocusToNextFocusableTask("handleAppDied");
- }
- if (!mRootWindowContainer.resumeFocusedTasksTopActivities()) {
- // If there was nothing to resume, and we are not already restarting
- // this process, but there is a visible activity that is hosted by the
- // process...then make sure all visible activities are running, taking
- // care of restarting this process.
- mRootWindowContainer.ensureActivitiesVisible(null, 0,
- !PRESERVE_WINDOWS);
- }
+ mRootWindowContainer.ensureVisibilityOnVisibleActivityDiedOrCrashed(
+ "handleAppDied");
} finally {
continueWindowLayout();
}
@@ -6901,7 +6890,18 @@
@Override
public int finishTopCrashedActivities(WindowProcessController crashedApp, String reason) {
synchronized (mGlobalLock) {
- return mRootWindowContainer.finishTopCrashedActivities(crashedApp, reason);
+ deferWindowLayout();
+ try {
+ final Task finishedTask = mRootWindowContainer.finishTopCrashedActivities(
+ crashedApp, reason);
+ if (finishedTask != null) {
+ mRootWindowContainer.ensureVisibilityOnVisibleActivityDiedOrCrashed(reason);
+ return finishedTask.mTaskId;
+ }
+ return INVALID_TASK_ID;
+ } finally {
+ continueWindowLayout();
+ }
}
}
diff --git a/services/core/java/com/android/server/wm/BackNavigationController.java b/services/core/java/com/android/server/wm/BackNavigationController.java
index c2885da..4237668 100644
--- a/services/core/java/com/android/server/wm/BackNavigationController.java
+++ b/services/core/java/com/android/server/wm/BackNavigationController.java
@@ -163,7 +163,8 @@
if (window == null) {
EmbeddedWindowController.EmbeddedWindow embeddedWindow =
- wmService.mEmbeddedWindowController.getByFocusToken(focusedWindowToken);
+ wmService.mEmbeddedWindowController.getByInputTransferToken(
+ focusedWindowToken);
if (embeddedWindow != null) {
ProtoLog.d(WM_DEBUG_BACK_PREVIEW,
"Current focused window is embeddedWindow. Dispatch KEYCODE_BACK.");
diff --git a/services/core/java/com/android/server/wm/DragState.java b/services/core/java/com/android/server/wm/DragState.java
index 0f1a105..7af4aad 100644
--- a/services/core/java/com/android/server/wm/DragState.java
+++ b/services/core/java/com/android/server/wm/DragState.java
@@ -48,7 +48,6 @@
import android.os.Binder;
import android.os.Build;
import android.os.IBinder;
-import android.os.InputConfig;
import android.os.RemoteException;
import android.os.UserHandle;
import android.os.UserManager;
@@ -186,6 +185,10 @@
// Crop the input surface to the display size.
mTmpClipRect.set(0, 0, mDisplaySize.x, mDisplaySize.y);
+ // Make trusted overlay to not block any touches while D&D ongoing and allowing
+ // touches to pass through to windows underneath. This allows user to interact with the
+ // UI to navigate while dragging.
+ h.setTrustedOverlay(mTransaction, mInputSurface, true);
mTransaction.show(mInputSurface)
.setInputWindowInfo(mInputSurface, h)
.setLayer(mInputSurface, Integer.MAX_VALUE)
@@ -377,11 +380,6 @@
mDragWindowHandle.ownerUid = MY_UID;
mDragWindowHandle.scaleFactor = 1.0f;
- // InputConfig.TRUSTED_OVERLAY: To not block any touches while D&D ongoing and allowing
- // touches to pass through to windows underneath. This allows user to interact with the
- // UI to navigate while dragging.
- mDragWindowHandle.inputConfig = InputConfig.TRUSTED_OVERLAY;
-
// The drag window cannot receive new touches.
mDragWindowHandle.touchableRegion.setEmpty();
diff --git a/services/core/java/com/android/server/wm/EmbeddedWindowController.java b/services/core/java/com/android/server/wm/EmbeddedWindowController.java
index c9bae12..275396f 100644
--- a/services/core/java/com/android/server/wm/EmbeddedWindowController.java
+++ b/services/core/java/com/android/server/wm/EmbeddedWindowController.java
@@ -45,8 +45,8 @@
private static final String TAG = TAG_WITH_CLASS_NAME ? "EmbeddedWindowController" : TAG_WM;
/* maps input token to an embedded window */
private ArrayMap<IBinder /*input token */, EmbeddedWindow> mWindows = new ArrayMap<>();
- private ArrayMap<IBinder /*focus grant token */, EmbeddedWindow> mWindowsByFocusToken =
- new ArrayMap<>();
+ private ArrayMap<IBinder /*input transfer token */, EmbeddedWindow>
+ mWindowsByInputTransferToken = new ArrayMap<>();
private ArrayMap<IBinder /*window token*/, EmbeddedWindow> mWindowsByWindowToken =
new ArrayMap<>();
private final Object mGlobalLock;
@@ -67,14 +67,14 @@
void add(IBinder inputToken, EmbeddedWindow window) {
try {
mWindows.put(inputToken, window);
- final IBinder focusToken = window.getFocusGrantToken();
- mWindowsByFocusToken.put(focusToken, window);
+ final IBinder inputTransferToken = window.getInputTransferToken();
+ mWindowsByInputTransferToken.put(inputTransferToken, window);
mWindowsByWindowToken.put(window.getWindowToken(), window);
updateProcessController(window);
window.mClient.asBinder().linkToDeath(()-> {
synchronized (mGlobalLock) {
mWindows.remove(inputToken);
- mWindowsByFocusToken.remove(focusToken);
+ mWindowsByInputTransferToken.remove(inputTransferToken);
}
}, 0);
} catch (RemoteException e) {
@@ -105,7 +105,7 @@
EmbeddedWindow ew = mWindows.valueAt(i);
if (ew.mClient.asBinder() == client.asBinder()) {
mWindows.removeAt(i).onRemoved();
- mWindowsByFocusToken.remove(ew.getFocusGrantToken());
+ mWindowsByInputTransferToken.remove(ew.getInputTransferToken());
mWindowsByWindowToken.remove(ew.getWindowToken());
return;
}
@@ -117,7 +117,7 @@
EmbeddedWindow ew = mWindows.valueAt(i);
if (ew.mHostWindowState == host) {
mWindows.removeAt(i).onRemoved();
- mWindowsByFocusToken.remove(ew.getFocusGrantToken());
+ mWindowsByInputTransferToken.remove(ew.getInputTransferToken());
mWindowsByWindowToken.remove(ew.getWindowToken());
}
}
@@ -127,8 +127,8 @@
return mWindows.get(inputToken);
}
- EmbeddedWindow getByFocusToken(IBinder focusGrantToken) {
- return mWindowsByFocusToken.get(focusGrantToken);
+ EmbeddedWindow getByInputTransferToken(IBinder inputTransferToken) {
+ return mWindowsByInputTransferToken.get(inputTransferToken);
}
EmbeddedWindow getByWindowToken(IBinder windowToken) {
@@ -153,7 +153,7 @@
* to request focus transfer to the embedded. This is not the input token since we don't
* want to give clients access to each others input token.
*/
- private final IBinder mFocusGrantToken;
+ private final IBinder mInputTransferToken;
private boolean mIsFocusable;
@@ -171,7 +171,7 @@
*/
EmbeddedWindow(Session session, WindowManagerService service, IWindow clientToken,
WindowState hostWindowState, int ownerUid, int ownerPid, int windowType,
- int displayId, IBinder focusGrantToken, String inputHandleName,
+ int displayId, IBinder inputTransferToken, String inputHandleName,
boolean isFocusable) {
mSession = session;
mWmService = service;
@@ -183,7 +183,7 @@
mOwnerPid = ownerPid;
mWindowType = windowType;
mDisplayId = displayId;
- mFocusGrantToken = focusGrantToken;
+ mInputTransferToken = inputTransferToken;
final String hostWindowName =
(mHostWindowState != null) ? "-" + mHostWindowState.getWindowTag().toString()
: "";
@@ -260,8 +260,8 @@
return mOwnerUid;
}
- IBinder getFocusGrantToken() {
- return mFocusGrantToken;
+ IBinder getInputTransferToken() {
+ return mInputTransferToken;
}
IBinder getInputChannelToken() {
@@ -290,7 +290,7 @@
// Use null session since this is being granted by system server and doesn't
// require the host session to be passed in
mWmService.grantEmbeddedWindowFocus(null, mHostWindowState.mClient,
- mFocusGrantToken, grantFocus);
+ mInputTransferToken, grantFocus);
if (grantFocus) {
// If granting focus to the embedded when tapped, we need to ensure the host
// gains focus as well or the transfer won't take effect since it requires
@@ -298,7 +298,7 @@
mHostWindowState.handleTapOutsideFocusInsideSelf();
}
} else {
- mWmService.grantEmbeddedWindowFocus(mSession, mFocusGrantToken, grantFocus);
+ mWmService.grantEmbeddedWindowFocus(mSession, mInputTransferToken, grantFocus);
}
}
}
diff --git a/services/core/java/com/android/server/wm/InputConsumerImpl.java b/services/core/java/com/android/server/wm/InputConsumerImpl.java
index 39622c1..c21930d 100644
--- a/services/core/java/com/android/server/wm/InputConsumerImpl.java
+++ b/services/core/java/com/android/server/wm/InputConsumerImpl.java
@@ -74,7 +74,7 @@
mWindowHandle.ownerPid = WindowManagerService.MY_PID;
mWindowHandle.ownerUid = WindowManagerService.MY_UID;
mWindowHandle.scaleFactor = 1.0f;
- mWindowHandle.inputConfig = InputConfig.NOT_FOCUSABLE | InputConfig.TRUSTED_OVERLAY;
+ mWindowHandle.inputConfig = InputConfig.NOT_FOCUSABLE;
mInputSurface = mService.makeSurfaceBuilder(
mService.mRoot.getDisplayContent(displayId).getSession())
@@ -129,12 +129,14 @@
void show(SurfaceControl.Transaction t, WindowContainer w) {
t.show(mInputSurface);
+ mWindowHandle.setTrustedOverlay(t, mInputSurface, true);
t.setInputWindowInfo(mInputSurface, mWindowHandle);
t.setRelativeLayer(mInputSurface, w.getSurfaceControl(), 1);
}
void show(SurfaceControl.Transaction t, int layer) {
t.show(mInputSurface);
+ mWindowHandle.setTrustedOverlay(t, mInputSurface, true);
t.setInputWindowInfo(mInputSurface, mWindowHandle);
t.setLayer(mInputSurface, layer);
}
diff --git a/services/core/java/com/android/server/wm/InputMonitor.java b/services/core/java/com/android/server/wm/InputMonitor.java
index 825d38b..af307ec3 100644
--- a/services/core/java/com/android/server/wm/InputMonitor.java
+++ b/services/core/java/com/android/server/wm/InputMonitor.java
@@ -675,6 +675,11 @@
w.getKeyInterceptionInfo());
if (w.mWinAnimator.hasSurface()) {
+ // Update trusted overlay changes here because they are tied to input info. Input
+ // changes can be updated even if surfaces aren't.
+ inputWindowHandle.setTrustedOverlay(mInputTransaction,
+ w.mWinAnimator.mSurfaceController.mSurfaceControl,
+ w.isWindowTrustedOverlay());
populateInputWindowHandle(inputWindowHandle, w);
setInputWindowInfoIfNeeded(mInputTransaction,
w.mWinAnimator.mSurfaceController.mSurfaceControl, inputWindowHandle);
@@ -732,7 +737,7 @@
new InputWindowHandle(null /* inputApplicationHandle */, displayId));
inputWindowHandle.setName(name);
inputWindowHandle.setLayoutParamsType(TYPE_SECURE_SYSTEM_OVERLAY);
- inputWindowHandle.setTrustedOverlay(true);
+ inputWindowHandle.setTrustedOverlay(t, sc, true);
populateOverlayInputInfo(inputWindowHandle);
setInputWindowInfoIfNeeded(t, sc, inputWindowHandle);
}
diff --git a/services/core/java/com/android/server/wm/InputWindowHandleWrapper.java b/services/core/java/com/android/server/wm/InputWindowHandleWrapper.java
index 64b7a60..90d81bd 100644
--- a/services/core/java/com/android/server/wm/InputWindowHandleWrapper.java
+++ b/services/core/java/com/android/server/wm/InputWindowHandleWrapper.java
@@ -195,6 +195,11 @@
mChanged = true;
}
+ void setTrustedOverlay(SurfaceControl.Transaction t, SurfaceControl sc,
+ boolean trustedOverlay) {
+ mHandle.setTrustedOverlay(t, sc, trustedOverlay);
+ }
+
void setOwnerPid(int pid) {
if (mHandle.ownerPid == pid) {
return;
diff --git a/services/core/java/com/android/server/wm/RecentsAnimationController.java b/services/core/java/com/android/server/wm/RecentsAnimationController.java
index c3977d6..82d4b90 100644
--- a/services/core/java/com/android/server/wm/RecentsAnimationController.java
+++ b/services/core/java/com/android/server/wm/RecentsAnimationController.java
@@ -62,6 +62,7 @@
import android.window.TaskSnapshot;
import com.android.internal.annotations.VisibleForTesting;
+import com.android.internal.os.IResultReceiver;
import com.android.internal.protolog.common.ProtoLog;
import com.android.server.LocalServices;
import com.android.server.inputmethod.InputMethodManagerInternal;
@@ -244,7 +245,8 @@
}
@Override
- public void finish(boolean moveHomeToTop, boolean sendUserLeaveHint) {
+ public void finish(boolean moveHomeToTop, boolean sendUserLeaveHint,
+ IResultReceiver finishCb) {
ProtoLog.d(WM_DEBUG_RECENTS_ANIMATIONS,
"finish(%b): mCanceled=%b", moveHomeToTop, mCanceled);
final long token = Binder.clearCallingIdentity();
@@ -257,6 +259,13 @@
} finally {
Binder.restoreCallingIdentity(token);
}
+ if (finishCb != null) {
+ try {
+ finishCb.send(0, new Bundle());
+ } catch (RemoteException e) {
+ Slog.e(TAG, "Failed to report animation finished", e);
+ }
+ }
}
@Override
diff --git a/services/core/java/com/android/server/wm/RootWindowContainer.java b/services/core/java/com/android/server/wm/RootWindowContainer.java
index a88aa2e..cf6a1fe 100644
--- a/services/core/java/com/android/server/wm/RootWindowContainer.java
+++ b/services/core/java/com/android/server/wm/RootWindowContainer.java
@@ -2319,19 +2319,36 @@
*
* @param app The app that crashed.
* @param reason Reason to perform this action.
- * @return The task id that was finished in this root task, or INVALID_TASK_ID if none was
- * finished.
+ * @return The finished task which was on top or visible, otherwise {@code null} if the crashed
+ * app doesn't have activity in visible task.
*/
- int finishTopCrashedActivities(WindowProcessController app, String reason) {
+ @Nullable
+ Task finishTopCrashedActivities(WindowProcessController app, String reason) {
Task focusedRootTask = getTopDisplayFocusedRootTask();
final Task[] finishedTask = new Task[1];
forAllRootTasks(rootTask -> {
+ final boolean recordTopOrVisible = finishedTask[0] == null
+ && (focusedRootTask == rootTask || rootTask.isVisibleRequested());
final Task t = rootTask.finishTopCrashedActivityLocked(app, reason);
- if (rootTask == focusedRootTask || finishedTask[0] == null) {
+ if (recordTopOrVisible) {
finishedTask[0] = t;
}
});
- return finishedTask[0] != null ? finishedTask[0].mTaskId : INVALID_TASK_ID;
+ return finishedTask[0];
+ }
+
+ void ensureVisibilityOnVisibleActivityDiedOrCrashed(String reason) {
+ final Task topTask = getTopDisplayFocusedRootTask();
+ if (topTask != null && topTask.topRunningActivity(true /* focusableOnly */) == null) {
+ // Move the next focusable task to front.
+ topTask.adjustFocusToNextFocusableTask(reason);
+ }
+ if (!resumeFocusedTasksTopActivities()) {
+ // It may be nothing to resume because there are pausing activities or all the top
+ // activities are resumed. Then it still needs to make sure all visible activities are
+ // running in case the tasks were reordered or there are non-top visible activities.
+ ensureActivitiesVisible(null /* starting */, 0 /* configChanges */, !PRESERVE_WINDOWS);
+ }
}
boolean resumeFocusedTasksTopActivities() {
diff --git a/services/core/java/com/android/server/wm/Session.java b/services/core/java/com/android/server/wm/Session.java
index bbe44c5..e6d4866 100644
--- a/services/core/java/com/android/server/wm/Session.java
+++ b/services/core/java/com/android/server/wm/Session.java
@@ -884,8 +884,8 @@
@Override
public void grantInputChannel(int displayId, SurfaceControl surface,
IWindow window, IBinder hostInputToken, int flags, int privateFlags, int type,
- int inputFeatures, IBinder windowToken, IBinder focusGrantToken, String inputHandleName,
- InputChannel outInputChannel) {
+ int inputFeatures, IBinder windowToken, IBinder inputTransferToken,
+ String inputHandleName, InputChannel outInputChannel) {
if (hostInputToken == null && !mCanAddInternalSystemWindow) {
// Callers without INTERNAL_SYSTEM_WINDOW permission cannot grant input channel to
// embedded windows without providing a host window input token
@@ -896,7 +896,7 @@
try {
mService.grantInputChannel(this, mUid, mPid, displayId, surface, window, hostInputToken,
flags, mCanAddInternalSystemWindow ? privateFlags : 0,
- type, inputFeatures, windowToken, focusGrantToken, inputHandleName,
+ type, inputFeatures, windowToken, inputTransferToken, inputHandleName,
outInputChannel);
} finally {
Binder.restoreCallingIdentity(identity);
diff --git a/services/core/java/com/android/server/wm/Transition.java b/services/core/java/com/android/server/wm/Transition.java
index c6547a0..882104a 100644
--- a/services/core/java/com/android/server/wm/Transition.java
+++ b/services/core/java/com/android/server/wm/Transition.java
@@ -372,8 +372,7 @@
parent.forAllTasks(t -> {
// Skip transient-launch task
if (t == transientRootTask) return false;
- if (t.isVisibleRequested() && !t.isAlwaysOnTop()
- && !t.getWindowConfiguration().tasksAreFloating()) {
+ if (t.isVisibleRequested() && !t.isAlwaysOnTop()) {
if (t.isRootTask()) {
mTransientHideTasks.add(t);
}
diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java
index 60dc84c..074b404 100644
--- a/services/core/java/com/android/server/wm/WindowManagerService.java
+++ b/services/core/java/com/android/server/wm/WindowManagerService.java
@@ -2493,14 +2493,6 @@
outInsetsState.set(win.getCompatInsetsState(), true /* copySources */);
}
- // TODO (b/298562855): Remove this after identifying the reason why the frame is empty.
- if (win.mAttrs.providedInsets != null && win.getFrame().isEmpty()) {
- Slog.w(TAG, "Empty frame of " + win
- + " configChanged=" + configChanged
- + " frame=" + win.getFrame().toShortString()
- + " attrs=" + attrs);
- }
-
ProtoLog.v(WM_DEBUG_FOCUS, "Relayout of %s: focusMayChange=%b",
win, focusMayChange);
@@ -8803,7 +8795,7 @@
void grantInputChannel(Session session, int callingUid, int callingPid, int displayId,
SurfaceControl surface, IWindow window, IBinder hostInputToken,
int flags, int privateFlags, int inputFeatures, int type, IBinder windowToken,
- IBinder focusGrantToken, String inputHandleName, InputChannel outInputChannel) {
+ IBinder inputTransferToken, String inputHandleName, InputChannel outInputChannel) {
final int sanitizedType = sanitizeWindowType(session, displayId, windowToken, type);
final InputApplicationHandle applicationHandle;
final String name;
@@ -8812,7 +8804,7 @@
EmbeddedWindowController.EmbeddedWindow win =
new EmbeddedWindowController.EmbeddedWindow(session, this, window,
mInputToWindowMap.get(hostInputToken), callingUid, callingPid,
- sanitizedType, displayId, focusGrantToken, inputHandleName,
+ sanitizedType, displayId, inputTransferToken, inputHandleName,
(flags & FLAG_NOT_FOCUSABLE) == 0);
win.openInputChannel(outInputChannel);
mEmbeddedWindowController.add(outInputChannel.getToken(), win);
@@ -8884,11 +8876,6 @@
h.inputConfig |= InputConfig.NOT_FOCUSABLE;
}
- // Check private trusted overlay flag to set trustedOverlay field of input window handle.
- if ((privateFlags & PRIVATE_FLAG_TRUSTED_OVERLAY) != 0) {
- h.inputConfig |= InputConfig.TRUSTED_OVERLAY;
- }
-
h.dispatchingTimeoutMillis = DEFAULT_DISPATCHING_TIMEOUT_MILLIS;
h.ownerUid = callingUid;
h.ownerPid = callingPid;
@@ -8908,6 +8895,8 @@
}
final SurfaceControl.Transaction t = mTransactionFactory.get();
+ // Check private trusted overlay flag to set trustedOverlay field of input window handle.
+ h.setTrustedOverlay(t, surface, (privateFlags & PRIVATE_FLAG_TRUSTED_OVERLAY) != 0);
t.setInputWindowInfo(surface, h);
t.apply();
t.close();
@@ -9139,10 +9128,10 @@
return mPossibleDisplayInfoMapper.getPossibleDisplayInfos(displayId);
}
- void grantEmbeddedWindowFocus(Session session, IBinder focusToken, boolean grantFocus) {
+ void grantEmbeddedWindowFocus(Session session, IBinder inputTransferToken, boolean grantFocus) {
synchronized (mGlobalLock) {
final EmbeddedWindowController.EmbeddedWindow embeddedWindow =
- mEmbeddedWindowController.getByFocusToken(focusToken);
+ mEmbeddedWindowController.getByInputTransferToken(inputTransferToken);
if (embeddedWindow == null) {
Slog.e(TAG, "Embedded window not found");
return;
@@ -9187,8 +9176,8 @@
}
}
- void grantEmbeddedWindowFocus(Session session, IWindow callingWindow, IBinder targetFocusToken,
- boolean grantFocus) {
+ void grantEmbeddedWindowFocus(Session session, IWindow callingWindow,
+ IBinder inputTransferToken, boolean grantFocus) {
synchronized (mGlobalLock) {
final WindowState hostWindow =
windowForClientLocked(session, callingWindow, false /* throwOnError*/);
@@ -9201,7 +9190,7 @@
return;
}
final EmbeddedWindowController.EmbeddedWindow embeddedWindow =
- mEmbeddedWindowController.getByFocusToken(targetFocusToken);
+ mEmbeddedWindowController.getByInputTransferToken(inputTransferToken);
if (embeddedWindow == null) {
Slog.e(TAG, "Embedded window not found");
return;
diff --git a/services/core/java/com/android/server/wm/WindowState.java b/services/core/java/com/android/server/wm/WindowState.java
index ebef606..4beec2b 100644
--- a/services/core/java/com/android/server/wm/WindowState.java
+++ b/services/core/java/com/android/server/wm/WindowState.java
@@ -178,6 +178,7 @@
import static com.android.server.wm.WindowStateProto.VIEW_VISIBILITY;
import static com.android.server.wm.WindowStateProto.WINDOW_CONTAINER;
import static com.android.server.wm.WindowStateProto.WINDOW_FRAMES;
+import static com.android.window.flags.Flags.surfaceTrustedOverlay;
import android.annotation.CallSuper;
import android.annotation.NonNull;
@@ -1110,7 +1111,9 @@
mInputWindowHandle.setName(getName());
mInputWindowHandle.setPackageName(mAttrs.packageName);
mInputWindowHandle.setLayoutParamsType(mAttrs.type);
- mInputWindowHandle.setTrustedOverlay(shouldWindowHandleBeTrusted(s));
+ if (!surfaceTrustedOverlay()) {
+ mInputWindowHandle.setTrustedOverlay(isWindowTrustedOverlay());
+ }
if (DEBUG) {
Slog.v(TAG, "Window " + this + " client=" + c.asBinder()
+ " token=" + token + " (" + mAttrs.token + ")" + " params=" + a);
@@ -1185,12 +1188,12 @@
}
}
- boolean shouldWindowHandleBeTrusted(Session s) {
+ public boolean isWindowTrustedOverlay() {
return InputMonitor.isTrustedOverlay(mAttrs.type)
|| ((mAttrs.privateFlags & PRIVATE_FLAG_TRUSTED_OVERLAY) != 0
- && s.mCanAddInternalSystemWindow)
+ && mSession.mCanAddInternalSystemWindow)
|| ((mAttrs.privateFlags & PRIVATE_FLAG_SYSTEM_APPLICATION_OVERLAY) != 0
- && s.mCanCreateSystemApplicationOverlay);
+ && mSession.mCanCreateSystemApplicationOverlay);
}
int getTouchOcclusionMode() {
@@ -5187,6 +5190,9 @@
updateFrameRateSelectionPriorityIfNeeded();
updateScaleIfNeeded();
mWinAnimator.prepareSurfaceLocked(getSyncTransaction());
+ if (surfaceTrustedOverlay()) {
+ getSyncTransaction().setTrustedOverlay(mSurfaceControl, isWindowTrustedOverlay());
+ }
}
super.prepareSurfaces();
}
@@ -5939,7 +5945,13 @@
}
boolean isTrustedOverlay() {
- return mInputWindowHandle.isTrustedOverlay();
+ if (surfaceTrustedOverlay()) {
+ WindowState parentWindow = getParentWindow();
+ return isWindowTrustedOverlay() || (parentWindow != null
+ && parentWindow.isWindowTrustedOverlay());
+ } else {
+ return mInputWindowHandle.isTrustedOverlay();
+ }
}
public boolean receiveFocusFromTapOutside() {
diff --git a/services/core/jni/Android.bp b/services/core/jni/Android.bp
index ec5378f..bc70658 100644
--- a/services/core/jni/Android.bp
+++ b/services/core/jni/Android.bp
@@ -78,6 +78,7 @@
"onload.cpp",
":lib_cachedAppOptimizer_native",
":lib_gameManagerService_native",
+ ":lib_oomConnection_native",
],
include_dirs: [
@@ -122,6 +123,7 @@
"libhardware_legacy",
"libhidlbase",
"libmeminfo",
+ "libmemevents",
"libmemtrackproxy",
"libmtp",
"libnativehelper",
@@ -239,3 +241,8 @@
"com_android_server_app_GameManagerService.cpp",
],
}
+
+filegroup {
+ name: "lib_oomConnection_native",
+ srcs: ["com_android_server_am_OomConnection.cpp",],
+}
diff --git a/services/core/jni/com_android_server_am_OomConnection.cpp b/services/core/jni/com_android_server_am_OomConnection.cpp
new file mode 100644
index 0000000..e892d23
--- /dev/null
+++ b/services/core/jni/com_android_server_am_OomConnection.cpp
@@ -0,0 +1,113 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "OomConnection"
+
+#include <core_jni_helpers.h>
+#include <jni.h>
+#include <memevents/memevents.h>
+
+namespace android {
+
+// Used to cache the results of the JNI name lookup
+static struct {
+ jclass clazz;
+ jmethodID ctor;
+} sOomKillRecordInfo;
+
+static memevents::MemEventListener memevent_listener;
+
+/**
+ * Initialize listening and waiting for new out-of-memory (OOM) events to occur.
+ * Once a OOM event is detected, we then fetch the list of OOM kills, and return
+ * a corresponding java array with the information gathered.
+ *
+ * In the case that we encounter an error, we make sure to close the epfd, and
+ * the OOM file descriptor, by calling `deregisterAllEvents()`.
+ *
+ * @return list of `android.os.OomKillRecord`
+ * @throws java.lang.RuntimeException
+ */
+static jobjectArray android_server_am_OomConnection_waitOom(JNIEnv* env, jobject) {
+ const memevents::MemEvent oom_event = memevents::MemEvent::OOM_KILL;
+ if (!memevent_listener.registerEvent(oom_event)) {
+ memevent_listener.deregisterAllEvents();
+ jniThrowRuntimeException(env, "listener failed to register to OOM events");
+ return nullptr;
+ }
+
+ memevents::MemEvent event_received;
+ do {
+ event_received = memevent_listener.listen();
+ if (event_received == memevents::MemEvent::ERROR) {
+ memevent_listener.deregisterAllEvents();
+ jniThrowRuntimeException(env, "listener received error event");
+ return nullptr;
+ }
+ } while (event_received != oom_event);
+
+ std::vector<memevents::OomKill> oom_events;
+ if (!memevent_listener.getOomEvents(oom_events)) {
+ memevent_listener.deregisterAllEvents();
+ jniThrowRuntimeException(env, "Failed to get OOM events");
+ return nullptr;
+ }
+
+ jobjectArray java_oom_array =
+ env->NewObjectArray(oom_events.size(), sOomKillRecordInfo.clazz, nullptr);
+ if (java_oom_array == NULL) {
+ memevent_listener.deregisterAllEvents();
+ jniThrowRuntimeException(env, "Failed to create OomKillRecord array");
+ return nullptr;
+ }
+
+ for (int i = 0; i < oom_events.size(); i++) {
+ const memevents::OomKill oom_event = oom_events[i];
+ jstring process_name = env->NewStringUTF(oom_event.process_name);
+ if (process_name == NULL) {
+ memevent_listener.deregisterAllEvents();
+ jniThrowRuntimeException(env, "Failed creating java string for process name");
+ }
+ jobject java_oom_kill = env->NewObject(sOomKillRecordInfo.clazz, sOomKillRecordInfo.ctor,
+ oom_event.timestamp_ms, oom_event.pid, oom_event.uid,
+ process_name, oom_event.oom_score_adj);
+ if (java_oom_kill == NULL) {
+ memevent_listener.deregisterAllEvents();
+ jniThrowRuntimeException(env, "Failed to create OomKillRecord object");
+ return java_oom_array;
+ }
+ env->SetObjectArrayElement(java_oom_array, i, java_oom_kill);
+ }
+ return java_oom_array;
+}
+
+static const JNINativeMethod sOomConnectionMethods[] = {
+ /* name, signature, funcPtr */
+ {"waitOom", "()[Landroid/os/OomKillRecord;",
+ (void*)android_server_am_OomConnection_waitOom},
+};
+
+int register_android_server_am_OomConnection(JNIEnv* env) {
+ sOomKillRecordInfo.clazz = FindClassOrDie(env, "android/os/OomKillRecord");
+ sOomKillRecordInfo.clazz = MakeGlobalRefOrDie(env, sOomKillRecordInfo.clazz);
+
+ sOomKillRecordInfo.ctor =
+ GetMethodIDOrDie(env, sOomKillRecordInfo.clazz, "<init>", "(JIILjava/lang/String;S)V");
+
+ return RegisterMethodsOrDie(env, "com/android/server/am/OomConnection", sOomConnectionMethods,
+ NELEM(sOomConnectionMethods));
+}
+} // namespace android
\ No newline at end of file
diff --git a/services/core/jni/onload.cpp b/services/core/jni/onload.cpp
index f6f6737..df44895 100644
--- a/services/core/jni/onload.cpp
+++ b/services/core/jni/onload.cpp
@@ -52,6 +52,7 @@
int register_android_server_HardwarePropertiesManagerService(JNIEnv* env);
int register_android_server_SyntheticPasswordManager(JNIEnv* env);
int register_android_hardware_display_DisplayViewport(JNIEnv* env);
+int register_android_server_am_OomConnection(JNIEnv* env);
int register_android_server_am_CachedAppOptimizer(JNIEnv* env);
int register_android_server_am_LowMemDetector(JNIEnv* env);
int register_com_android_server_soundtrigger_middleware_AudioSessionProviderImpl(JNIEnv* env);
@@ -112,6 +113,7 @@
register_android_server_storage_AppFuse(env);
register_android_server_SyntheticPasswordManager(env);
register_android_hardware_display_DisplayViewport(env);
+ register_android_server_am_OomConnection(env);
register_android_server_am_CachedAppOptimizer(env);
register_android_server_am_LowMemDetector(env);
register_com_android_server_soundtrigger_middleware_AudioSessionProviderImpl(env);
diff --git a/services/core/xsd/display-device-config/display-device-config.xsd b/services/core/xsd/display-device-config/display-device-config.xsd
index d0a9c45..debd891 100644
--- a/services/core/xsd/display-device-config/display-device-config.xsd
+++ b/services/core/xsd/display-device-config/display-device-config.xsd
@@ -46,6 +46,8 @@
<xs:annotation name="nonnull"/>
<xs:annotation name="final"/>
</xs:element>
+ <xs:element type="powerThrottlingConfig" name="powerThrottlingConfig" minOccurs="0"
+ maxOccurs="1"/>
<xs:element type="luxThrottling" name="luxThrottling" minOccurs="0"
maxOccurs="1"/>
<xs:element type="highBrightnessMode" name="highBrightnessMode" minOccurs="0"
@@ -350,6 +352,43 @@
</xs:sequence>
</xs:complexType>
+ <xs:complexType name="powerThrottlingMap">
+ <xs:sequence>
+ <xs:element name="powerThrottlingPoint" type="powerThrottlingPoint" maxOccurs="unbounded" minOccurs="1">
+ <xs:annotation name="nonnull"/>
+ <xs:annotation name="final"/>
+ </xs:element>
+ </xs:sequence>
+ <xs:attribute name="id" type="xs:string"/>
+ </xs:complexType>
+
+ <xs:complexType name="powerThrottlingPoint">
+ <xs:sequence>
+ <xs:element type="thermalStatus" name="thermalStatus">
+ <xs:annotation name="nonnull"/>
+ <xs:annotation name="final"/>
+ </xs:element>
+ <xs:element type="nonNegativeDecimal" name="powerQuotaMilliWatts">
+ <xs:annotation name="nonnull"/>
+ <xs:annotation name="final"/>
+ </xs:element>
+ </xs:sequence>
+ </xs:complexType>
+
+ <xs:complexType name="powerThrottlingConfig">
+ <xs:element type="nonNegativeDecimal" name="brightnessLowestCapAllowed">
+ <xs:annotation name="nonnull"/>
+ <xs:annotation name="final"/>
+ </xs:element>
+ <xs:element name="pollingWindowMillis" type="xs:nonNegativeInteger">
+ <xs:annotation name="nonnull"/>
+ <xs:annotation name="final"/>
+ </xs:element>
+ <xs:element type="powerThrottlingMap" name="powerThrottlingMap" maxOccurs="unbounded">
+ <xs:annotation name="final"/>
+ </xs:element>
+ </xs:complexType>
+
<xs:complexType name="nitsMap">
<xs:sequence>
<xs:element name="point" type="point" maxOccurs="unbounded" minOccurs="2">
diff --git a/services/core/xsd/display-device-config/schema/current.txt b/services/core/xsd/display-device-config/schema/current.txt
index 949b1f2..2d27f0c 100644
--- a/services/core/xsd/display-device-config/schema/current.txt
+++ b/services/core/xsd/display-device-config/schema/current.txt
@@ -106,6 +106,7 @@
method public final com.android.server.display.config.SensorDetails getLightSensor();
method public com.android.server.display.config.LuxThrottling getLuxThrottling();
method @Nullable public final String getName();
+ method public com.android.server.display.config.PowerThrottlingConfig getPowerThrottlingConfig();
method public final com.android.server.display.config.SensorDetails getProxSensor();
method public com.android.server.display.config.DisplayQuirks getQuirks();
method public com.android.server.display.config.RefreshRateConfigs getRefreshRate();
@@ -138,6 +139,7 @@
method public final void setLightSensor(com.android.server.display.config.SensorDetails);
method public void setLuxThrottling(com.android.server.display.config.LuxThrottling);
method public final void setName(@Nullable String);
+ method public void setPowerThrottlingConfig(com.android.server.display.config.PowerThrottlingConfig);
method public final void setProxSensor(com.android.server.display.config.SensorDetails);
method public void setQuirks(com.android.server.display.config.DisplayQuirks);
method public void setRefreshRate(com.android.server.display.config.RefreshRateConfigs);
@@ -246,6 +248,30 @@
method public final void setValue(@NonNull java.math.BigDecimal);
}
+ public class PowerThrottlingConfig {
+ ctor public PowerThrottlingConfig();
+ method @NonNull public final java.math.BigDecimal getBrightnessLowestCapAllowed();
+ method @NonNull public final java.math.BigInteger getPollingWindowMillis();
+ method public final java.util.List<com.android.server.display.config.PowerThrottlingMap> getPowerThrottlingMap();
+ method public final void setBrightnessLowestCapAllowed(@NonNull java.math.BigDecimal);
+ method public final void setPollingWindowMillis(@NonNull java.math.BigInteger);
+ }
+
+ public class PowerThrottlingMap {
+ ctor public PowerThrottlingMap();
+ method public String getId();
+ method @NonNull public final java.util.List<com.android.server.display.config.PowerThrottlingPoint> getPowerThrottlingPoint();
+ method public void setId(String);
+ }
+
+ public class PowerThrottlingPoint {
+ ctor public PowerThrottlingPoint();
+ method @NonNull public final java.math.BigDecimal getPowerQuotaMilliWatts();
+ method @NonNull public final com.android.server.display.config.ThermalStatus getThermalStatus();
+ method public final void setPowerQuotaMilliWatts(@NonNull java.math.BigDecimal);
+ method public final void setThermalStatus(@NonNull com.android.server.display.config.ThermalStatus);
+ }
+
public enum PredefinedBrightnessLimitNames {
method public String getRawName();
enum_constant public static final com.android.server.display.config.PredefinedBrightnessLimitNames _default;
diff --git a/services/core/xsd/display-layout-config/display-layout-config.xsd b/services/core/xsd/display-layout-config/display-layout-config.xsd
index 57b5d00..4e95465 100644
--- a/services/core/xsd/display-layout-config/display-layout-config.xsd
+++ b/services/core/xsd/display-layout-config/display-layout-config.xsd
@@ -52,6 +52,7 @@
<xs:element name="address" type="xs:nonNegativeInteger"/>
<xs:element name="position" type="xs:string" minOccurs="0" maxOccurs="1" />
<xs:element name="brightnessThrottlingMapId" type="xs:string" minOccurs="0" maxOccurs="1" />
+ <xs:element name="powerThrottlingMapId" type="xs:string" minOccurs="0" maxOccurs="1" />
<xs:element name="refreshRateThermalThrottlingMapId" type="xs:string" minOccurs="0" />
<xs:element name="leadDisplayAddress" type="xs:nonNegativeInteger" minOccurs="0" maxOccurs="1" />
</xs:sequence>
diff --git a/services/core/xsd/display-layout-config/schema/current.txt b/services/core/xsd/display-layout-config/schema/current.txt
index 2d4f7a4..195cae5 100644
--- a/services/core/xsd/display-layout-config/schema/current.txt
+++ b/services/core/xsd/display-layout-config/schema/current.txt
@@ -8,6 +8,7 @@
method public String getDisplayGroup();
method public java.math.BigInteger getLeadDisplayAddress();
method public String getPosition();
+ method public String getPowerThrottlingMapId();
method public String getRefreshRateThermalThrottlingMapId();
method public String getRefreshRateZoneId();
method public boolean isDefaultDisplay();
@@ -19,6 +20,7 @@
method public void setEnabled(boolean);
method public void setLeadDisplayAddress(java.math.BigInteger);
method public void setPosition(String);
+ method public void setPowerThrottlingMapId(String);
method public void setRefreshRateThermalThrottlingMapId(String);
method public void setRefreshRateZoneId(String);
}
diff --git a/services/credentials/java/com/android/server/credentials/CredentialManagerUi.java b/services/credentials/java/com/android/server/credentials/CredentialManagerUi.java
index b90f08e..3c190bf 100644
--- a/services/credentials/java/com/android/server/credentials/CredentialManagerUi.java
+++ b/services/credentials/java/com/android/server/credentials/CredentialManagerUi.java
@@ -32,6 +32,7 @@
import android.os.IBinder;
import android.os.Looper;
import android.os.ResultReceiver;
+import android.os.UserHandle;
import android.service.credentials.CredentialProviderInfoFactory;
import android.util.Slog;
@@ -171,7 +172,9 @@
.setAction(UUID.randomUUID().toString());
//TODO: Create unique pending intent using request code and cancel any pre-existing pending
// intents
- return PendingIntent.getActivity(
- mContext, /*requestCode=*/0, intent, PendingIntent.FLAG_IMMUTABLE);
+ return PendingIntent.getActivityAsUser(
+ mContext, /*requestCode=*/0, intent,
+ PendingIntent.FLAG_IMMUTABLE, /*options=*/null,
+ UserHandle.of(mUserId));
}
}
diff --git a/services/credentials/java/com/android/server/credentials/ProviderGetSession.java b/services/credentials/java/com/android/server/credentials/ProviderGetSession.java
index 3eb6718..7bd1cc4 100644
--- a/services/credentials/java/com/android/server/credentials/ProviderGetSession.java
+++ b/services/credentials/java/com/android/server/credentials/ProviderGetSession.java
@@ -31,6 +31,7 @@
import android.credentials.ui.GetCredentialProviderData;
import android.credentials.ui.ProviderPendingIntentResponse;
import android.os.ICancellationSignal;
+import android.service.autofill.Flags;
import android.service.credentials.Action;
import android.service.credentials.BeginGetCredentialOption;
import android.service.credentials.BeginGetCredentialRequest;
@@ -42,6 +43,7 @@
import android.service.credentials.RemoteEntry;
import android.util.Pair;
import android.util.Slog;
+import android.view.autofill.AutofillId;
import java.util.ArrayList;
import java.util.HashMap;
@@ -379,13 +381,23 @@
// but does not resolve to a valid option. For now, not skipping it because
// it may be possible that the provider adds their own extras and expects to receive
// those and complete the flow.
- if (mBeginGetOptionToCredentialOptionMap.get(id) == null) {
+ Intent intent = new Intent();
+ CredentialOption credentialOption = mBeginGetOptionToCredentialOptionMap.get(id);
+ if (credentialOption == null) {
Slog.w(TAG, "Id from Credential Entry does not resolve to a valid option");
- return new Intent();
+ return intent;
}
- return new Intent().putExtra(CredentialProviderService.EXTRA_GET_CREDENTIAL_REQUEST,
+ AutofillId autofillId = credentialOption
+ .getCandidateQueryData()
+ .getParcelable(CredentialProviderService.EXTRA_AUTOFILL_ID, AutofillId.class);
+ if (autofillId != null && Flags.autofillCredmanIntegration()) {
+ intent.putExtra(CredentialProviderService.EXTRA_AUTOFILL_ID, autofillId);
+ }
+ return intent.putExtra(
+ CredentialProviderService.EXTRA_GET_CREDENTIAL_REQUEST,
new GetCredentialRequest(
- mCallingAppInfo, List.of(mBeginGetOptionToCredentialOptionMap.get(id))));
+ mCallingAppInfo,
+ List.of(credentialOption)));
}
private Intent setUpFillInIntentWithQueryRequest() {
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
index 6aa135a..43e47d7 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
@@ -241,6 +241,7 @@
import static android.provider.Telephony.Carriers.ENFORCE_MANAGED_URI;
import static android.provider.Telephony.Carriers.INVALID_APN_ID;
import static android.security.keystore.AttestationUtils.USE_INDIVIDUAL_ATTESTATION;
+
import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.PROVISIONING_ENTRY_POINT_ADB;
import static com.android.internal.widget.LockPatternUtils.CREDENTIAL_TYPE_NONE;
import static com.android.internal.widget.LockPatternUtils.StrongAuthTracker.STRONG_AUTH_REQUIRED_AFTER_DPM_LOCK_NOW;
@@ -15781,57 +15782,19 @@
} else {
long ident = mInjector.binderClearCallingIdentity();
try {
- // TODO(b/277908283): check in the policy engine instead of calling user manager.
- List<UserManager.EnforcingUser> sources = mUserManager
- .getUserRestrictionSources(restriction, UserHandle.of(userId));
- if (sources == null) {
- // The restriction is not enforced.
- return null;
- }
- int sizeBefore = sources.size();
- if (sizeBefore > 1) {
- Slogf.d(LOG_TAG, "getEnforcingAdminAndUserDetailsInternal(%d, %s): "
- + "%d sources found, excluding those set by UserManager",
- userId, restriction, sizeBefore);
- sources = getDevicePolicySources(sources);
- }
- if (sources.isEmpty()) {
- // The restriction is not enforced (or is just enforced by the system)
+ if (getEnforcingAdminsForRestrictionInternal(userId, restriction).size() == 0) {
return null;
}
- if (sources.size() > 1) {
- // In this case, we'll show an admin support dialog that does not
- // specify the admin.
- // TODO(b/128928355): if this restriction is enforced by multiple DPCs, return
- // the admin for the calling user.
- Slogf.w(LOG_TAG, "getEnforcingAdminAndUserDetailsInternal(%d, %s): multiple "
- + "sources for restriction %s on user %d",
- userId, restriction, restriction, userId);
+ ActiveAdmin admin = getMostProbableDPCAdminForLocalPolicy(userId);
+ if (admin != null) {
result = new Bundle();
- result.putInt(Intent.EXTRA_USER_ID, userId);
+ result.putInt(Intent.EXTRA_USER_ID, admin.getUserHandle().getIdentifier());
+ result.putParcelable(DevicePolicyManager.EXTRA_DEVICE_ADMIN,
+ admin.info.getComponent());
return result;
}
- final UserManager.EnforcingUser enforcingUser = sources.get(0);
- final int sourceType = enforcingUser.getUserRestrictionSource();
- if (sourceType == UserManager.RESTRICTION_SOURCE_PROFILE_OWNER
- || sourceType == UserManager.RESTRICTION_SOURCE_DEVICE_OWNER) {
- ActiveAdmin admin = getMostProbableDPCAdminForLocalPolicy(userId);
- if (admin != null) {
- result = new Bundle();
- result.putInt(Intent.EXTRA_USER_ID, admin.getUserHandle().getIdentifier());
- result.putParcelable(DevicePolicyManager.EXTRA_DEVICE_ADMIN,
- admin.info.getComponent());
- return result;
- }
- } else if (sourceType == UserManager.RESTRICTION_SOURCE_SYSTEM) {
- /*
- * In this case, the user restriction is enforced by the system.
- * So we won't show an admin support intent, even if it is also
- * enforced by a profile/device owner.
- */
- return null;
- }
+ return null;
} finally {
mInjector.binderRestoreCallingIdentity(ident);
}
diff --git a/services/foldables/devicestateprovider/tests/Android.bp b/services/foldables/devicestateprovider/tests/Android.bp
index a8db05e..84a6df3 100644
--- a/services/foldables/devicestateprovider/tests/Android.bp
+++ b/services/foldables/devicestateprovider/tests/Android.bp
@@ -20,11 +20,11 @@
"foldable-device-state-provider",
"androidx.test.rules",
"junit",
- "truth-prebuilt",
+ "truth",
"mockito-target-extended-minus-junit4",
"androidx.test.uiautomator_uiautomator",
"androidx.test.ext.junit",
"testables",
],
- test_suites: ["device-tests"]
+ test_suites: ["device-tests"],
}
diff --git a/services/java/com/android/server/SystemServer.java b/services/java/com/android/server/SystemServer.java
index 57fa12d..49ad84a 100644
--- a/services/java/com/android/server/SystemServer.java
+++ b/services/java/com/android/server/SystemServer.java
@@ -264,6 +264,8 @@
"com.android.server.backup.BackupManagerService$Lifecycle";
private static final String APPWIDGET_SERVICE_CLASS =
"com.android.server.appwidget.AppWidgetService";
+ private static final String ARC_SYSTEM_HEALTH_SERVICE =
+ "com.android.server.arc.health.ArcSystemHealthService";
private static final String VOICE_RECOGNITION_MANAGER_SERVICE_CLASS =
"com.android.server.voiceinteraction.VoiceInteractionManagerService";
private static final String APP_HIBERNATION_SERVICE_CLASS =
@@ -1287,6 +1289,12 @@
}
}
+ if (Build.IS_ARC) {
+ t.traceBegin("StartArcSystemHealthService");
+ mSystemServiceManager.startService(ARC_SYSTEM_HEALTH_SERVICE);
+ t.traceEnd();
+ }
+
t.traceBegin("StartUserManagerService");
mSystemServiceManager.startService(UserManagerService.LifeCycle.class);
t.traceEnd();
diff --git a/services/robotests/backup/Android.bp b/services/robotests/backup/Android.bp
index e04dd68..8b9efb3 100644
--- a/services/robotests/backup/Android.bp
+++ b/services/robotests/backup/Android.bp
@@ -59,7 +59,7 @@
"mockito-robolectric-prebuilt",
"platform-test-annotations",
"testng",
- "truth-prebuilt",
+ "truth",
],
instrumentation_for: "BackupFrameworksServicesLib",
diff --git a/services/tests/InputMethodSystemServerTests/Android.bp b/services/tests/InputMethodSystemServerTests/Android.bp
index 36446f6..ffe6dc5 100644
--- a/services/tests/InputMethodSystemServerTests/Android.bp
+++ b/services/tests/InputMethodSystemServerTests/Android.bp
@@ -44,7 +44,7 @@
"service-permission.stubs.system_server",
"servicestests-core-utils",
"servicestests-utils-mockito-extended",
- "truth-prebuilt",
+ "truth",
],
libs: [
@@ -92,7 +92,7 @@
"service-permission.stubs.system_server",
"servicestests-core-utils",
"servicestests-utils-mockito-extended",
- "truth-prebuilt",
+ "truth",
"SimpleImeTestingLib",
"SimpleImeImsLib",
],
diff --git a/services/tests/PackageManager/packageinstaller/Android.bp b/services/tests/PackageManager/packageinstaller/Android.bp
index 35d754b..e8fce8e 100644
--- a/services/tests/PackageManager/packageinstaller/Android.bp
+++ b/services/tests/PackageManager/packageinstaller/Android.bp
@@ -32,7 +32,7 @@
"androidx.test.runner",
"junit",
"kotlin-test",
- "truth-prebuilt",
+ "truth",
],
platform_apis: true,
test_suites: ["device-tests"],
diff --git a/services/tests/PackageManagerComponentOverrideTests/Android.bp b/services/tests/PackageManagerComponentOverrideTests/Android.bp
index bc36970..00850a5 100644
--- a/services/tests/PackageManagerComponentOverrideTests/Android.bp
+++ b/services/tests/PackageManagerComponentOverrideTests/Android.bp
@@ -38,7 +38,7 @@
"service-permission.stubs.system_server",
"servicestests-utils-mockito-extended",
"testng", // TODO: remove once Android migrates to JUnit 4.12, which provides assertThrows
- "truth-prebuilt",
+ "truth",
],
jni_libs: [
diff --git a/services/tests/PackageManagerServiceTests/appenumeration/Android.bp b/services/tests/PackageManagerServiceTests/appenumeration/Android.bp
index 9c4e6fd..ad7af44 100644
--- a/services/tests/PackageManagerServiceTests/appenumeration/Android.bp
+++ b/services/tests/PackageManagerServiceTests/appenumeration/Android.bp
@@ -29,7 +29,7 @@
static_libs: [
"compatibility-device-util-axt",
"androidx.test.runner",
- "truth-prebuilt",
+ "truth",
"Harrier",
],
platform_apis: true,
diff --git a/services/tests/PackageManagerServiceTests/host/Android.bp b/services/tests/PackageManagerServiceTests/host/Android.bp
index ce28682..6eacef7 100644
--- a/services/tests/PackageManagerServiceTests/host/Android.bp
+++ b/services/tests/PackageManagerServiceTests/host/Android.bp
@@ -30,7 +30,7 @@
libs: [
"tradefed",
"junit",
- "truth-prebuilt",
+ "truth",
],
static_libs: [
"ApexInstallHelper",
diff --git a/services/tests/PackageManagerServiceTests/host/test-apps/DeviceSide/Android.bp b/services/tests/PackageManagerServiceTests/host/test-apps/DeviceSide/Android.bp
index 462c580..cea9c59 100644
--- a/services/tests/PackageManagerServiceTests/host/test-apps/DeviceSide/Android.bp
+++ b/services/tests/PackageManagerServiceTests/host/test-apps/DeviceSide/Android.bp
@@ -38,6 +38,6 @@
"junit-params",
"androidx.test.ext.junit",
"androidx.test.rules",
- "truth-prebuilt",
+ "truth",
],
}
diff --git a/services/tests/PackageManagerServiceTests/host/test-apps/OverlayActor/Android.bp b/services/tests/PackageManagerServiceTests/host/test-apps/OverlayActor/Android.bp
index 5718474..ed5f2b5 100644
--- a/services/tests/PackageManagerServiceTests/host/test-apps/OverlayActor/Android.bp
+++ b/services/tests/PackageManagerServiceTests/host/test-apps/OverlayActor/Android.bp
@@ -28,6 +28,6 @@
"androidx.test.runner",
"junit",
"kotlin-test",
- "truth-prebuilt",
+ "truth",
],
}
diff --git a/services/tests/PackageManagerServiceTests/server/Android.bp b/services/tests/PackageManagerServiceTests/server/Android.bp
index a1d846e..3aca1ca 100644
--- a/services/tests/PackageManagerServiceTests/server/Android.bp
+++ b/services/tests/PackageManagerServiceTests/server/Android.bp
@@ -41,7 +41,7 @@
"mockito-target-minus-junit4",
"platform-test-annotations",
"ShortcutManagerTestUtils",
- "truth-prebuilt",
+ "truth",
"testables",
"platformprotosnano",
"framework-protos",
@@ -51,7 +51,7 @@
"servicestests-utils",
"service-permission.impl",
"testng",
- "truth-prebuilt",
+ "truth",
"junit",
"junit-params",
"platform-compat-test-rules",
diff --git a/services/tests/PackageManagerServiceTests/unit/Android.bp b/services/tests/PackageManagerServiceTests/unit/Android.bp
index 9b3b8c35..85059838 100644
--- a/services/tests/PackageManagerServiceTests/unit/Android.bp
+++ b/services/tests/PackageManagerServiceTests/unit/Android.bp
@@ -37,7 +37,7 @@
"services.core",
"servicestests-utils",
"servicestests-core-utils",
- "truth-prebuilt",
+ "truth",
],
jni_libs: [
"libdexmakerjvmtiagent",
diff --git a/services/tests/RemoteProvisioningServiceTests/Android.bp b/services/tests/RemoteProvisioningServiceTests/Android.bp
index fc2c085..19c9136 100644
--- a/services/tests/RemoteProvisioningServiceTests/Android.bp
+++ b/services/tests/RemoteProvisioningServiceTests/Android.bp
@@ -30,8 +30,8 @@
"mockito-target",
"service-rkp.impl",
"services.core",
- "truth-prebuilt",
- "truth-java8-extension-jar",
+ "truth",
+ "truth-java8-extension",
],
test_suites: [
"device-tests",
diff --git a/services/tests/apexsystemservices/Android.bp b/services/tests/apexsystemservices/Android.bp
index e724e804..9dacfea 100644
--- a/services/tests/apexsystemservices/Android.bp
+++ b/services/tests/apexsystemservices/Android.bp
@@ -34,7 +34,7 @@
"compatibility-host-util",
"cts-install-lib-host",
"frameworks-base-hostutils",
- "truth-prebuilt",
+ "truth",
"modules-utils-build-testing",
],
test_suites: [
diff --git a/services/tests/displayservicetests/src/com/android/server/display/DisplayDeviceConfigTest.java b/services/tests/displayservicetests/src/com/android/server/display/DisplayDeviceConfigTest.java
index 6ef150c..c37d21a 100644
--- a/services/tests/displayservicetests/src/com/android/server/display/DisplayDeviceConfigTest.java
+++ b/services/tests/displayservicetests/src/com/android/server/display/DisplayDeviceConfigTest.java
@@ -179,6 +179,89 @@
}
@Test
+ public void testPowerThrottlingConfigFromDisplayConfig() throws IOException {
+ setupDisplayDeviceConfigFromDisplayConfigFile();
+
+ DisplayDeviceConfig.PowerThrottlingConfigData powerThrottlingConfigData =
+ mDisplayDeviceConfig.getPowerThrottlingConfigData();
+ assertNotNull(powerThrottlingConfigData);
+ assertEquals(0.1f, powerThrottlingConfigData.brightnessLowestCapAllowed, SMALL_DELTA);
+ assertEquals(10, powerThrottlingConfigData.pollingWindowMillis);
+ }
+
+ @Test
+ public void testPowerThrottlingDataFromDisplayConfig() throws IOException {
+ setupDisplayDeviceConfigFromDisplayConfigFile();
+
+ List<DisplayDeviceConfig.PowerThrottlingData.ThrottlingLevel>
+ defaultThrottlingLevels = new ArrayList<>();
+ defaultThrottlingLevels.add(
+ new DisplayDeviceConfig.PowerThrottlingData.ThrottlingLevel(
+ DisplayDeviceConfig.convertThermalStatus(ThermalStatus.light), 800f
+ ));
+ defaultThrottlingLevels.add(
+ new DisplayDeviceConfig.PowerThrottlingData.ThrottlingLevel(
+ DisplayDeviceConfig.convertThermalStatus(ThermalStatus.moderate), 600f
+ ));
+ defaultThrottlingLevels.add(
+ new DisplayDeviceConfig.PowerThrottlingData.ThrottlingLevel(
+ DisplayDeviceConfig.convertThermalStatus(ThermalStatus.severe), 400f
+ ));
+ defaultThrottlingLevels.add(
+ new DisplayDeviceConfig.PowerThrottlingData.ThrottlingLevel(
+ DisplayDeviceConfig.convertThermalStatus(ThermalStatus.critical), 200f
+ ));
+ defaultThrottlingLevels.add(
+ new DisplayDeviceConfig.PowerThrottlingData.ThrottlingLevel(
+ DisplayDeviceConfig.convertThermalStatus(ThermalStatus.emergency), 100f
+ ));
+ defaultThrottlingLevels.add(
+ new DisplayDeviceConfig.PowerThrottlingData.ThrottlingLevel(
+ DisplayDeviceConfig.convertThermalStatus(ThermalStatus.shutdown), 50f
+ ));
+
+ DisplayDeviceConfig.PowerThrottlingData defaultThrottlingData =
+ new DisplayDeviceConfig.PowerThrottlingData(defaultThrottlingLevels);
+
+ List<DisplayDeviceConfig.PowerThrottlingData.ThrottlingLevel>
+ concurrentThrottlingLevels = new ArrayList<>();
+ concurrentThrottlingLevels.add(
+ new DisplayDeviceConfig.PowerThrottlingData.ThrottlingLevel(
+ DisplayDeviceConfig.convertThermalStatus(ThermalStatus.light), 800f
+ ));
+ concurrentThrottlingLevels.add(
+ new DisplayDeviceConfig.PowerThrottlingData.ThrottlingLevel(
+ DisplayDeviceConfig.convertThermalStatus(ThermalStatus.moderate), 600f
+ ));
+ concurrentThrottlingLevels.add(
+ new DisplayDeviceConfig.PowerThrottlingData.ThrottlingLevel(
+ DisplayDeviceConfig.convertThermalStatus(ThermalStatus.severe), 400f
+ ));
+ concurrentThrottlingLevels.add(
+ new DisplayDeviceConfig.PowerThrottlingData.ThrottlingLevel(
+ DisplayDeviceConfig.convertThermalStatus(ThermalStatus.critical), 200f
+ ));
+ concurrentThrottlingLevels.add(
+ new DisplayDeviceConfig.PowerThrottlingData.ThrottlingLevel(
+ DisplayDeviceConfig.convertThermalStatus(ThermalStatus.emergency), 100f
+ ));
+ concurrentThrottlingLevels.add(
+ new DisplayDeviceConfig.PowerThrottlingData.ThrottlingLevel(
+ DisplayDeviceConfig.convertThermalStatus(ThermalStatus.shutdown), 50f
+ ));
+ DisplayDeviceConfig.PowerThrottlingData concurrentThrottlingData =
+ new DisplayDeviceConfig.PowerThrottlingData(concurrentThrottlingLevels);
+
+ HashMap<String, DisplayDeviceConfig.PowerThrottlingData> throttlingDataMap =
+ new HashMap<>(2);
+ throttlingDataMap.put("default", defaultThrottlingData);
+ throttlingDataMap.put("concurrent", concurrentThrottlingData);
+
+ assertEquals(throttlingDataMap,
+ mDisplayDeviceConfig.getPowerThrottlingDataMapByThrottlingId());
+ }
+
+ @Test
public void testConfigValuesFromConfigResource() {
setupDisplayDeviceConfigFromConfigResourceFile();
verifyConfigValuesFromConfigResource();
@@ -845,6 +928,64 @@
+ "</screenBrightnessRampSlowIncreaseIdle>\n";
}
+ private String getPowerThrottlingConfig() {
+ return "<powerThrottlingConfig >\n"
+ + "<brightnessLowestCapAllowed>0.1</brightnessLowestCapAllowed>\n"
+ + "<pollingWindowMillis>10</pollingWindowMillis>\n"
+ + "<powerThrottlingMap>\n"
+ + "<powerThrottlingPoint>\n"
+ + "<thermalStatus>light</thermalStatus>\n"
+ + "<powerQuotaMilliWatts>800</powerQuotaMilliWatts>\n"
+ + "</powerThrottlingPoint>\n"
+ + "<powerThrottlingPoint>\n"
+ + "<thermalStatus>moderate</thermalStatus>\n"
+ + "<powerQuotaMilliWatts>600</powerQuotaMilliWatts>\n"
+ + "</powerThrottlingPoint>\n"
+ + "<powerThrottlingPoint>\n"
+ + "<thermalStatus>severe</thermalStatus>\n"
+ + "<powerQuotaMilliWatts>400</powerQuotaMilliWatts>\n"
+ + "</powerThrottlingPoint>\n"
+ + "<powerThrottlingPoint>\n"
+ + "<thermalStatus>critical</thermalStatus>\n"
+ + "<powerQuotaMilliWatts>200</powerQuotaMilliWatts>\n"
+ + "</powerThrottlingPoint>\n"
+ + "<powerThrottlingPoint>\n"
+ + "<thermalStatus>emergency</thermalStatus>\n"
+ + "<powerQuotaMilliWatts>100</powerQuotaMilliWatts>\n"
+ + "</powerThrottlingPoint>\n"
+ + "<powerThrottlingPoint>\n"
+ + "<thermalStatus>shutdown</thermalStatus>\n"
+ + "<powerQuotaMilliWatts>50</powerQuotaMilliWatts>\n"
+ + "</powerThrottlingPoint>\n"
+ + "</powerThrottlingMap>\n"
+ + "<powerThrottlingMap id=\"concurrent\">\n"
+ + "<powerThrottlingPoint>\n"
+ + "<thermalStatus>light</thermalStatus>\n"
+ + "<powerQuotaMilliWatts>800</powerQuotaMilliWatts>\n"
+ + "</powerThrottlingPoint>\n"
+ + "<powerThrottlingPoint>\n"
+ + "<thermalStatus>moderate</thermalStatus>\n"
+ + "<powerQuotaMilliWatts>600</powerQuotaMilliWatts>\n"
+ + "</powerThrottlingPoint>\n"
+ + "<powerThrottlingPoint>\n"
+ + "<thermalStatus>severe</thermalStatus>\n"
+ + "<powerQuotaMilliWatts>400</powerQuotaMilliWatts>\n"
+ + "</powerThrottlingPoint>\n"
+ + "<powerThrottlingPoint>\n"
+ + "<thermalStatus>critical</thermalStatus>\n"
+ + "<powerQuotaMilliWatts>200</powerQuotaMilliWatts>\n"
+ + "</powerThrottlingPoint>\n"
+ + "<powerThrottlingPoint>\n"
+ + "<thermalStatus>emergency</thermalStatus>\n"
+ + "<powerQuotaMilliWatts>100</powerQuotaMilliWatts>\n"
+ + "</powerThrottlingPoint>\n"
+ + "<powerThrottlingPoint>\n"
+ + "<thermalStatus>shutdown</thermalStatus>\n"
+ + "<powerQuotaMilliWatts>50</powerQuotaMilliWatts>\n"
+ + "</powerThrottlingPoint>\n"
+ + "</powerThrottlingMap>\n"
+ + "</powerThrottlingConfig>\n";
+ }
private String getScreenBrightnessRampCapsIdle() {
return "<screenBrightnessRampIncreaseMaxIdleMillis>"
+ "4000"
@@ -915,6 +1056,7 @@
+ "</displayBrightnessPoint>\n"
+ "</displayBrightnessMapping>\n"
+ "</autoBrightness>\n"
+ + getPowerThrottlingConfig()
+ "<highBrightnessMode enabled=\"true\">\n"
+ "<transitionPoint>" + BRIGHTNESS[1] + "</transitionPoint>\n"
+ "<minimumLux>10000</minimumLux>\n"
diff --git a/services/tests/inprocesstests/Android.bp b/services/tests/inprocesstests/Android.bp
index 7c237ac..086e84b 100644
--- a/services/tests/inprocesstests/Android.bp
+++ b/services/tests/inprocesstests/Android.bp
@@ -14,7 +14,7 @@
"androidx.test.core",
"androidx.test.rules",
"services.core",
- "truth-prebuilt",
+ "truth",
"platform-test-annotations",
],
test_suites: ["general-tests"],
diff --git a/services/tests/mockingservicestests/Android.bp b/services/tests/mockingservicestests/Android.bp
index 101498a..063af57 100644
--- a/services/tests/mockingservicestests/Android.bp
+++ b/services/tests/mockingservicestests/Android.bp
@@ -46,6 +46,7 @@
"androidx.test.espresso.core",
"androidx.test.espresso.contrib",
"androidx.test.ext.truth",
+ "flag-junit",
"frameworks-base-testutils",
"hamcrest-library",
"kotlin-test",
@@ -67,7 +68,7 @@
"servicestests-core-utils",
"servicestests-utils-mockito-extended",
"testables",
- "truth-prebuilt",
+ "truth",
// TODO: remove once Android migrates to JUnit 4.12, which provides assertThrows
"testng",
"compatibility-device-util-axt",
diff --git a/services/tests/mockingservicestests/jni/Android.bp b/services/tests/mockingservicestests/jni/Android.bp
index f1dc1fa..1eb9888 100644
--- a/services/tests/mockingservicestests/jni/Android.bp
+++ b/services/tests/mockingservicestests/jni/Android.bp
@@ -22,6 +22,7 @@
srcs: [
":lib_cachedAppOptimizer_native",
":lib_gameManagerService_native",
+ ":lib_oomConnection_native",
"onload.cpp",
],
@@ -42,6 +43,7 @@
"libgui",
"libhidlbase",
"liblog",
+ "libmemevents",
"libmeminfo",
"libnativehelper",
"libprocessgroup",
diff --git a/services/tests/mockingservicestests/jni/onload.cpp b/services/tests/mockingservicestests/jni/onload.cpp
index 23ccb22..fb91051 100644
--- a/services/tests/mockingservicestests/jni/onload.cpp
+++ b/services/tests/mockingservicestests/jni/onload.cpp
@@ -26,6 +26,7 @@
namespace android {
int register_android_server_am_CachedAppOptimizer(JNIEnv* env);
int register_android_server_app_GameManagerService(JNIEnv* env);
+int register_android_server_am_OomConnection(JNIEnv* env);
};
using namespace android;
@@ -42,6 +43,7 @@
ALOG_ASSERT(env, "Could not retrieve the env!");
register_android_server_am_CachedAppOptimizer(env);
register_android_server_app_GameManagerService(env);
+ register_android_server_am_OomConnection(env);
return JNI_VERSION_1_4;
}
diff --git a/services/tests/mockingservicestests/src/com/android/server/DeviceIdleControllerTest.java b/services/tests/mockingservicestests/src/com/android/server/DeviceIdleControllerTest.java
index 5b1508b..be29163 100644
--- a/services/tests/mockingservicestests/src/com/android/server/DeviceIdleControllerTest.java
+++ b/services/tests/mockingservicestests/src/com/android/server/DeviceIdleControllerTest.java
@@ -1290,7 +1290,8 @@
}
@Test
- public void testLightStepIdleStateIdlingTimeIncreases() {
+ public void testLightStepIdleStateIdlingTimeIncreasesExponentially() {
+ mConstants.LIGHT_IDLE_INCREASE_LINEARLY = false;
final long maintenanceTimeMs = 60_000L;
mConstants.LIGHT_IDLE_MAINTENANCE_MIN_BUDGET = maintenanceTimeMs;
mConstants.LIGHT_IDLE_MAINTENANCE_MAX_BUDGET = maintenanceTimeMs;
@@ -1335,13 +1336,88 @@
eq(mInjector.nowElapsed + idlingTimeMs),
anyLong(), anyString(), any(), any(Handler.class));
- for (int i = 0; i < 2; ++i) {
+ for (int i = 0; i < 10; ++i) {
// IDLE->MAINTENANCE alarm
mInjector.nowElapsed = mDeviceIdleController.getNextLightAlarmTimeForTesting();
alarmListener.onAlarm();
verifyLightStateConditions(LIGHT_STATE_IDLE_MAINTENANCE);
long maintenanceExpiryTime = mInjector.nowElapsed + maintenanceTimeMs;
idlingTimeMs *= mConstants.LIGHT_IDLE_FACTOR;
+ idlingTimeMs = Math.min(idlingTimeMs, mConstants.LIGHT_MAX_IDLE_TIMEOUT);
+ // Set MAINTENANCE->IDLE
+ alarmManagerInOrder.verify(mAlarmManager).setWindow(
+ eq(AlarmManager.ELAPSED_REALTIME_WAKEUP),
+ eq(maintenanceExpiryTime),
+ anyLong(), anyString(), any(), any(Handler.class));
+
+ // MAINTENANCE->IDLE alarm
+ mInjector.nowElapsed = mDeviceIdleController.getNextLightAlarmTimeForTesting();
+ alarmListener.onAlarm();
+ verifyLightStateConditions(LIGHT_STATE_IDLE);
+ // Set IDLE->MAINTENANCE again
+ alarmManagerInOrder.verify(mAlarmManager).setWindow(
+ eq(AlarmManager.ELAPSED_REALTIME_WAKEUP),
+ eq(mInjector.nowElapsed + idlingTimeMs),
+ anyLong(), anyString(), any(), any(Handler.class));
+ }
+ }
+
+ @Test
+ public void testLightStepIdleStateIdlingTimeIncreasesLinearly() {
+ mConstants.LIGHT_IDLE_INCREASE_LINEARLY = true;
+ final long maintenanceTimeMs = 60_000L;
+ mConstants.LIGHT_IDLE_MAINTENANCE_MIN_BUDGET = maintenanceTimeMs;
+ mConstants.LIGHT_IDLE_MAINTENANCE_MAX_BUDGET = maintenanceTimeMs;
+ mConstants.LIGHT_IDLE_TIMEOUT = 5 * 60_000L;
+ mConstants.LIGHT_MAX_IDLE_TIMEOUT = 30 * 60_000L;
+ mConstants.LIGHT_IDLE_FACTOR = 2f;
+ mConstants.LIGHT_IDLE_LINEAR_INCREASE_FACTOR_MS = 2 * 60_000L;
+
+ setNetworkConnected(true);
+ mDeviceIdleController.setJobsActive(false);
+ mDeviceIdleController.setAlarmsActive(false);
+ mDeviceIdleController.setActiveIdleOpsForTest(0);
+
+ InOrder alarmManagerInOrder = inOrder(mAlarmManager);
+
+ final ArgumentCaptor<AlarmManager.OnAlarmListener> alarmListenerCaptor = ArgumentCaptor
+ .forClass(AlarmManager.OnAlarmListener.class);
+ doNothing().when(mAlarmManager).setWindow(anyInt(), anyLong(), anyLong(),
+ eq("DeviceIdleController.light"), alarmListenerCaptor.capture(), any());
+
+ // Set state to INACTIVE.
+ mDeviceIdleController.becomeActiveLocked("testing", 0);
+ setChargingOn(false);
+ setScreenOn(false);
+ verifyLightStateConditions(LIGHT_STATE_INACTIVE);
+ long idlingTimeMs = mConstants.LIGHT_IDLE_TIMEOUT;
+ final long idleAfterInactiveExpiryTime =
+ mInjector.nowElapsed + mConstants.LIGHT_IDLE_AFTER_INACTIVE_TIMEOUT;
+ alarmManagerInOrder.verify(mAlarmManager).setWindow(
+ eq(AlarmManager.ELAPSED_REALTIME_WAKEUP),
+ eq(idleAfterInactiveExpiryTime),
+ anyLong(), anyString(), any(), any(Handler.class));
+
+ final AlarmManager.OnAlarmListener alarmListener =
+ alarmListenerCaptor.getAllValues().get(0);
+
+ // INACTIVE -> IDLE alarm
+ mInjector.nowElapsed = mDeviceIdleController.getNextLightAlarmTimeForTesting();
+ alarmListener.onAlarm();
+ verifyLightStateConditions(LIGHT_STATE_IDLE);
+ alarmManagerInOrder.verify(mAlarmManager).setWindow(
+ eq(AlarmManager.ELAPSED_REALTIME_WAKEUP),
+ eq(mInjector.nowElapsed + idlingTimeMs),
+ anyLong(), anyString(), any(), any(Handler.class));
+
+ for (int i = 0; i < 10; ++i) {
+ // IDLE->MAINTENANCE alarm
+ mInjector.nowElapsed = mDeviceIdleController.getNextLightAlarmTimeForTesting();
+ alarmListener.onAlarm();
+ verifyLightStateConditions(LIGHT_STATE_IDLE_MAINTENANCE);
+ long maintenanceExpiryTime = mInjector.nowElapsed + maintenanceTimeMs;
+ idlingTimeMs += mConstants.LIGHT_IDLE_LINEAR_INCREASE_FACTOR_MS;
+ idlingTimeMs = Math.min(idlingTimeMs, mConstants.LIGHT_MAX_IDLE_TIMEOUT);
// Set MAINTENANCE->IDLE
alarmManagerInOrder.verify(mAlarmManager).setWindow(
eq(AlarmManager.ELAPSED_REALTIME_WAKEUP),
diff --git a/services/tests/mockingservicestests/src/com/android/server/am/ActivityManagerInternalTest.java b/services/tests/mockingservicestests/src/com/android/server/am/ActivityManagerInternalTest.java
index 64cc397..9ba4f5b 100644
--- a/services/tests/mockingservicestests/src/com/android/server/am/ActivityManagerInternalTest.java
+++ b/services/tests/mockingservicestests/src/com/android/server/am/ActivityManagerInternalTest.java
@@ -218,4 +218,9 @@
assertEquals(errMsg, Thread.State.TERMINATED, getState());
}
}
+
+ // TODO: [b/302724778] Remove manual JNI load
+ static {
+ System.loadLibrary("mockingservicestestjni");
+ }
}
diff --git a/services/tests/mockingservicestests/src/com/android/server/am/ActivityManagerServiceTest.java b/services/tests/mockingservicestests/src/com/android/server/am/ActivityManagerServiceTest.java
index 2bc66ac..40b5458 100644
--- a/services/tests/mockingservicestests/src/com/android/server/am/ActivityManagerServiceTest.java
+++ b/services/tests/mockingservicestests/src/com/android/server/am/ActivityManagerServiceTest.java
@@ -1210,4 +1210,9 @@
return returnValueForstartUserOnSecondaryDisplay;
}
}
+
+ // TODO: [b/302724778] Remove manual JNI load
+ static {
+ System.loadLibrary("mockingservicestestjni");
+ }
}
diff --git a/services/tests/mockingservicestests/src/com/android/server/am/AppChildProcessTest.java b/services/tests/mockingservicestests/src/com/android/server/am/AppChildProcessTest.java
index 1c0989c..9391d5b 100644
--- a/services/tests/mockingservicestests/src/com/android/server/am/AppChildProcessTest.java
+++ b/services/tests/mockingservicestests/src/com/android/server/am/AppChildProcessTest.java
@@ -338,4 +338,8 @@
}
}
+ // TODO: [b/302724778] Remove manual JNI load
+ static {
+ System.loadLibrary("mockingservicestestjni");
+ }
}
diff --git a/services/tests/mockingservicestests/src/com/android/server/am/ApplicationExitInfoTest.java b/services/tests/mockingservicestests/src/com/android/server/am/ApplicationExitInfoTest.java
index d56229c..e15942b 100644
--- a/services/tests/mockingservicestests/src/com/android/server/am/ApplicationExitInfoTest.java
+++ b/services/tests/mockingservicestests/src/com/android/server/am/ApplicationExitInfoTest.java
@@ -1126,4 +1126,9 @@
};
}
}
+
+ // TODO: [b/302724778] Remove manual JNI load
+ static {
+ System.loadLibrary("mockingservicestestjni");
+ }
}
diff --git a/services/tests/mockingservicestests/src/com/android/server/am/AsyncProcessStartTest.java b/services/tests/mockingservicestests/src/com/android/server/am/AsyncProcessStartTest.java
index 0abf46b..596a3f3 100644
--- a/services/tests/mockingservicestests/src/com/android/server/am/AsyncProcessStartTest.java
+++ b/services/tests/mockingservicestests/src/com/android/server/am/AsyncProcessStartTest.java
@@ -284,4 +284,9 @@
return app;
}
+
+ // TODO: [b/302724778] Remove manual JNI load
+ static {
+ System.loadLibrary("mockingservicestestjni");
+ }
}
diff --git a/services/tests/mockingservicestests/src/com/android/server/am/CacheOomRankerTest.java b/services/tests/mockingservicestests/src/com/android/server/am/CacheOomRankerTest.java
index 434d200..dfb8fda 100644
--- a/services/tests/mockingservicestests/src/com/android/server/am/CacheOomRankerTest.java
+++ b/services/tests/mockingservicestests/src/com/android/server/am/CacheOomRankerTest.java
@@ -803,4 +803,9 @@
return mHandler;
}
}
+
+ // TODO: [b/302724778] Remove manual JNI load
+ static {
+ System.loadLibrary("mockingservicestestjni");
+ }
}
diff --git a/services/tests/mockingservicestests/src/com/android/server/am/ServiceTimeoutTest.java b/services/tests/mockingservicestests/src/com/android/server/am/ServiceTimeoutTest.java
index fd1b068..7ec27be 100644
--- a/services/tests/mockingservicestests/src/com/android/server/am/ServiceTimeoutTest.java
+++ b/services/tests/mockingservicestests/src/com/android/server/am/ServiceTimeoutTest.java
@@ -201,4 +201,9 @@
return mActiveServices;
}
}
+
+ // TODO: [b/302724778] Remove manual JNI load
+ static {
+ System.loadLibrary("mockingservicestestjni");
+ }
}
diff --git a/services/tests/mockingservicestests/src/com/android/server/job/controllers/ConnectivityControllerTest.java b/services/tests/mockingservicestests/src/com/android/server/job/controllers/ConnectivityControllerTest.java
index 2b56ea8..bded9b4 100644
--- a/services/tests/mockingservicestests/src/com/android/server/job/controllers/ConnectivityControllerTest.java
+++ b/services/tests/mockingservicestests/src/com/android/server/job/controllers/ConnectivityControllerTest.java
@@ -34,6 +34,7 @@
import static com.android.dx.mockito.inline.extended.ExtendedMockito.mock;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.spy;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.when;
+import static com.android.server.job.Flags.FLAG_RELAX_PREFETCH_CONNECTIVITY_CONSTRAINT_ONLY_ON_CHARGER;
import static com.android.server.job.JobSchedulerService.FREQUENT_INDEX;
import static com.android.server.job.JobSchedulerService.RARE_INDEX;
import static com.android.server.job.JobSchedulerService.RESTRICTED_INDEX;
@@ -66,6 +67,7 @@
import android.os.Build;
import android.os.Looper;
import android.os.SystemClock;
+import android.platform.test.flag.junit.SetFlagsRule;
import android.telephony.CellSignalStrength;
import android.telephony.SignalStrength;
import android.telephony.TelephonyCallback;
@@ -79,6 +81,7 @@
import com.android.server.net.NetworkPolicyManagerInternal;
import org.junit.Before;
+import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.ArgumentCaptor;
@@ -107,6 +110,9 @@
@Mock
private PackageManager mPackageManager;
+ @Rule
+ public final SetFlagsRule mSetFlagsRule = new SetFlagsRule();
+
private Constants mConstants;
private FlexibilityController mFlexibilityController;
@@ -898,7 +904,8 @@
assertTrue(controller.isSatisfied(latePrefetchUnknownUp, net, caps, mConstants));
}
- // Metered network is only when prefetching, late, and in opportunistic quota
+ // Metered network is only when prefetching, charging*, late, and in opportunistic quota
+ // *Charging only when the flag is enabled
{
final Network net = mock(Network.class);
final NetworkCapabilities caps = createCapabilitiesBuilder()
@@ -910,6 +917,8 @@
assertFalse(controller.isSatisfied(latePrefetch, net, caps, mConstants));
assertFalse(controller.isSatisfied(latePrefetchUnknownDown, net, caps, mConstants));
assertFalse(controller.isSatisfied(latePrefetchUnknownUp, net, caps, mConstants));
+ mSetFlagsRule.disableFlags(FLAG_RELAX_PREFETCH_CONNECTIVITY_CONSTRAINT_ONLY_ON_CHARGER);
+ when(mService.isBatteryCharging()).thenReturn(false);
when(mNetPolicyManagerInternal.getSubscriptionOpportunisticQuota(
any(), eq(NetworkPolicyManagerInternal.QUOTA_TYPE_JOBS)))
@@ -918,6 +927,21 @@
// Only relax restrictions when we at least know the estimated download bytes.
assertFalse(controller.isSatisfied(latePrefetchUnknownDown, net, caps, mConstants));
assertTrue(controller.isSatisfied(latePrefetchUnknownUp, net, caps, mConstants));
+
+ mSetFlagsRule.enableFlags(FLAG_RELAX_PREFETCH_CONNECTIVITY_CONSTRAINT_ONLY_ON_CHARGER);
+ when(mNetPolicyManagerInternal.getSubscriptionOpportunisticQuota(
+ any(), eq(NetworkPolicyManagerInternal.QUOTA_TYPE_JOBS)))
+ .thenReturn(9876543210L);
+ assertFalse(controller.isSatisfied(latePrefetch, net, caps, mConstants));
+ // Only relax restrictions when we at least know the estimated download bytes.
+ assertFalse(controller.isSatisfied(latePrefetchUnknownDown, net, caps, mConstants));
+ assertFalse(controller.isSatisfied(latePrefetchUnknownUp, net, caps, mConstants));
+
+ when(mService.isBatteryCharging()).thenReturn(true);
+ assertTrue(controller.isSatisfied(latePrefetch, net, caps, mConstants));
+ // Only relax restrictions when we at least know the estimated download bytes.
+ assertFalse(controller.isSatisfied(latePrefetchUnknownDown, net, caps, mConstants));
+ assertTrue(controller.isSatisfied(latePrefetchUnknownUp, net, caps, mConstants));
}
}
diff --git a/services/tests/mockingservicestests/src/com/android/server/pm/UserManagerServiceTest.java b/services/tests/mockingservicestests/src/com/android/server/pm/UserManagerServiceTest.java
index 6304270..305569e 100644
--- a/services/tests/mockingservicestests/src/com/android/server/pm/UserManagerServiceTest.java
+++ b/services/tests/mockingservicestests/src/com/android/server/pm/UserManagerServiceTest.java
@@ -308,7 +308,6 @@
addDefaultProfileAndParent();
mUms.setBootUser(PROFILE_USER_ID);
-
// Boot user not switchable so return most recently in foreground.
assertWithMessage("getBootUser")
.that(mUmi.getBootUser(/* waitUntilSet= */ false)).isEqualTo(OTHER_USER_ID);
@@ -523,6 +522,24 @@
.isFalse();
}
+ @Test
+ public void testCreateUserWithLongName_TruncatesName() {
+ UserInfo user = mUms.createUserWithThrow(generateLongString(), USER_TYPE_FULL_SECONDARY, 0);
+ assertThat(user.name.length()).isEqualTo(500);
+ UserInfo user1 = mUms.createUserWithThrow("Test", USER_TYPE_FULL_SECONDARY, 0);
+ assertThat(user1.name.length()).isEqualTo(4);
+ }
+
+ private String generateLongString() {
+ String partialString = "Test Name Test Name Test Name Test Name Test Name Test Name Test "
+ + "Name Test Name Test Name Test Name "; //String of length 100
+ StringBuilder resultString = new StringBuilder();
+ for (int i = 0; i < 660; i++) {
+ resultString.append(partialString);
+ }
+ return resultString.toString();
+ }
+
private void removeNonSystemUsers() {
for (UserInfo user : mUms.getUsers(true)) {
if (!user.getUserHandle().isSystem()) {
diff --git a/services/tests/powerstatstests/Android.bp b/services/tests/powerstatstests/Android.bp
index 8ab4507..18a4f00 100644
--- a/services/tests/powerstatstests/Android.bp
+++ b/services/tests/powerstatstests/Android.bp
@@ -16,7 +16,7 @@
"coretests-aidl",
"platformprotosnano",
"junit",
- "truth-prebuilt",
+ "truth",
"androidx.test.runner",
"androidx.test.ext.junit",
"androidx.test.ext.truth",
diff --git a/services/tests/servicestests/Android.bp b/services/tests/servicestests/Android.bp
index 20d8a5d..2ece8c7 100644
--- a/services/tests/servicestests/Android.bp
+++ b/services/tests/servicestests/Android.bp
@@ -2,6 +2,13 @@
// Build FrameworksServicesTests package
//########################################################################
+java_defaults {
+ name: "FrameworksServicesTests-jni-defaults",
+ jni_libs: [
+ "libservicestestjni",
+ ],
+}
+
package {
// See: http://go/android-license-faq
// A large-scale-change added 'default_applicable_licenses' to import
@@ -13,6 +20,9 @@
android_test {
name: "FrameworksServicesTests",
+ defaults: [
+ "FrameworksServicesTests-jni-defaults",
+ ],
// Include all test java files.
srcs: [
@@ -51,7 +61,7 @@
"mockito-target-minus-junit4",
"platform-test-annotations",
"ShortcutManagerTestUtils",
- "truth-prebuilt",
+ "truth",
"testables",
"androidx.test.uiautomator_uiautomator",
"platformprotosnano",
@@ -62,7 +72,7 @@
// TODO: remove once Android migrates to JUnit 4.12,
// which provides assertThrows
"testng",
- "truth-prebuilt",
+ "truth",
"junit",
"junit-params",
"ActivityContext",
diff --git a/services/tests/servicestests/jni/Android.bp b/services/tests/servicestests/jni/Android.bp
new file mode 100644
index 0000000..174beb8
--- /dev/null
+++ b/services/tests/servicestests/jni/Android.bp
@@ -0,0 +1,58 @@
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_base_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_base_license"],
+}
+
+cc_library_shared {
+ name: "libservicestestjni",
+
+ defaults: ["android.hardware.graphics.common-ndk_shared"],
+
+ cflags: [
+ "-Wall",
+ "-Werror",
+ "-Wno-unused-parameter",
+ "-Wthread-safety",
+ ],
+
+ srcs: [
+ ":lib_cachedAppOptimizer_native",
+ ":lib_gameManagerService_native",
+ ":lib_oomConnection_native",
+ "onload.cpp",
+ ],
+
+ include_dirs: [
+ "frameworks/base/libs",
+ "frameworks/native/services",
+ "frameworks/native/libs/math/include",
+ "frameworks/native/libs/ui/include",
+ "system/memory/libmeminfo/include",
+ ],
+
+ shared_libs: [
+ "libandroid",
+ "libandroid_runtime",
+ "libbase",
+ "libbinder",
+ "libgralloctypes",
+ "libgui",
+ "libhidlbase",
+ "liblog",
+ "libmeminfo",
+ "libmemevents",
+ "libnativehelper",
+ "libprocessgroup",
+ "libutils",
+ "libcutils",
+ "android.hardware.graphics.bufferqueue@1.0",
+ "android.hardware.graphics.bufferqueue@2.0",
+ "android.hardware.graphics.common@1.2",
+ "android.hardware.graphics.mapper@4.0",
+ "android.hidl.token@1.0-utils",
+ ],
+}
\ No newline at end of file
diff --git a/services/tests/servicestests/jni/onload.cpp b/services/tests/servicestests/jni/onload.cpp
new file mode 100644
index 0000000..f160b3d
--- /dev/null
+++ b/services/tests/servicestests/jni/onload.cpp
@@ -0,0 +1,48 @@
+/*
+ * Copyright (C) 2023 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.
+ */
+
+/*
+ * this is a mini native libaray for cached app optimizer tests to run properly. It
+ * loads all the native methods necessary.
+ */
+#include <nativehelper/JNIHelp.h>
+#include "jni.h"
+#include "utils/Log.h"
+#include "utils/misc.h"
+
+namespace android {
+int register_android_server_am_CachedAppOptimizer(JNIEnv* env);
+int register_android_server_app_GameManagerService(JNIEnv* env);
+int register_android_server_am_OomConnection(JNIEnv* env);
+};
+
+using namespace android;
+
+extern "C" jint JNI_OnLoad(JavaVM* vm, void* /* reserved */)
+{
+ JNIEnv* env = NULL;
+ jint result = -1;
+
+ if (vm->GetEnv((void**) &env, JNI_VERSION_1_4) != JNI_OK) {
+ ALOGE("GetEnv failed!");
+ return result;
+ }
+ ALOG_ASSERT(env, "Could not retrieve the env!");
+ register_android_server_am_CachedAppOptimizer(env);
+ register_android_server_app_GameManagerService(env);
+ register_android_server_am_OomConnection(env);
+ return JNI_VERSION_1_4;
+}
diff --git a/services/tests/servicestests/src/com/android/server/am/AnrHelperTest.java b/services/tests/servicestests/src/com/android/server/am/AnrHelperTest.java
index acdfee9..c0051c6 100644
--- a/services/tests/servicestests/src/com/android/server/am/AnrHelperTest.java
+++ b/services/tests/servicestests/src/com/android/server/am/AnrHelperTest.java
@@ -172,4 +172,9 @@
anyString(), any(), any(), any(), anyBoolean(), any(), eq(mAuxExecutorService),
anyBoolean(), anyBoolean(), any());
}
+
+ // TODO: [b/302724778] Remove manual JNI load
+ static {
+ System.loadLibrary("servicestestjni");
+ }
}
diff --git a/services/tests/servicestests/src/com/android/server/am/AnrTimerTest.java b/services/tests/servicestests/src/com/android/server/am/AnrTimerTest.java
index 9fdbdda..70527ce 100644
--- a/services/tests/servicestests/src/com/android/server/am/AnrTimerTest.java
+++ b/services/tests/servicestests/src/com/android/server/am/AnrTimerTest.java
@@ -228,6 +228,7 @@
TestHandler mTestHandler;
TestInjector(int skip, boolean immediate) {
+ super(mHandler);
mTracker = new TestTracker(skip);
mImmediate = immediate;
}
@@ -249,9 +250,16 @@
return mTestHandler;
}
+ @Override
AnrTimer.CpuTracker getTracker() {
return mTracker;
}
+
+ /** For test purposes, always enable the feature. */
+ @Override
+ boolean getFeatureEnabled() {
+ return true;
+ }
}
// Tests
@@ -261,7 +269,6 @@
// 4. Start a couple of timers. Verify max active timers. Discard one and verify the active
// count drops by 1. Accept one and verify the active count drops by 1.
-
@Test
public void testSimpleTimeout() throws Exception {
// Create an immediate TestHandler.
diff --git a/services/tests/uiservicestests/Android.bp b/services/tests/uiservicestests/Android.bp
index 1d37f9d..d1f4961 100644
--- a/services/tests/uiservicestests/Android.bp
+++ b/services/tests/uiservicestests/Android.bp
@@ -39,7 +39,7 @@
"hamcrest-library",
"servicestests-utils",
"testables",
- "truth-prebuilt",
+ "truth",
// TODO: remove once Android migrates to JUnit 4.12,
// which provides assertThrows
"testng",
diff --git a/services/tests/uiservicestests/src/com/android/server/notification/NotificationBitmapJobServiceTest.java b/services/tests/uiservicestests/src/com/android/server/notification/NotificationBitmapJobServiceTest.java
index 312057ee..348d1bf 100644
--- a/services/tests/uiservicestests/src/com/android/server/notification/NotificationBitmapJobServiceTest.java
+++ b/services/tests/uiservicestests/src/com/android/server/notification/NotificationBitmapJobServiceTest.java
@@ -44,6 +44,12 @@
import org.mockito.Mock;
import java.lang.reflect.Field;
+import java.time.Duration;
+import java.time.Instant;
+import java.time.LocalDate;
+import java.time.LocalTime;
+import java.time.ZonedDateTime;
+import java.time.ZoneId;
@RunWith(AndroidTestingRunner.class)
public class NotificationBitmapJobServiceTest extends UiServiceTestCase {
@@ -103,17 +109,39 @@
@Test
public void testGetTimeUntilRemoval_beforeToday2am_returnTimeUntilToday2am() {
- final long timeUntilRemoval = mJobService.getTimeUntilRemoval(/* now= */ 1,
- /* today2AM= */ 2, /* tomorrow2AM= */ 26);
+ ZoneId zoneId = ZoneId.systemDefault();
+ ZonedDateTime now = Instant.now().atZone(zoneId);
+ LocalDate today = now.toLocalDate();
- assertThat(timeUntilRemoval).isEqualTo(1);
+ LocalTime oneAM = LocalTime.of(/* hour= */ 1, /* minute= */ 0);
+ LocalTime twoAM = LocalTime.of(/* hour= */ 2, /* minute= */ 0);
+
+ ZonedDateTime today1AM = ZonedDateTime.of(today, oneAM, zoneId);
+ ZonedDateTime today2AM = ZonedDateTime.of(today, twoAM, zoneId);
+ ZonedDateTime tomorrow2AM = today2AM.plusDays(1);
+
+ final long msUntilRemoval = mJobService.getTimeUntilRemoval(
+ /* now= */ today1AM, today2AM, tomorrow2AM);
+
+ assertThat(msUntilRemoval).isEqualTo(Duration.ofHours(1).toMillis());
}
@Test
public void testGetTimeUntilRemoval_afterToday2am_returnTimeUntilTomorrow2am() {
- final long timeUntilRemoval = mJobService.getTimeUntilRemoval(/* now= */ 3,
- /* today2AM= */ 2, /* tomorrow2AM= */ 26);
+ ZoneId zoneId = ZoneId.systemDefault();
+ ZonedDateTime now = Instant.now().atZone(zoneId);
+ LocalDate today = now.toLocalDate();
- assertThat(timeUntilRemoval).isEqualTo(23);
+ LocalTime threeAM = LocalTime.of(/* hour= */ 3, /* minute= */ 0);
+ LocalTime twoAM = LocalTime.of(/* hour= */ 2, /* minute= */ 0);
+
+ ZonedDateTime today3AM = ZonedDateTime.of(today, threeAM, zoneId);
+ ZonedDateTime today2AM = ZonedDateTime.of(today, twoAM, zoneId);
+ ZonedDateTime tomorrow2AM = today2AM.plusDays(1);
+
+ final long msUntilRemoval = mJobService.getTimeUntilRemoval(/* now= */ today3AM,
+ today2AM, tomorrow2AM);
+
+ assertThat(msUntilRemoval).isEqualTo(Duration.ofHours(23).toMillis());
}
}
\ No newline at end of file
diff --git a/services/tests/uiservicestests/src/com/android/server/notification/NotificationHistoryJobServiceTest.java b/services/tests/uiservicestests/src/com/android/server/notification/NotificationHistoryJobServiceTest.java
index d758e71..3499a12 100644
--- a/services/tests/uiservicestests/src/com/android/server/notification/NotificationHistoryJobServiceTest.java
+++ b/services/tests/uiservicestests/src/com/android/server/notification/NotificationHistoryJobServiceTest.java
@@ -71,10 +71,10 @@
@Before
public void setUp() throws Exception {
mJobService = new NotificationHistoryJobService();
+ mJobService.attachBaseContext(mContext);
+ mJobService.onCreate();
+ mJobService.onBind(/* intent= */ null); // Create JobServiceEngine within JobService.
- final Field field = JobService.class.getDeclaredField("mEngine");
- field.setAccessible(true);
- field.set(mJobService, mock(JobServiceEngine.class));
mContext.addMockSystemService(JobScheduler.class, mMockJobScheduler);
// add NotificationManagerInternal to LocalServices
diff --git a/services/tests/uiservicestests/src/com/android/server/notification/NotificationListenerServiceTest.java b/services/tests/uiservicestests/src/com/android/server/notification/NotificationListenerServiceTest.java
index 7a55143..c05f814 100644
--- a/services/tests/uiservicestests/src/com/android/server/notification/NotificationListenerServiceTest.java
+++ b/services/tests/uiservicestests/src/com/android/server/notification/NotificationListenerServiceTest.java
@@ -462,7 +462,7 @@
}
private void detailedAssertEquals(NotificationRankingUpdate a, NotificationRankingUpdate b) {
- assertEquals(a.getRankingMap(), b.getRankingMap());
+ detailedAssertEquals(a.getRankingMap(), b.getRankingMap());
}
private void detailedAssertEquals(String comment, Ranking a, Ranking b) {
diff --git a/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java b/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java
index c98d235..91129a1 100755
--- a/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java
+++ b/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java
@@ -91,7 +91,7 @@
import static com.android.server.am.PendingIntentRecord.FLAG_ACTIVITY_SENDER;
import static com.android.server.am.PendingIntentRecord.FLAG_BROADCAST_SENDER;
import static com.android.server.am.PendingIntentRecord.FLAG_SERVICE_SENDER;
-import static com.android.server.notification.NotificationManagerService.BITMAP_EXPIRATION_TIME_MS;
+import static com.android.server.notification.NotificationManagerService.BITMAP_DURATION;
import static com.android.server.notification.NotificationManagerService.DEFAULT_MAX_NOTIFICATION_ENQUEUE_RATE;
import static com.android.server.notification.NotificationRecordLogger.NotificationReportedEvent.NOTIFICATION_ADJUSTED;
import static com.android.server.notification.NotificationRecordLogger.NotificationReportedEvent.NOTIFICATION_POSTED;
@@ -11381,7 +11381,7 @@
long timePostedMs = System.currentTimeMillis();
if (isExpired) {
- timePostedMs -= BITMAP_EXPIRATION_TIME_MS;
+ timePostedMs -= BITMAP_DURATION.toMillis();
}
StatusBarNotification sbn = new StatusBarNotification(PKG, PKG, 8, "tag", mUid, 0,
notification, UserHandle.getUserHandleForUid(mUid), null, timePostedMs);
diff --git a/services/tests/vibrator/src/com/android/server/vibrator/HapticFeedbackVibrationProviderTest.java b/services/tests/vibrator/src/com/android/server/vibrator/HapticFeedbackVibrationProviderTest.java
index a91bd2b..0003555 100644
--- a/services/tests/vibrator/src/com/android/server/vibrator/HapticFeedbackVibrationProviderTest.java
+++ b/services/tests/vibrator/src/com/android/server/vibrator/HapticFeedbackVibrationProviderTest.java
@@ -16,6 +16,8 @@
package com.android.server.vibrator;
+import static android.os.VibrationAttributes.FLAG_BYPASS_INTERRUPTION_POLICY;
+import static android.os.VibrationAttributes.FLAG_BYPASS_USER_VIBRATION_INTENSITY_OFF;
import static android.os.VibrationEffect.Composition.PRIMITIVE_CLICK;
import static android.os.VibrationEffect.Composition.PRIMITIVE_TICK;
import static android.os.VibrationEffect.EFFECT_TEXTURE_TICK;
@@ -24,8 +26,13 @@
import static android.view.HapticFeedbackConstants.CONTEXT_CLICK;
import static android.view.HapticFeedbackConstants.SAFE_MODE_ENABLED;
import static android.view.HapticFeedbackConstants.TEXT_HANDLE_MOVE;
+import static android.view.HapticFeedbackConstants.SCROLL_ITEM_FOCUS;
+import static android.view.HapticFeedbackConstants.SCROLL_LIMIT;
+import static android.view.HapticFeedbackConstants.SCROLL_TICK;
+
import static com.google.common.truth.Truth.assertThat;
+import static com.google.common.truth.Truth.assertWithMessage;
import static org.mockito.Mockito.when;
@@ -37,6 +44,7 @@
import android.os.VibratorInfo;
import android.util.AtomicFile;
import android.util.SparseArray;
+import android.view.flags.FeatureFlags;
import androidx.test.InstrumentationRegistry;
@@ -59,23 +67,25 @@
private static final VibrationEffect PRIMITIVE_CLICK_EFFECT =
VibrationEffect.startComposition().addPrimitive(PRIMITIVE_CLICK, 0.3497f).compose();
+ private static final int[] SCROLL_FEEDBACK_CONSTANTS =
+ new int[] {SCROLL_ITEM_FOCUS, SCROLL_LIMIT, SCROLL_TICK};
private Context mContext = InstrumentationRegistry.getContext();
private VibratorInfo mVibratorInfo = VibratorInfo.EMPTY_VIBRATOR_INFO;
@Mock private Resources mResourcesMock;
+ @Mock private FeatureFlags mViewFeatureFlags;
@Test
public void testNonExistentCustomization_useDefault() throws Exception {
// No customization file is set.
- HapticFeedbackVibrationProvider hapticProvider =
- new HapticFeedbackVibrationProvider(mResourcesMock, mVibratorInfo);
+ HapticFeedbackVibrationProvider hapticProvider = createProviderWithDefaultCustomizations();
assertThat(hapticProvider.getVibrationForHapticFeedback(CONTEXT_CLICK))
.isEqualTo(VibrationEffect.get(EFFECT_TICK));
// The customization file specifies no customization.
setupCustomizationFile("<haptic-feedback-constants></haptic-feedback-constants>");
- hapticProvider = new HapticFeedbackVibrationProvider(mResourcesMock, mVibratorInfo);
+ hapticProvider = createProviderWithDefaultCustomizations();
assertThat(hapticProvider.getVibrationForHapticFeedback(CONTEXT_CLICK))
.isEqualTo(VibrationEffect.get(EFFECT_TICK));
@@ -84,8 +94,7 @@
@Test
public void testExceptionParsingCustomizations_useDefault() throws Exception {
setupCustomizationFile("<bad-xml></bad-xml>");
- HapticFeedbackVibrationProvider hapticProvider =
- new HapticFeedbackVibrationProvider(mResourcesMock, mVibratorInfo);
+ HapticFeedbackVibrationProvider hapticProvider = createProviderWithDefaultCustomizations();
assertThat(hapticProvider.getVibrationForHapticFeedback(CONTEXT_CLICK))
.isEqualTo(VibrationEffect.get(EFFECT_TICK));
@@ -97,8 +106,7 @@
SparseArray<VibrationEffect> customizations = new SparseArray<>();
customizations.put(CONTEXT_CLICK, PRIMITIVE_CLICK_EFFECT);
- HapticFeedbackVibrationProvider hapticProvider =
- new HapticFeedbackVibrationProvider(mResourcesMock, mVibratorInfo, customizations);
+ HapticFeedbackVibrationProvider hapticProvider = createProvider(customizations);
// The override for `CONTEXT_CLICK` is used.
assertThat(hapticProvider.getVibrationForHapticFeedback(CONTEXT_CLICK))
@@ -118,8 +126,7 @@
+ "</haptic-feedback-constants>";
setupCustomizationFile(xml);
- HapticFeedbackVibrationProvider hapticProvider =
- new HapticFeedbackVibrationProvider(mResourcesMock, mVibratorInfo);
+ HapticFeedbackVibrationProvider hapticProvider = createProviderWithDefaultCustomizations();
// The override for `CONTEXT_CLICK` is not used because the vibration is not supported.
assertThat(hapticProvider.getVibrationForHapticFeedback(CONTEXT_CLICK))
@@ -137,15 +144,12 @@
customizations.put(TEXT_HANDLE_MOVE, PRIMITIVE_CLICK_EFFECT);
// Test with a customization available for `TEXT_HANDLE_MOVE`.
- HapticFeedbackVibrationProvider hapticProvider =
- new HapticFeedbackVibrationProvider(mResourcesMock, mVibratorInfo, customizations);
+ HapticFeedbackVibrationProvider hapticProvider = createProvider(customizations);
assertThat(hapticProvider.getVibrationForHapticFeedback(TEXT_HANDLE_MOVE)).isNull();
// Test with no customization available for `TEXT_HANDLE_MOVE`.
- hapticProvider =
- new HapticFeedbackVibrationProvider(
- mResourcesMock, mVibratorInfo, /* hapticCustomizations= */ null);
+ hapticProvider = createProvider(/* customizations= */ null);
assertThat(hapticProvider.getVibrationForHapticFeedback(TEXT_HANDLE_MOVE)).isNull();
}
@@ -158,16 +162,13 @@
customizations.put(TEXT_HANDLE_MOVE, PRIMITIVE_CLICK_EFFECT);
// Test with a customization available for `TEXT_HANDLE_MOVE`.
- HapticFeedbackVibrationProvider hapticProvider =
- new HapticFeedbackVibrationProvider(mResourcesMock, mVibratorInfo, customizations);
+ HapticFeedbackVibrationProvider hapticProvider = createProvider(customizations);
assertThat(hapticProvider.getVibrationForHapticFeedback(TEXT_HANDLE_MOVE))
.isEqualTo(PRIMITIVE_CLICK_EFFECT);
// Test with no customization available for `TEXT_HANDLE_MOVE`.
- hapticProvider =
- new HapticFeedbackVibrationProvider(
- mResourcesMock, mVibratorInfo, /* hapticCustomizations= */ null);
+ hapticProvider = createProvider(/* customizations= */ null);
assertThat(hapticProvider.getVibrationForHapticFeedback(TEXT_HANDLE_MOVE))
.isEqualTo(VibrationEffect.get(EFFECT_TEXTURE_TICK));
@@ -181,15 +182,13 @@
SparseArray<VibrationEffect> customizations = new SparseArray<>();
customizations.put(SAFE_MODE_ENABLED, PRIMITIVE_CLICK_EFFECT);
- HapticFeedbackVibrationProvider hapticProvider =
- new HapticFeedbackVibrationProvider(mResourcesMock, mVibratorInfo, customizations);
+ HapticFeedbackVibrationProvider hapticProvider = createProvider(customizations);
assertThat(hapticProvider.getVibrationForHapticFeedback(SAFE_MODE_ENABLED))
.isEqualTo(PRIMITIVE_CLICK_EFFECT);
mockSafeModeEnabledVibration(null);
- hapticProvider =
- new HapticFeedbackVibrationProvider(mResourcesMock, mVibratorInfo, customizations);
+ hapticProvider = createProvider(customizations);
assertThat(hapticProvider.getVibrationForHapticFeedback(SAFE_MODE_ENABLED))
.isEqualTo(PRIMITIVE_CLICK_EFFECT);
@@ -199,9 +198,7 @@
public void testNoValidCustomizationPresentForSafeModeEnabled_resourceBasedVibrationUsed()
throws Exception {
mockSafeModeEnabledVibration(10, 20, 30, 40);
- HapticFeedbackVibrationProvider hapticProvider =
- new HapticFeedbackVibrationProvider(
- mResourcesMock, mVibratorInfo, /* hapticCustomizations= */ null);
+ HapticFeedbackVibrationProvider hapticProvider = createProvider(/* customizations= */ null);
assertThat(hapticProvider.getVibrationForHapticFeedback(SAFE_MODE_ENABLED))
.isEqualTo(VibrationEffect.createWaveform(new long[] {10, 20, 30, 40}, -1));
@@ -211,35 +208,65 @@
public void testNoValidCustomizationAndResourcePresentForSafeModeEnabled_noVibrationUsed()
throws Exception {
mockSafeModeEnabledVibration(null);
- HapticFeedbackVibrationProvider hapticProvider =
- new HapticFeedbackVibrationProvider(
- mResourcesMock, mVibratorInfo, /* hapticCustomizations= */ null);
+ HapticFeedbackVibrationProvider hapticProvider = createProvider(/* customizations= */ null);
assertThat(hapticProvider.getVibrationForHapticFeedback(SAFE_MODE_ENABLED)).isNull();
}
@Test
public void testVibrationAttribute_forNotBypassingIntensitySettings() {
- HapticFeedbackVibrationProvider hapticProvider =
- new HapticFeedbackVibrationProvider(mResourcesMock, mVibratorInfo);
+ HapticFeedbackVibrationProvider hapticProvider = createProviderWithDefaultCustomizations();
VibrationAttributes attrs = hapticProvider.getVibrationAttributesForHapticFeedback(
SAFE_MODE_ENABLED, /* bypassVibrationIntensitySetting= */ false);
- assertThat(attrs.getFlags() & VibrationAttributes.FLAG_BYPASS_USER_VIBRATION_INTENSITY_OFF)
- .isEqualTo(0);
+ assertThat(attrs.isFlagSet(FLAG_BYPASS_USER_VIBRATION_INTENSITY_OFF)).isFalse();
}
@Test
public void testVibrationAttribute_forByassingIntensitySettings() {
- HapticFeedbackVibrationProvider hapticProvider =
- new HapticFeedbackVibrationProvider(mResourcesMock, mVibratorInfo);
+ HapticFeedbackVibrationProvider hapticProvider = createProviderWithDefaultCustomizations();
VibrationAttributes attrs = hapticProvider.getVibrationAttributesForHapticFeedback(
SAFE_MODE_ENABLED, /* bypassVibrationIntensitySetting= */ true);
- assertThat(attrs.getFlags() & VibrationAttributes.FLAG_BYPASS_USER_VIBRATION_INTENSITY_OFF)
- .isNotEqualTo(0);
+ assertThat(attrs.isFlagSet(FLAG_BYPASS_USER_VIBRATION_INTENSITY_OFF)).isTrue();
+ }
+
+ @Test
+ public void testVibrationAttribute_scrollFeedback_scrollApiFlagOn_bypassInterruptPolicy() {
+ when(mViewFeatureFlags.scrollFeedbackApi()).thenReturn(true);
+ HapticFeedbackVibrationProvider hapticProvider = createProviderWithDefaultCustomizations();
+
+ for (int effectId : SCROLL_FEEDBACK_CONSTANTS) {
+ VibrationAttributes attrs = hapticProvider.getVibrationAttributesForHapticFeedback(
+ effectId, /* bypassVibrationIntensitySetting= */ false);
+ assertWithMessage("Expected FLAG_BYPASS_INTERRUPTION_POLICY for effect " + effectId)
+ .that(attrs.isFlagSet(FLAG_BYPASS_INTERRUPTION_POLICY)).isTrue();
+ }
+ }
+
+ @Test
+ public void testVibrationAttribute_scrollFeedback_scrollApiFlagOff_noBypassInterruptPolicy() {
+ when(mViewFeatureFlags.scrollFeedbackApi()).thenReturn(false);
+ HapticFeedbackVibrationProvider hapticProvider = createProviderWithDefaultCustomizations();
+
+ for (int effectId : SCROLL_FEEDBACK_CONSTANTS) {
+ VibrationAttributes attrs = hapticProvider.getVibrationAttributesForHapticFeedback(
+ effectId, /* bypassVibrationIntensitySetting= */ false);
+ assertWithMessage("Expected no FLAG_BYPASS_INTERRUPTION_POLICY for effect " + effectId)
+ .that(attrs.isFlagSet(FLAG_BYPASS_INTERRUPTION_POLICY)).isFalse();
+ }
+ }
+
+ private HapticFeedbackVibrationProvider createProviderWithDefaultCustomizations() {
+ return createProvider(/* customizations= */ null);
+ }
+
+ private HapticFeedbackVibrationProvider createProvider(
+ SparseArray<VibrationEffect> customizations) {
+ return new HapticFeedbackVibrationProvider(
+ mResourcesMock, mVibratorInfo, customizations, mViewFeatureFlags);
}
private void mockVibratorPrimitiveSupport(int... supportedPrimitives) {
diff --git a/services/tests/vibrator/src/com/android/server/vibrator/VibratorManagerServiceTest.java b/services/tests/vibrator/src/com/android/server/vibrator/VibratorManagerServiceTest.java
index 0eec9cd..40e0e84 100644
--- a/services/tests/vibrator/src/com/android/server/vibrator/VibratorManagerServiceTest.java
+++ b/services/tests/vibrator/src/com/android/server/vibrator/VibratorManagerServiceTest.java
@@ -31,6 +31,7 @@
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.atLeastOnce;
import static org.mockito.Mockito.doAnswer;
+import static org.mockito.Mockito.doNothing;
import static org.mockito.Mockito.doThrow;
import static org.mockito.Mockito.inOrder;
import static org.mockito.Mockito.mock;
@@ -46,6 +47,7 @@
import android.content.ContentResolver;
import android.content.Context;
import android.content.ContextWrapper;
+import android.content.pm.PackageManager;
import android.content.pm.PackageManagerInternal;
import android.content.res.Resources;
import android.hardware.input.IInputManager;
@@ -87,6 +89,7 @@
import android.view.Display;
import android.view.HapticFeedbackConstants;
import android.view.InputDevice;
+import android.view.flags.FeatureFlags;
import androidx.test.InstrumentationRegistry;
import androidx.test.filters.FlakyTest;
@@ -172,6 +175,8 @@
private VirtualDeviceManagerInternal mVirtualDeviceManagerInternalMock;
@Mock
private AudioManager mAudioManagerMock;
+ @Mock
+ private FeatureFlags mViewFeatureFlags;
private final Map<Integer, FakeVibratorControllerProvider> mVibratorProviders = new HashMap<>();
@@ -321,7 +326,8 @@
HapticFeedbackVibrationProvider createHapticFeedbackVibrationProvider(
Resources resources, VibratorInfo vibratorInfo) {
return new HapticFeedbackVibrationProvider(
- resources, vibratorInfo, mHapticFeedbackVibrationMap);
+ resources, vibratorInfo, mHapticFeedbackVibrationMap,
+ mViewFeatureFlags);
}
});
return mService;
@@ -649,6 +655,42 @@
}
@Test
+ public void vibrate_withoutBypassFlagsPermissions_bypassFlagsNotApplied() throws Exception {
+ denyPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS);
+ denyPermission(android.Manifest.permission.MODIFY_PHONE_STATE);
+ denyPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING);
+
+ assertCanVibrateWithBypassFlags(false);
+ }
+
+ @Test
+ public void vibrate_withSecureSettingsPermission_bypassFlagsApplied() throws Exception {
+ grantPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS);
+ denyPermission(android.Manifest.permission.MODIFY_PHONE_STATE);
+ denyPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING);
+
+ assertCanVibrateWithBypassFlags(true);
+ }
+
+ @Test
+ public void vibrate_withModifyPhoneStatePermission_bypassFlagsApplied() throws Exception {
+ denyPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS);
+ grantPermission(android.Manifest.permission.MODIFY_PHONE_STATE);
+ denyPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING);
+
+ assertCanVibrateWithBypassFlags(true);
+ }
+
+ @Test
+ public void vibrate_withModifyAudioRoutingPermission_bypassFlagsApplied() throws Exception {
+ denyPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS);
+ denyPermission(android.Manifest.permission.MODIFY_PHONE_STATE);
+ grantPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING);
+
+ assertCanVibrateWithBypassFlags(true);
+ }
+
+ @Test
public void vibrate_withRingtone_usesRingerModeSettings() throws Exception {
mockVibrators(1);
FakeVibratorControllerProvider fakeVibrator = mVibratorProviders.get(1);
@@ -1166,7 +1208,7 @@
}
@Test
- public void vibrate_withTriggerCallback_finishesVibration() throws Exception {
+ public void vibrate_withriggerCallback_finishesVibration() throws Exception {
mockCapabilities(IVibratorManager.CAP_SYNC, IVibratorManager.CAP_PREPARE_COMPOSE);
mockVibrators(1, 2);
mVibratorProviders.get(1).setCapabilities(IVibrator.CAP_COMPOSE_EFFECTS);
@@ -1303,10 +1345,18 @@
}
@Test
- public void performHapticFeedback_doesNotRequirePermission() throws Exception {
+ public void performHapticFeedback_doesNotRequireVibrateOrBypassPermissions() throws Exception {
+ // Deny permissions that would have been required for regular vibrations, and check that
+ // the vibration proceed as expected to verify that haptic feedback does not need these
+ // permissions.
denyPermission(android.Manifest.permission.VIBRATE);
+ denyPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS);
+ denyPermission(android.Manifest.permission.MODIFY_PHONE_STATE);
+ denyPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING);
+ // Flag override to enable the scroll feedack constants to bypass interruption policies.
+ when(mViewFeatureFlags.scrollFeedbackApi()).thenReturn(true);
mHapticFeedbackVibrationMap.put(
- HapticFeedbackConstants.KEYBOARD_TAP,
+ HapticFeedbackConstants.SCROLL_TICK,
VibrationEffect.createPredefined(VibrationEffect.EFFECT_CLICK));
mockVibrators(1);
FakeVibratorControllerProvider fakeVibrator = mVibratorProviders.get(1);
@@ -1315,13 +1365,16 @@
HalVibration vibration =
performHapticFeedbackAndWaitUntilFinished(
- service, HapticFeedbackConstants.KEYBOARD_TAP, /* always= */ true);
+ service, HapticFeedbackConstants.SCROLL_TICK, /* always= */ true);
List<VibrationEffectSegment> playedSegments = fakeVibrator.getAllEffectSegments();
assertEquals(1, playedSegments.size());
PrebakedSegment segment = (PrebakedSegment) playedSegments.get(0);
assertEquals(VibrationEffect.EFFECT_CLICK, segment.getEffectId());
- assertEquals(VibrationAttributes.USAGE_TOUCH, vibration.callerInfo.attrs.getUsage());
+ VibrationAttributes attrs = vibration.callerInfo.attrs;
+ assertEquals(VibrationAttributes.USAGE_HARDWARE_FEEDBACK, attrs.getUsage());
+ assertTrue(attrs.isFlagSet(VibrationAttributes.FLAG_BYPASS_USER_VIBRATION_INTENSITY_OFF));
+ assertTrue(attrs.isFlagSet(VibrationAttributes.FLAG_BYPASS_INTERRUPTION_POLICY));
}
@Test
@@ -2261,6 +2314,31 @@
assertNull(metrics.halUnsupportedEffectsUsed);
}
+ private void assertCanVibrateWithBypassFlags(boolean expectedCanApplyBypassFlags)
+ throws Exception {
+ mockVibrators(1);
+ mVibratorProviders.get(1).setSupportedEffects(VibrationEffect.EFFECT_CLICK);
+ VibratorManagerService service = createSystemReadyService();
+
+ HalVibration vibration = vibrateAndWaitUntilFinished(
+ service,
+ VibrationEffect.createPredefined(VibrationEffect.EFFECT_CLICK),
+ new VibrationAttributes.Builder()
+ .setUsage(VibrationAttributes.USAGE_TOUCH)
+ .setFlags(
+ VibrationAttributes.FLAG_BYPASS_USER_VIBRATION_INTENSITY_OFF
+ | VibrationAttributes.FLAG_BYPASS_INTERRUPTION_POLICY)
+ .build());
+
+ VibrationAttributes attrs = vibration.callerInfo.attrs;
+ assertEquals(
+ expectedCanApplyBypassFlags,
+ attrs.isFlagSet(VibrationAttributes.FLAG_BYPASS_USER_VIBRATION_INTENSITY_OFF));
+ assertEquals(
+ expectedCanApplyBypassFlags,
+ attrs.isFlagSet(VibrationAttributes.FLAG_BYPASS_INTERRUPTION_POLICY));
+ }
+
private VibrationEffectSegment expectedPrebaked(int effectId) {
return expectedPrebaked(effectId, VibrationEffect.EFFECT_STRENGTH_MEDIUM);
}
@@ -2327,12 +2405,13 @@
return vib;
}
- private void vibrateAndWaitUntilFinished(VibratorManagerService service, VibrationEffect effect,
- VibrationAttributes attrs) throws InterruptedException {
- vibrateAndWaitUntilFinished(service, CombinedVibration.createParallel(effect), attrs);
+ private HalVibration vibrateAndWaitUntilFinished(VibratorManagerService service,
+ VibrationEffect effect, VibrationAttributes attrs) throws InterruptedException {
+ return vibrateAndWaitUntilFinished(
+ service, CombinedVibration.createParallel(effect), attrs);
}
- private void vibrateAndWaitUntilFinished(VibratorManagerService service,
+ private HalVibration vibrateAndWaitUntilFinished(VibratorManagerService service,
CombinedVibration effect, VibrationAttributes attrs) throws InterruptedException {
HalVibration vib =
service.vibrateWithPermissionCheck(UID, Display.DEFAULT_DISPLAY, PACKAGE_NAME,
@@ -2340,6 +2419,8 @@
if (vib != null) {
vib.waitForEnd();
}
+
+ return vib;
}
private void vibrate(VibratorManagerService service, VibrationEffect effect,
@@ -2368,7 +2449,15 @@
return predicateResult;
}
+ private void grantPermission(String permission) {
+ when(mContextSpy.checkCallingOrSelfPermission(permission))
+ .thenReturn(PackageManager.PERMISSION_GRANTED);
+ doNothing().when(mContextSpy).enforceCallingOrSelfPermission(eq(permission), anyString());
+ }
+
private void denyPermission(String permission) {
+ when(mContextSpy.checkCallingOrSelfPermission(permission))
+ .thenReturn(PackageManager.PERMISSION_DENIED);
doThrow(new SecurityException()).when(mContextSpy)
.enforceCallingOrSelfPermission(eq(permission), anyString());
}
diff --git a/services/tests/voiceinteractiontests/Android.bp b/services/tests/voiceinteractiontests/Android.bp
index e704ebf..744cb63 100644
--- a/services/tests/voiceinteractiontests/Android.bp
+++ b/services/tests/voiceinteractiontests/Android.bp
@@ -43,7 +43,7 @@
"services.soundtrigger",
"servicestests-core-utils",
"servicestests-utils-mockito-extended",
- "truth-prebuilt",
+ "truth",
],
libs: [
diff --git a/services/tests/wmtests/Android.bp b/services/tests/wmtests/Android.bp
index c2812a1..af39b2f 100644
--- a/services/tests/wmtests/Android.bp
+++ b/services/tests/wmtests/Android.bp
@@ -57,12 +57,14 @@
"platform-test-annotations",
"servicestests-utils",
"testng",
- "truth-prebuilt",
+ "truth",
"testables",
"hamcrest-library",
"platform-compat-test-rules",
"CtsSurfaceValidatorLib",
"service-sdksandbox.impl",
+ "com.android.window.flags.window-aconfig-java",
+ "flag-junit",
],
libs: [
diff --git a/services/tests/wmtests/AndroidManifest.xml b/services/tests/wmtests/AndroidManifest.xml
index 42e3383..762e23c 100644
--- a/services/tests/wmtests/AndroidManifest.xml
+++ b/services/tests/wmtests/AndroidManifest.xml
@@ -47,6 +47,8 @@
<uses-permission android:name="android.permission.FOREGROUND_SERVICE"/>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.MANAGE_MEDIA_PROJECTION"/>
+ <uses-permission android:name="android.permission.INTERNAL_SYSTEM_WINDOW"/>
+ <uses-permission android:name="android.permission.MONITOR_INPUT"/>
<!-- TODO: Remove largeHeap hack when memory leak is fixed (b/123984854) -->
<application android:debuggable="true"
@@ -104,6 +106,11 @@
android:showWhenLocked="true"
android:turnScreenOn="true" />
+ <activity android:name="android.app.Activity"
+ android:exported="true"
+ android:showWhenLocked="true"
+ android:turnScreenOn="true" />
+
<activity
android:name="androidx.test.core.app.InstrumentationActivityInvoker$EmptyActivity"
android:exported="true">
diff --git a/services/tests/wmtests/src/com/android/server/wm/RootWindowContainerTests.java b/services/tests/wmtests/src/com/android/server/wm/RootWindowContainerTests.java
index 3bc6450..c241033 100644
--- a/services/tests/wmtests/src/com/android/server/wm/RootWindowContainerTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/RootWindowContainerTests.java
@@ -549,10 +549,12 @@
// Let's pretend that the app has crashed.
firstActivity.app.setThread(null);
- mRootWindowContainer.finishTopCrashedActivities(firstActivity.app, "test");
+ final Task finishedTask = mRootWindowContainer.finishTopCrashedActivities(
+ firstActivity.app, "test");
// Verify that the root task was removed.
assertEquals(originalRootTaskCount, defaultTaskDisplayArea.getRootTaskCount());
+ assertEquals(rootTask, finishedTask);
}
/**
diff --git a/services/tests/wmtests/src/com/android/server/wm/SurfaceControlViewHostTests.java b/services/tests/wmtests/src/com/android/server/wm/SurfaceControlViewHostTests.java
index c1d5147..8119fd4 100644
--- a/services/tests/wmtests/src/com/android/server/wm/SurfaceControlViewHostTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/SurfaceControlViewHostTests.java
@@ -138,11 +138,11 @@
IWindow window = IWindow.Stub.asInterface(mActivity.mSurfaceView.getWindowToken());
WindowManagerGlobal.getWindowSession().grantEmbeddedWindowFocus(window,
- mScvh1.getFocusGrantToken(), true);
+ mScvh1.getInputTransferToken(), true);
assertTrue("Failed to gain focus for view1", waitForWindowFocus(mView1, true));
WindowManagerGlobal.getWindowSession().grantEmbeddedWindowFocus(window,
- mScvh2.getFocusGrantToken(), true);
+ mScvh2.getInputTransferToken(), true);
assertTrue("Failed to gain focus for view2", waitForWindowFocus(mView2, true));
}
diff --git a/services/tests/wmtests/src/com/android/server/wm/TrustedOverlayTests.java b/services/tests/wmtests/src/com/android/server/wm/TrustedOverlayTests.java
new file mode 100644
index 0000000..ac49839
--- /dev/null
+++ b/services/tests/wmtests/src/com/android/server/wm/TrustedOverlayTests.java
@@ -0,0 +1,217 @@
+/*
+ * Copyright 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.wm;
+
+import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_TRUSTED_OVERLAY;
+import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_PANEL;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+
+import android.app.Activity;
+import android.app.Instrumentation;
+import android.os.IBinder;
+import android.platform.test.annotations.Presubmit;
+import android.platform.test.annotations.RequiresFlagsDisabled;
+import android.platform.test.annotations.RequiresFlagsEnabled;
+import android.platform.test.flag.junit.CheckFlagsRule;
+import android.platform.test.flag.junit.DeviceFlagsValueProvider;
+import android.server.wm.BuildUtils;
+import android.server.wm.CtsWindowInfoUtils;
+import android.view.View;
+import android.view.ViewTreeObserver;
+import android.view.WindowManager;
+
+import androidx.test.ext.junit.rules.ActivityScenarioRule;
+import androidx.test.platform.app.InstrumentationRegistry;
+
+import com.android.window.flags.Flags;
+
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.TestName;
+
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
+
+@Presubmit
+public class TrustedOverlayTests {
+ private static final String TAG = "TrustedOverlayTests";
+ private static final long TIMEOUT_S = 5L * BuildUtils.HW_TIMEOUT_MULTIPLIER;
+
+ @Rule
+ public final CheckFlagsRule mCheckFlagsRule =
+ DeviceFlagsValueProvider.createCheckFlagsRule();
+
+ @Rule
+ public TestName mName = new TestName();
+
+ @Rule
+ public final ActivityScenarioRule<Activity> mActivityRule = new ActivityScenarioRule<>(
+ Activity.class);
+
+ private Instrumentation mInstrumentation;
+ private Activity mActivity;
+
+ @Before
+ public void setup() {
+ mInstrumentation = InstrumentationRegistry.getInstrumentation();
+ mActivityRule.getScenario().onActivity(activity -> {
+ mActivity = activity;
+ });
+ }
+
+ @RequiresFlagsDisabled(Flags.FLAG_SURFACE_TRUSTED_OVERLAY)
+ @Test
+ public void setTrustedOverlayInputWindow() throws InterruptedException {
+ testTrustedOverlayChildHelper(false);
+ }
+
+ @Test
+ @RequiresFlagsEnabled(Flags.FLAG_SURFACE_TRUSTED_OVERLAY)
+ public void setTrustedOverlayChildLayer() throws InterruptedException {
+ testTrustedOverlayChildHelper(true);
+ }
+
+ /**
+ * b/300659960 where setting spy window and trusted overlay were not happening in the same
+ * transaction causing the system to crash. This ensures there are no synchronization issues
+ * setting both spy window and trusted overlay.
+ */
+ @Test
+ public void setSpyWindowDoesntCrash() throws InterruptedException {
+ IBinder[] tokens = new IBinder[1];
+ CountDownLatch hostTokenReady = new CountDownLatch(1);
+ mInstrumentation.runOnMainSync(() -> {
+ WindowManager.LayoutParams params = mActivity.getWindow().getAttributes();
+ params.inputFeatures |= WindowManager.LayoutParams.INPUT_FEATURE_SPY;
+ params.privateFlags |= PRIVATE_FLAG_TRUSTED_OVERLAY;
+ mActivity.getWindow().setAttributes(params);
+
+ View rootView = mActivity.getWindow().getDecorView();
+ if (rootView.isAttachedToWindow()) {
+ tokens[0] = rootView.getWindowToken();
+ hostTokenReady.countDown();
+ } else {
+ rootView.getViewTreeObserver().addOnWindowAttachListener(
+ new ViewTreeObserver.OnWindowAttachListener() {
+ @Override
+ public void onWindowAttached() {
+ tokens[0] = rootView.getWindowToken();
+ hostTokenReady.countDown();
+ }
+
+ @Override
+ public void onWindowDetached() {
+ }
+ });
+ }
+ });
+
+ assertTrue("Failed to wait for host to get added",
+ hostTokenReady.await(TIMEOUT_S, TimeUnit.SECONDS));
+
+ boolean[] foundTrusted = new boolean[1];
+ CtsWindowInfoUtils.waitForWindowInfos(
+ windowInfos -> {
+ for (var windowInfo : windowInfos) {
+ if (windowInfo.windowToken == tokens[0] && windowInfo.isTrustedOverlay) {
+ foundTrusted[0] = true;
+ return true;
+ }
+ }
+ return false;
+ }, TIMEOUT_S, TimeUnit.SECONDS);
+
+ if (!foundTrusted[0]) {
+ CtsWindowInfoUtils.dumpWindowsOnScreen(TAG, mName.getMethodName());
+ }
+
+ assertTrue("Failed to find window or was not marked trusted", foundTrusted[0]);
+ }
+
+ private void testTrustedOverlayChildHelper(boolean expectedTrustedChild)
+ throws InterruptedException {
+ IBinder[] tokens = new IBinder[2];
+ CountDownLatch hostTokenReady = new CountDownLatch(1);
+ mInstrumentation.runOnMainSync(() -> {
+ mActivity.getWindow().addPrivateFlags(PRIVATE_FLAG_TRUSTED_OVERLAY);
+ View rootView = mActivity.getWindow().getDecorView();
+ if (rootView.isAttachedToWindow()) {
+ tokens[0] = rootView.getWindowToken();
+ hostTokenReady.countDown();
+ } else {
+ rootView.getViewTreeObserver().addOnWindowAttachListener(
+ new ViewTreeObserver.OnWindowAttachListener() {
+ @Override
+ public void onWindowAttached() {
+ tokens[0] = rootView.getWindowToken();
+ hostTokenReady.countDown();
+ }
+
+ @Override
+ public void onWindowDetached() {
+ }
+ });
+ }
+ });
+
+ assertTrue("Failed to wait for host to get added",
+ hostTokenReady.await(TIMEOUT_S, TimeUnit.SECONDS));
+
+ mInstrumentation.runOnMainSync(() -> {
+ WindowManager wm = mActivity.getSystemService(WindowManager.class);
+
+ View childView = new View(mActivity) {
+ @Override
+ protected void onAttachedToWindow() {
+ super.onAttachedToWindow();
+ tokens[1] = getWindowToken();
+ }
+ };
+ WindowManager.LayoutParams params = new WindowManager.LayoutParams();
+ params.token = tokens[0];
+ params.type = TYPE_APPLICATION_PANEL;
+ wm.addView(childView, params);
+ });
+
+ boolean[] foundTrusted = new boolean[2];
+
+ CtsWindowInfoUtils.waitForWindowInfos(
+ windowInfos -> {
+ for (var windowInfo : windowInfos) {
+ if (windowInfo.windowToken == tokens[0]
+ && windowInfo.isTrustedOverlay) {
+ foundTrusted[0] = true;
+ } else if (windowInfo.windowToken == tokens[1]
+ && windowInfo.isTrustedOverlay) {
+ foundTrusted[1] = true;
+ }
+ }
+ return foundTrusted[0] && foundTrusted[1];
+ }, TIMEOUT_S, TimeUnit.SECONDS);
+
+ if (!foundTrusted[0] || !foundTrusted[1]) {
+ CtsWindowInfoUtils.dumpWindowsOnScreen(TAG, mName.getMethodName());
+ }
+
+ assertTrue("Failed to find parent window or was not marked trusted", foundTrusted[0]);
+ assertEquals("Failed to find child window or was not marked trusted", expectedTrustedChild,
+ foundTrusted[1]);
+ }
+}
diff --git a/services/usage/java/com/android/server/usage/UsageStatsHandlerThread.java b/services/usage/java/com/android/server/usage/UsageStatsHandlerThread.java
deleted file mode 100644
index 6801c94..0000000
--- a/services/usage/java/com/android/server/usage/UsageStatsHandlerThread.java
+++ /dev/null
@@ -1,80 +0,0 @@
-/*
- * Copyright (C) 2023 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.server.usage;
-
-import android.os.Handler;
-import android.os.HandlerExecutor;
-import android.os.HandlerThread;
-import android.os.Looper;
-import android.os.Process;
-import android.os.Trace;
-
-import java.util.concurrent.Executor;
-
-/**
- * Shared singleton default priority thread for usage stats message handling.
- *
- * @see com.android.internal.os.BackgroundThread
- */
-public final class UsageStatsHandlerThread extends HandlerThread {
- private static final long SLOW_DISPATCH_THRESHOLD_MS = 10_000;
- private static final long SLOW_DELIVERY_THRESHOLD_MS = 30_000;
- private static UsageStatsHandlerThread sInstance;
- private static Handler sHandler;
- private static Executor sHandlerExecutor;
-
- private UsageStatsHandlerThread() {
- super("usagestats.default", Process.THREAD_PRIORITY_DEFAULT);
- }
-
- private static void ensureThreadLocked() {
- if (sInstance == null) {
- sInstance = new UsageStatsHandlerThread();
- sInstance.start();
- final Looper looper = sInstance.getLooper();
- looper.setTraceTag(Trace.TRACE_TAG_SYSTEM_SERVER);
- looper.setSlowLogThresholdMs(
- SLOW_DISPATCH_THRESHOLD_MS, SLOW_DELIVERY_THRESHOLD_MS);
- sHandler = new Handler(sInstance.getLooper());
- sHandlerExecutor = new HandlerExecutor(sHandler);
- }
- }
-
- /** Returns the UsageStatsHandlerThread singleton */
- public static UsageStatsHandlerThread get() {
- synchronized (UsageStatsHandlerThread.class) {
- ensureThreadLocked();
- return sInstance;
- }
- }
-
- /** Returns the singleton handler for UsageStatsHandlerThread */
- public static Handler getHandler() {
- synchronized (UsageStatsHandlerThread.class) {
- ensureThreadLocked();
- return sHandler;
- }
- }
-
- /** Returns the singleton handler executor for UsageStatsHandlerThread */
- public static Executor getExecutor() {
- synchronized (UsageStatsHandlerThread.class) {
- ensureThreadLocked();
- return sHandlerExecutor;
- }
- }
-}
diff --git a/services/usage/java/com/android/server/usage/UsageStatsService.java b/services/usage/java/com/android/server/usage/UsageStatsService.java
index 18c960e..f3bf026 100644
--- a/services/usage/java/com/android/server/usage/UsageStatsService.java
+++ b/services/usage/java/com/android/server/usage/UsageStatsService.java
@@ -332,8 +332,7 @@
mUserManager = (UserManager) getContext().getSystemService(Context.USER_SERVICE);
mPackageManager = getContext().getPackageManager();
mPackageManagerInternal = LocalServices.getService(PackageManagerInternal.class);
-
- mHandler = new H(UsageStatsHandlerThread.get().getLooper());
+ mHandler = new H(BackgroundThread.get().getLooper());
mIoHandler = new Handler(IoThread.get().getLooper(), mIoHandlerCallback);
mAppStandby = mInjector.getAppStandbyController(getContext());
@@ -495,9 +494,12 @@
Trace.traceBegin(Trace.TRACE_TAG_SYSTEM_SERVER, "loadPendingEvents");
loadPendingEventsLocked(userId, pendingEvents);
Trace.traceEnd(Trace.TRACE_TAG_SYSTEM_SERVER);
- final LinkedList<Event> eventsInMem = mReportedEvents.get(userId);
- if (eventsInMem != null) {
- pendingEvents.addAll(eventsInMem);
+ synchronized (mReportedEvents) {
+ final LinkedList<Event> eventsInMem = mReportedEvents.get(userId);
+ if (eventsInMem != null) {
+ pendingEvents.addAll(eventsInMem);
+ mReportedEvents.remove(userId);
+ }
}
boolean needToFlush = !pendingEvents.isEmpty();
@@ -518,8 +520,7 @@
mIoHandler.obtainMessage(MSG_HANDLE_LAUNCH_TIME_ON_USER_UNLOCK,
userId, 0).sendToTarget();
- // Remove all the stats stored in memory and in system DE.
- mReportedEvents.remove(userId);
+ // Remove all the stats stored in system DE.
deleteRecursively(new File(Environment.getDataSystemDeDirectory(userId), "usagestats"));
// Force a flush to disk for the current user to ensure important events are persisted.
@@ -916,6 +917,7 @@
}
}
+ @GuardedBy({"mLock", "mReportedEvents"})
private void persistPendingEventsLocked(int userId) {
final LinkedList<Event> pendingEvents = mReportedEvents.get(userId);
if (pendingEvents == null || pendingEvents.isEmpty()) {
@@ -1019,7 +1021,7 @@
+ UserUsageStatsService.eventToString(event.mEventType);
Trace.traceBegin(Trace.TRACE_TAG_SYSTEM_SERVER, traceTag);
}
- synchronized (mLock) {
+ synchronized (mReportedEvents) {
LinkedList<Event> events = mReportedEvents.get(userId);
if (events == null) {
events = new LinkedList<>();
@@ -1943,16 +1945,19 @@
idpw.println();
}
} else {
- final LinkedList<Event> pendingEvents = mReportedEvents.get(userId);
- if (pendingEvents != null && !pendingEvents.isEmpty()) {
- final int eventCount = pendingEvents.size();
- idpw.println("Pending events: count=" + eventCount);
- idpw.increaseIndent();
- for (int idx = 0; idx < eventCount; idx++) {
- UserUsageStatsService.printEvent(idpw, pendingEvents.get(idx), true);
+ synchronized (mReportedEvents) {
+ final LinkedList<Event> pendingEvents = mReportedEvents.get(userId);
+ if (pendingEvents != null && !pendingEvents.isEmpty()) {
+ final int eventCount = pendingEvents.size();
+ idpw.println("Pending events: count=" + eventCount);
+ idpw.increaseIndent();
+ for (int idx = 0; idx < eventCount; idx++) {
+ UserUsageStatsService.printEvent(idpw, pendingEvents.get(idx),
+ true);
+ }
+ idpw.decreaseIndent();
+ idpw.println();
}
- idpw.decreaseIndent();
- idpw.println();
}
}
idpw.decreaseIndent();
diff --git a/tests/BatteryStatsPerfTest/Android.bp b/tests/BatteryStatsPerfTest/Android.bp
index 5233a5b..c2a7015 100644
--- a/tests/BatteryStatsPerfTest/Android.bp
+++ b/tests/BatteryStatsPerfTest/Android.bp
@@ -27,7 +27,7 @@
static_libs: [
"androidx.test.rules",
"apct-perftests-utils",
- "truth-prebuilt",
+ "truth",
],
platform_apis: true,
certificate: "platform",
diff --git a/tests/BinaryTransparencyHostTest/Android.bp b/tests/BinaryTransparencyHostTest/Android.bp
index 615990f..38cb9869 100644
--- a/tests/BinaryTransparencyHostTest/Android.bp
+++ b/tests/BinaryTransparencyHostTest/Android.bp
@@ -30,7 +30,7 @@
"compatibility-host-util",
],
static_libs: [
- "truth-prebuilt",
+ "truth",
],
data: [
":BinaryTransparencyTestApp",
diff --git a/tests/BlobStoreTestUtils/Android.bp b/tests/BlobStoreTestUtils/Android.bp
index c4faf7f..1fb73e2 100644
--- a/tests/BlobStoreTestUtils/Android.bp
+++ b/tests/BlobStoreTestUtils/Android.bp
@@ -22,12 +22,12 @@
}
java_library {
- name: "BlobStoreTestUtils",
- srcs: ["src/**/*.java"],
- static_libs: [
- "truth-prebuilt",
- "androidx.test.uiautomator_uiautomator",
- "androidx.test.ext.junit",
- ],
- sdk_version: "test_current",
+ name: "BlobStoreTestUtils",
+ srcs: ["src/**/*.java"],
+ static_libs: [
+ "truth",
+ "androidx.test.uiautomator_uiautomator",
+ "androidx.test.ext.junit",
+ ],
+ sdk_version: "test_current",
}
diff --git a/tests/ChoreographerTests/Android.bp b/tests/ChoreographerTests/Android.bp
index ca30267..5d49120 100644
--- a/tests/ChoreographerTests/Android.bp
+++ b/tests/ChoreographerTests/Android.bp
@@ -34,7 +34,7 @@
"androidx.test.rules",
"compatibility-device-util-axt",
"com.google.android.material_material",
- "truth-prebuilt",
+ "truth",
],
jni_libs: [
"libchoreographertests_jni",
diff --git a/tests/CtsSurfaceControlTestsStaging/Android.bp b/tests/CtsSurfaceControlTestsStaging/Android.bp
index 6809521..96e4a9e 100644
--- a/tests/CtsSurfaceControlTestsStaging/Android.bp
+++ b/tests/CtsSurfaceControlTestsStaging/Android.bp
@@ -37,7 +37,7 @@
"compatibility-device-util-axt",
"com.google.android.material_material",
"SurfaceFlingerProperties",
- "truth-prebuilt",
+ "truth",
],
resource_dirs: ["src/main/res"],
certificate: "platform",
diff --git a/tests/DynamicCodeLoggerIntegrationTests/Android.bp b/tests/DynamicCodeLoggerIntegrationTests/Android.bp
index 448d46f..3f2c808 100644
--- a/tests/DynamicCodeLoggerIntegrationTests/Android.bp
+++ b/tests/DynamicCodeLoggerIntegrationTests/Android.bp
@@ -47,7 +47,7 @@
static_libs: [
"androidx.test.rules",
- "truth-prebuilt",
+ "truth",
],
compile_multilib: "both",
diff --git a/tests/FlickerTests/Android.bp b/tests/FlickerTests/Android.bp
index a2ae56e..82aa85d 100644
--- a/tests/FlickerTests/Android.bp
+++ b/tests/FlickerTests/Android.bp
@@ -236,7 +236,7 @@
static_libs: [
"flickerlib",
"flickerlib-helpers",
- "truth-prebuilt",
+ "truth",
"app-helpers-core",
],
}
@@ -255,7 +255,7 @@
"flickerlib",
"flickerlib-apphelpers",
"flickerlib-helpers",
- "truth-prebuilt",
+ "truth",
"app-helpers-core",
"wm-flicker-window-extensions",
],
diff --git a/tests/FsVerityTest/TEST_MAPPING b/tests/FsVerityTest/TEST_MAPPING
index 39944be..7d59d77 100644
--- a/tests/FsVerityTest/TEST_MAPPING
+++ b/tests/FsVerityTest/TEST_MAPPING
@@ -1,12 +1,7 @@
{
- "postsubmit": [
+ "presubmit": [
{
"name": "FsVerityTest"
- },
- // nextgen test only runs during postsubmit.
- {
- "name": "FsVerityTest",
- "keywords": ["nextgen"]
}
]
}
diff --git a/tests/Input/Android.bp b/tests/Input/Android.bp
index 365e00e..f910b8b 100644
--- a/tests/Input/Android.bp
+++ b/tests/Input/Android.bp
@@ -35,7 +35,7 @@
"services.core.unboosted",
"testables",
"testng",
- "truth-prebuilt",
+ "truth",
],
libs: [
"android.test.mock",
diff --git a/tests/Input/src/com/android/server/input/FocusEventDebugViewTest.java b/tests/Input/src/com/android/server/input/FocusEventDebugViewTest.java
deleted file mode 100644
index 1b98887..0000000
--- a/tests/Input/src/com/android/server/input/FocusEventDebugViewTest.java
+++ /dev/null
@@ -1,135 +0,0 @@
-/*
- * Copyright 2023 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.server.input;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertNotNull;
-import static org.junit.Assert.assertNull;
-import static org.junit.Assert.assertTrue;
-import static org.mockito.Mockito.anyInt;
-import static org.mockito.Mockito.anyString;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.when;
-
-import android.content.Context;
-import android.view.InputChannel;
-import android.view.InputDevice;
-import android.view.MotionEvent;
-import android.view.MotionEvent.PointerCoords;
-import android.view.MotionEvent.PointerProperties;
-import android.view.ViewConfiguration;
-
-import androidx.test.InstrumentationRegistry;
-import androidx.test.runner.AndroidJUnit4;
-
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-
-/**
- * Build/Install/Run:
- * atest FocusEventDebugViewTest
- */
-@RunWith(AndroidJUnit4.class)
-public class FocusEventDebugViewTest {
-
- private FocusEventDebugView mFocusEventDebugView;
- private FocusEventDebugView.RotaryInputValueView mRotaryInputValueView;
- private FocusEventDebugView.RotaryInputGraphView mRotaryInputGraphView;
- private float mScaledVerticalScrollFactor;
-
- @Before
- public void setUp() throws Exception {
- Context context = InstrumentationRegistry.getContext();
- mScaledVerticalScrollFactor =
- ViewConfiguration.get(context).getScaledVerticalScrollFactor();
- InputManagerService mockService = mock(InputManagerService.class);
- when(mockService.monitorInput(anyString(), anyInt()))
- .thenReturn(InputChannel.openInputChannelPair("FocusEventDebugViewTest")[1]);
-
- mRotaryInputValueView = new FocusEventDebugView.RotaryInputValueView(context);
- mRotaryInputGraphView = new FocusEventDebugView.RotaryInputGraphView(context);
- mFocusEventDebugView = new FocusEventDebugView(context, mockService,
- () -> mRotaryInputValueView, () -> mRotaryInputGraphView);
- }
-
- @Test
- public void startsRotaryInputValueViewWithDefaultValue() {
- assertEquals("+0.0", mRotaryInputValueView.getText());
- }
-
- @Test
- public void startsRotaryInputGraphViewWithDefaultFrameCenter() {
- assertEquals(0, mRotaryInputGraphView.getFrameCenterPosition(), 0.01);
- }
-
- @Test
- public void handleRotaryInput_updatesRotaryInputValueViewWithScrollValue() {
- mFocusEventDebugView.handleUpdateShowRotaryInput(true);
-
- mFocusEventDebugView.handleRotaryInput(createRotaryMotionEvent(0.5f));
-
- assertEquals(String.format("+%.1f", 0.5f * mScaledVerticalScrollFactor),
- mRotaryInputValueView.getText());
- }
-
- @Test
- public void handleRotaryInput_translatesRotaryInputGraphViewWithHighScrollValue() {
- mFocusEventDebugView.handleUpdateShowRotaryInput(true);
-
- mFocusEventDebugView.handleRotaryInput(createRotaryMotionEvent(1000f));
-
- assertTrue(mRotaryInputGraphView.getFrameCenterPosition() > 0);
- }
-
- @Test
- public void updateActivityStatus_setsAndRemovesColorFilter() {
- // It should not be active initially.
- assertNull(mRotaryInputValueView.getBackground().getColorFilter());
-
- mRotaryInputValueView.updateActivityStatus(true);
- // It should be active after rotary input.
- assertNotNull(mRotaryInputValueView.getBackground().getColorFilter());
-
- mRotaryInputValueView.updateActivityStatus(false);
- // It should not be active after waiting for mUpdateActivityStatusCallback.
- assertNull(mRotaryInputValueView.getBackground().getColorFilter());
- }
-
- private MotionEvent createRotaryMotionEvent(float scrollAxisValue) {
- PointerCoords pointerCoords = new PointerCoords();
- pointerCoords.setAxisValue(MotionEvent.AXIS_SCROLL, scrollAxisValue);
- PointerProperties pointerProperties = new PointerProperties();
-
- return MotionEvent.obtain(
- /* downTime */ 0,
- /* eventTime */ 0,
- /* action */ MotionEvent.ACTION_SCROLL,
- /* pointerCount */ 1,
- /* pointerProperties */ new PointerProperties[] {pointerProperties},
- /* pointerCoords */ new PointerCoords[] {pointerCoords},
- /* metaState */ 0,
- /* buttonState */ 0,
- /* xPrecision */ 0,
- /* yPrecision */ 0,
- /* deviceId */ 0,
- /* edgeFlags */ 0,
- /* source */ InputDevice.SOURCE_ROTARY_ENCODER,
- /* flags */ 0
- );
- }
-}
diff --git a/tests/Input/src/com/android/server/input/debug/FocusEventDebugViewTest.java b/tests/Input/src/com/android/server/input/debug/FocusEventDebugViewTest.java
new file mode 100644
index 0000000..ae7fb3b
--- /dev/null
+++ b/tests/Input/src/com/android/server/input/debug/FocusEventDebugViewTest.java
@@ -0,0 +1,111 @@
+/*
+ * Copyright 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.input.debug;
+
+import static org.mockito.Mockito.anyFloat;
+import static org.mockito.Mockito.anyInt;
+import static org.mockito.Mockito.anyLong;
+import static org.mockito.Mockito.anyString;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import android.content.Context;
+import android.view.InputChannel;
+import android.view.InputDevice;
+import android.view.MotionEvent;
+import android.view.MotionEvent.PointerCoords;
+import android.view.MotionEvent.PointerProperties;
+
+import androidx.test.InstrumentationRegistry;
+import androidx.test.runner.AndroidJUnit4;
+
+import com.android.server.input.InputManagerService;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+/**
+ * Build/Install/Run:
+ * atest FocusEventDebugViewTest
+ */
+@RunWith(AndroidJUnit4.class)
+public class FocusEventDebugViewTest {
+
+ private FocusEventDebugView mFocusEventDebugView;
+ private RotaryInputValueView mRotaryInputValueView;
+ private RotaryInputGraphView mRotaryInputGraphView;
+
+ @Before
+ public void setUp() throws Exception {
+ Context context = InstrumentationRegistry.getContext();
+ InputManagerService mockService = mock(InputManagerService.class);
+ when(mockService.monitorInput(anyString(), anyInt()))
+ .thenReturn(InputChannel.openInputChannelPair("FocusEventDebugViewTest")[1]);
+
+ mRotaryInputValueView = spy(new RotaryInputValueView(context));
+ mRotaryInputGraphView = spy(new RotaryInputGraphView(context));
+ mFocusEventDebugView = new FocusEventDebugView(context, mockService,
+ () -> mRotaryInputValueView, () -> mRotaryInputGraphView);
+ }
+
+ @Test
+ public void handleRotaryInput_sendsMotionEventWhenEnabled() {
+ mFocusEventDebugView.handleUpdateShowRotaryInput(true);
+
+ mFocusEventDebugView.handleRotaryInput(createRotaryMotionEvent(0.5f, 10L));
+
+ verify(mRotaryInputGraphView).addValue(0.5f, 10L);
+ verify(mRotaryInputValueView).updateValue(0.5f);
+ }
+
+ @Test
+ public void handleRotaryInput_doesNotSendMotionEventWhenDisabled() {
+ mFocusEventDebugView.handleUpdateShowRotaryInput(false);
+
+ mFocusEventDebugView.handleRotaryInput(createRotaryMotionEvent(0.5f, 10L));
+
+ verify(mRotaryInputGraphView, never()).addValue(anyFloat(), anyLong());
+ verify(mRotaryInputValueView, never()).updateValue(anyFloat());
+ }
+
+ private MotionEvent createRotaryMotionEvent(float scrollAxisValue, long eventTime) {
+ PointerCoords pointerCoords = new PointerCoords();
+ pointerCoords.setAxisValue(MotionEvent.AXIS_SCROLL, scrollAxisValue);
+ PointerProperties pointerProperties = new PointerProperties();
+
+ return MotionEvent.obtain(
+ /* downTime */ 0,
+ /* eventTime */ eventTime,
+ /* action */ MotionEvent.ACTION_SCROLL,
+ /* pointerCount */ 1,
+ /* pointerProperties */ new PointerProperties[] {pointerProperties},
+ /* pointerCoords */ new PointerCoords[] {pointerCoords},
+ /* metaState */ 0,
+ /* buttonState */ 0,
+ /* xPrecision */ 0,
+ /* yPrecision */ 0,
+ /* deviceId */ 0,
+ /* edgeFlags */ 0,
+ /* source */ InputDevice.SOURCE_ROTARY_ENCODER,
+ /* flags */ 0
+ );
+ }
+}
diff --git a/tests/Input/src/com/android/server/input/debug/RotaryInputGraphViewTest.java b/tests/Input/src/com/android/server/input/debug/RotaryInputGraphViewTest.java
new file mode 100644
index 0000000..af6ece4
--- /dev/null
+++ b/tests/Input/src/com/android/server/input/debug/RotaryInputGraphViewTest.java
@@ -0,0 +1,61 @@
+/*
+ * Copyright 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.input.debug;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+
+import android.content.Context;
+
+import androidx.test.InstrumentationRegistry;
+import androidx.test.runner.AndroidJUnit4;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+/**
+ * Build/Install/Run:
+ * atest RotaryInputGraphViewTest
+ */
+@RunWith(AndroidJUnit4.class)
+public class RotaryInputGraphViewTest {
+
+ private RotaryInputGraphView mRotaryInputGraphView;
+
+ @Before
+ public void setUp() throws Exception {
+ Context context = InstrumentationRegistry.getContext();
+
+ mRotaryInputGraphView = new RotaryInputGraphView(context);
+ }
+
+ @Test
+ public void startsWithDefaultFrameCenter() {
+ assertEquals(0, mRotaryInputGraphView.getFrameCenterPosition(), 0.01);
+ }
+
+ @Test
+ public void addValue_translatesRotaryInputGraphViewWithHighScrollValue() {
+ final float scrollAxisValue = 1000f;
+ final long eventTime = 0;
+
+ mRotaryInputGraphView.addValue(scrollAxisValue, eventTime);
+
+ assertTrue(mRotaryInputGraphView.getFrameCenterPosition() > 0);
+ }
+}
diff --git a/tests/Input/src/com/android/server/input/debug/RotaryInputValueViewTest.java b/tests/Input/src/com/android/server/input/debug/RotaryInputValueViewTest.java
new file mode 100644
index 0000000..e5e3852
--- /dev/null
+++ b/tests/Input/src/com/android/server/input/debug/RotaryInputValueViewTest.java
@@ -0,0 +1,85 @@
+/*
+ * Copyright 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.input.debug;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+
+import android.content.Context;
+import android.view.ViewConfiguration;
+
+import androidx.test.InstrumentationRegistry;
+import androidx.test.runner.AndroidJUnit4;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.util.Locale;
+
+/**
+ * Build/Install/Run:
+ * atest RotaryInputValueViewTest
+ */
+@RunWith(AndroidJUnit4.class)
+public class RotaryInputValueViewTest {
+
+ private final Locale mDefaultLocale = Locale.getDefault();
+
+ private RotaryInputValueView mRotaryInputValueView;
+ private float mScaledVerticalScrollFactor;
+
+ @Before
+ public void setUp() throws Exception {
+ Context context = InstrumentationRegistry.getContext();
+ mScaledVerticalScrollFactor =
+ ViewConfiguration.get(context).getScaledVerticalScrollFactor();
+
+ mRotaryInputValueView = new RotaryInputValueView(context);
+ }
+
+ @Test
+ public void startsWithDefaultValue() {
+ assertEquals("+0.0", mRotaryInputValueView.getText().toString());
+ }
+
+ @Test
+ public void updateValue_updatesTextWithScrollValue() {
+ final float scrollAxisValue = 1000f;
+ final String expectedText = String.format(mDefaultLocale, "+%.1f",
+ scrollAxisValue * mScaledVerticalScrollFactor);
+
+ mRotaryInputValueView.updateValue(scrollAxisValue);
+
+ assertEquals(expectedText, mRotaryInputValueView.getText().toString());
+ }
+
+ @Test
+ public void updateActivityStatus_setsAndRemovesColorFilter() {
+ // It should not be active initially.
+ assertNull(mRotaryInputValueView.getBackground().getColorFilter());
+
+ mRotaryInputValueView.updateActivityStatus(true);
+ // It should be active after rotary input.
+ assertNotNull(mRotaryInputValueView.getBackground().getColorFilter());
+
+ mRotaryInputValueView.updateActivityStatus(false);
+ // It should not be active after waiting for mUpdateActivityStatusCallback.
+ assertNull(mRotaryInputValueView.getBackground().getColorFilter());
+ }
+}
diff --git a/tests/InputMethodStressTest/Android.bp b/tests/InputMethodStressTest/Android.bp
index 84845c6..58ceb3f 100644
--- a/tests/InputMethodStressTest/Android.bp
+++ b/tests/InputMethodStressTest/Android.bp
@@ -26,7 +26,7 @@
"compatibility-device-util-axt",
"platform-test-annotations",
"platform-test-rules",
- "truth-prebuilt",
+ "truth",
],
test_suites: [
"general-tests",
diff --git a/tests/InputScreenshotTest/Android.bp b/tests/InputScreenshotTest/Android.bp
index eee486f..15aaa46 100644
--- a/tests/InputScreenshotTest/Android.bp
+++ b/tests/InputScreenshotTest/Android.bp
@@ -29,7 +29,7 @@
"androidx.lifecycle_lifecycle-livedata-ktx",
"androidx.lifecycle_lifecycle-runtime-compose",
"androidx.navigation_navigation-compose",
- "truth-prebuilt",
+ "truth",
"androidx.compose.runtime_runtime",
"androidx.test.core",
"androidx.test.ext.junit",
@@ -47,7 +47,7 @@
"services.core.unboosted",
"testables",
"testng",
- "truth-prebuilt",
+ "truth",
],
libs: [
"android.test.mock",
diff --git a/tests/Internal/Android.bp b/tests/Internal/Android.bp
index ef45864..ddec8fa 100644
--- a/tests/Internal/Android.bp
+++ b/tests/Internal/Android.bp
@@ -19,7 +19,7 @@
"junit",
"androidx.test.rules",
"mockito-target-minus-junit4",
- "truth-prebuilt",
+ "truth",
"platform-test-annotations",
],
java_resource_dirs: ["res"],
diff --git a/tests/LocalizationTest/Android.bp b/tests/LocalizationTest/Android.bp
index 4e0b0a8..909ca59 100644
--- a/tests/LocalizationTest/Android.bp
+++ b/tests/LocalizationTest/Android.bp
@@ -34,7 +34,7 @@
"androidx.test.ext.junit",
"androidx.test.rules",
"mockito-target-extended-minus-junit4",
- "truth-prebuilt",
+ "truth",
],
jni_libs: [
// For mockito extended
diff --git a/tests/MidiTests/Android.bp b/tests/MidiTests/Android.bp
index 254770d..fcacab3 100644
--- a/tests/MidiTests/Android.bp
+++ b/tests/MidiTests/Android.bp
@@ -31,7 +31,7 @@
"mockito-target-inline-minus-junit4",
"platform-test-annotations",
"services.midi",
- "truth-prebuilt",
+ "truth",
],
jni_libs: ["libdexmakerjvmtiagent"],
certificate: "platform",
diff --git a/tests/PackageWatchdog/Android.bp b/tests/PackageWatchdog/Android.bp
index 1e1dc84..e0e6c4c 100644
--- a/tests/PackageWatchdog/Android.bp
+++ b/tests/PackageWatchdog/Android.bp
@@ -32,7 +32,7 @@
"androidx.test.rules",
"services.core",
"services.net",
- "truth-prebuilt",
+ "truth",
],
libs: ["android.test.runner"],
jni_libs: [
diff --git a/tests/PlatformCompatGating/Android.bp b/tests/PlatformCompatGating/Android.bp
index f0f9c4b..fd992cf 100644
--- a/tests/PlatformCompatGating/Android.bp
+++ b/tests/PlatformCompatGating/Android.bp
@@ -38,7 +38,7 @@
"androidx.test.ext.junit",
"mockito-target-minus-junit4",
"testng",
- "truth-prebuilt",
+ "truth",
"platform-compat-test-rules",
],
}
diff --git a/tests/PlatformCompatGating/test-rules/Android.bp b/tests/PlatformCompatGating/test-rules/Android.bp
index 5f91f9d0..f6a41c2 100644
--- a/tests/PlatformCompatGating/test-rules/Android.bp
+++ b/tests/PlatformCompatGating/test-rules/Android.bp
@@ -29,7 +29,7 @@
static_libs: [
"junit",
"androidx.test.core",
- "truth-prebuilt",
- "core-compat-test-rules"
+ "truth",
+ "core-compat-test-rules",
],
}
diff --git a/tests/SurfaceViewBufferTests/Android.bp b/tests/SurfaceViewBufferTests/Android.bp
index 38313f8..055d625 100644
--- a/tests/SurfaceViewBufferTests/Android.bp
+++ b/tests/SurfaceViewBufferTests/Android.bp
@@ -45,7 +45,7 @@
"kotlinx-coroutines-android",
"flickerlib",
"flickerlib-trace_processor_shell",
- "truth-prebuilt",
+ "truth",
"cts-wm-util",
"CtsSurfaceValidatorLib",
],
diff --git a/tests/TaskOrganizerTest/Android.bp b/tests/TaskOrganizerTest/Android.bp
index bf12f42..d2ade34 100644
--- a/tests/TaskOrganizerTest/Android.bp
+++ b/tests/TaskOrganizerTest/Android.bp
@@ -43,6 +43,6 @@
"kotlinx-coroutines-android",
"flickerlib",
"flickerlib-trace_processor_shell",
- "truth-prebuilt",
+ "truth",
],
}
diff --git a/tests/TelephonyCommonTests/Android.bp b/tests/TelephonyCommonTests/Android.bp
index 81ec265..b968e5d 100644
--- a/tests/TelephonyCommonTests/Android.bp
+++ b/tests/TelephonyCommonTests/Android.bp
@@ -32,11 +32,11 @@
static_libs: [
"mockito-target-extended",
"androidx.test.rules",
- "truth-prebuilt",
+ "truth",
"platform-test-annotations",
"androidx.core_core",
"androidx.fragment_fragment",
- "androidx.test.ext.junit"
+ "androidx.test.ext.junit",
],
jni_libs: ["libdexmakerjvmtiagent"],
diff --git a/tests/TrustTests/Android.bp b/tests/TrustTests/Android.bp
index c216bce..4e75a1d 100644
--- a/tests/TrustTests/Android.bp
+++ b/tests/TrustTests/Android.bp
@@ -28,7 +28,7 @@
"flag-junit",
"mockito-target-minus-junit4",
"servicestests-utils",
- "truth-prebuilt",
+ "truth",
],
libs: [
"android.test.runner",
diff --git a/tests/UpdatableSystemFontTest/Android.bp b/tests/UpdatableSystemFontTest/Android.bp
index 9bfcc18..ddb3649 100644
--- a/tests/UpdatableSystemFontTest/Android.bp
+++ b/tests/UpdatableSystemFontTest/Android.bp
@@ -30,7 +30,7 @@
"androidx.test.uiautomator_uiautomator",
"compatibility-device-util-axt",
"platform-test-annotations",
- "truth-prebuilt",
+ "truth",
],
test_suites: [
"general-tests",
diff --git a/tests/UsbManagerTests/Android.bp b/tests/UsbManagerTests/Android.bp
index 97fbf5b..c02d8e9 100644
--- a/tests/UsbManagerTests/Android.bp
+++ b/tests/UsbManagerTests/Android.bp
@@ -31,7 +31,7 @@
"androidx.test.rules",
"mockito-target-inline-minus-junit4",
"platform-test-annotations",
- "truth-prebuilt",
+ "truth",
"UsbManagerTestLib",
],
jni_libs: ["libdexmakerjvmtiagent"],
diff --git a/tests/UsbManagerTests/lib/Android.bp b/tests/UsbManagerTests/lib/Android.bp
index 994484c..4e5a70fe 100644
--- a/tests/UsbManagerTests/lib/Android.bp
+++ b/tests/UsbManagerTests/lib/Android.bp
@@ -34,7 +34,7 @@
"services.core",
"services.net",
"services.usb",
- "truth-prebuilt",
+ "truth",
"androidx.core_core",
],
libs: [
diff --git a/tests/UsbTests/Android.bp b/tests/UsbTests/Android.bp
index c60c519..92c2711 100644
--- a/tests/UsbTests/Android.bp
+++ b/tests/UsbTests/Android.bp
@@ -34,7 +34,7 @@
"services.core",
"services.net",
"services.usb",
- "truth-prebuilt",
+ "truth",
"UsbManagerTestLib",
],
jni_libs: [
diff --git a/tests/componentalias/Android.bp b/tests/componentalias/Android.bp
index 01d34e4..39037f2 100644
--- a/tests/componentalias/Android.bp
+++ b/tests/componentalias/Android.bp
@@ -25,7 +25,7 @@
"androidx.test.rules",
"compatibility-device-util-axt",
"mockito-target-extended-minus-junit4",
- "truth-prebuilt",
+ "truth",
],
libs: ["android.test.base"],
srcs: [
diff --git a/tools/hoststubgen/hoststubgen/test-framework/AndroidHostTest.bp b/tools/hoststubgen/hoststubgen/test-framework/AndroidHostTest.bp
index e7fb2de..b71e5c4 100644
--- a/tools/hoststubgen/hoststubgen/test-framework/AndroidHostTest.bp
+++ b/tools/hoststubgen/hoststubgen/test-framework/AndroidHostTest.bp
@@ -24,7 +24,7 @@
],
static_libs: [
"junit",
- "truth-prebuilt",
+ "truth",
"mockito",
// http://cs/h/googleplex-android/platform/superproject/main/+/main:platform_testing/libraries/annotations/src/android/platform/test/annotations/
diff --git a/tools/hoststubgen/hoststubgen/test-tiny-framework/Android.bp b/tools/hoststubgen/hoststubgen/test-tiny-framework/Android.bp
index 05d6a43..f9dc305 100644
--- a/tools/hoststubgen/hoststubgen/test-tiny-framework/Android.bp
+++ b/tools/hoststubgen/hoststubgen/test-tiny-framework/Android.bp
@@ -104,7 +104,7 @@
],
static_libs: [
"junit",
- "truth-prebuilt",
+ "truth",
// http://cs/h/googleplex-android/platform/superproject/main/+/main:platform_testing/libraries/annotations/src/android/platform/test/annotations/
"platform-test-annotations",
diff --git a/tools/processors/immutability/Android.bp b/tools/processors/immutability/Android.bp
index a7d69039..ecc283b 100644
--- a/tools/processors/immutability/Android.bp
+++ b/tools/processors/immutability/Android.bp
@@ -50,7 +50,7 @@
static_libs: [
"compile-testing-prebuilt",
- "truth-prebuilt",
+ "truth",
"junit",
"kotlin-reflect",
"ImmutabilityAnnotationProcessorHostLibrary",
diff --git a/tools/processors/intdef_mappings/Android.bp b/tools/processors/intdef_mappings/Android.bp
index 7059c52..9c755b7 100644
--- a/tools/processors/intdef_mappings/Android.bp
+++ b/tools/processors/intdef_mappings/Android.bp
@@ -38,7 +38,7 @@
static_libs: [
"compile-testing-prebuilt",
- "truth-prebuilt",
+ "truth",
"junit",
"guava",
"libintdef-annotation-processor",
diff --git a/wifi/tests/Android.bp b/wifi/tests/Android.bp
index 7a29969..5a0f742 100644
--- a/wifi/tests/Android.bp
+++ b/wifi/tests/Android.bp
@@ -40,7 +40,7 @@
"frameworks-base-testutils",
"guava",
"mockito-target-minus-junit4",
- "truth-prebuilt",
+ "truth",
],
libs: [